v.checker: fix multi insts of generics fn with generic struct (#11161)

pull/11155/head^2
yuyi 2021-08-13 03:58:02 +08:00 committed by GitHub
parent 576664e31f
commit 579aa7b1b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 45 additions and 28 deletions

View File

@ -960,7 +960,7 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
unwrapped_struct_type := c.unwrap_generic_type(node.typ, c.table.cur_fn.generic_names, unwrapped_struct_type := c.unwrap_generic_type(node.typ, c.table.cur_fn.generic_names,
c.table.cur_concrete_types) c.table.cur_concrete_types)
c.ensure_type_exists(unwrapped_struct_type, node.pos) or {} c.ensure_type_exists(unwrapped_struct_type, node.pos) or {}
type_sym := c.table.get_type_symbol(unwrapped_struct_type) type_sym := c.table.get_type_symbol(node.typ)
if !c.inside_unsafe && type_sym.kind == .sum_type { if !c.inside_unsafe && type_sym.kind == .sum_type {
c.note('direct sum type init (`x := SumType{}`) will be removed soon', node.pos) c.note('direct sum type init (`x := SumType{}`) will be removed soon', node.pos)
} }
@ -1091,7 +1091,7 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
if is_embed { if is_embed {
expected_type = embed_type expected_type = embed_type
c.expected_type = expected_type c.expected_type = expected_type
expr_type = c.unwrap_generic(c.expr(field.expr)) expr_type = c.expr(field.expr)
expr_type_sym := c.table.get_type_symbol(expr_type) expr_type_sym := c.table.get_type_symbol(expr_type)
if expr_type != ast.void_type && expr_type_sym.kind != .placeholder { if expr_type != ast.void_type && expr_type_sym.kind != .placeholder {
c.check_expected(expr_type, embed_type) or { c.check_expected(expr_type, embed_type) or {
@ -1106,7 +1106,7 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
field_type_sym := c.table.get_type_symbol(field_info.typ) field_type_sym := c.table.get_type_symbol(field_info.typ)
expected_type = field_info.typ expected_type = field_info.typ
c.expected_type = expected_type c.expected_type = expected_type
expr_type = c.unwrap_generic(c.expr(field.expr)) expr_type = c.expr(field.expr)
if !field_info.typ.has_flag(.optional) { if !field_info.typ.has_flag(.optional) {
expr_type = c.check_expr_opt_call(field.expr, expr_type) expr_type = c.check_expr_opt_call(field.expr, expr_type)
} }
@ -1228,7 +1228,7 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
c.error('expression is not an lvalue', node.update_expr.position()) c.error('expression is not an lvalue', node.update_expr.position())
} }
} }
return unwrapped_struct_type return node.typ
} }
fn (mut c Checker) check_div_mod_by_zero(expr ast.Expr, op_kind token.Kind) { fn (mut c Checker) check_div_mod_by_zero(expr ast.Expr, op_kind token.Kind) {

View File

@ -12,3 +12,10 @@ vlib/v/checker/tests/generic_fn_decl_without_generic_names_err.vv:32:1: error: g
| ~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~
33 | println("hi") 33 | println("hi")
34 | } 34 | }
vlib/v/checker/tests/generic_fn_decl_without_generic_names_err.vv:23:9: error: cannot use `Generic` as type `Generic<Concrete>` in return argument
21 | go g_worker(g)
22 |
23 | return g
| ^
24 | }
25 |

View File

@ -5,9 +5,3 @@ vlib/v/checker/tests/generics_fn_return_generic_struct_err.vv:13:32: error: retu
| ~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~
14 | d := GenericChannelStruct{ 14 | d := GenericChannelStruct{
15 | ch: chan T{} 15 | ch: chan T{}
vlib/v/checker/tests/generics_fn_return_generic_struct_err.vv:17:9: error: cannot use `GenericChannelStruct<Simple>` as type `GenericChannelStruct` in return argument
15 | ch: chan T{}
16 | }
17 | return d
| ^
18 | }

View File

@ -16,7 +16,7 @@ fn main() {
} }
pub fn new_channel_struct<T>() GenericChannelStruct<T> { pub fn new_channel_struct<T>() GenericChannelStruct<T> {
d := GenericChannelStruct{ d := GenericChannelStruct<T>{
ch: chan T{} ch: chan T{}
} }

View File

@ -3,7 +3,7 @@ struct Test<T> {
} }
fn get_test<T>(v T) Test<T> { fn get_test<T>(v T) Test<T> {
return Test{ return Test<T>{
v: v v: v
} }
} }

View File

@ -6,7 +6,7 @@ mut:
} }
pub fn new_some<T>(value T) Optional<T> { pub fn new_some<T>(value T) Optional<T> {
return Optional{ return Optional<T>{
value: value value: value
some: true some: true
} }
@ -40,7 +40,7 @@ pub struct Foo {
} }
pub fn (f Foo) new_some<T>(value T) Optional<T> { pub fn (f Foo) new_some<T>(value T) Optional<T> {
return Optional{ return Optional<T>{
value: value value: value
some: true some: true
} }
@ -77,7 +77,7 @@ mut:
} }
pub fn iter<T>(arr []T) ArrayIterator<T> { pub fn iter<T>(arr []T) ArrayIterator<T> {
return ArrayIterator{ return ArrayIterator<T>{
data: arr data: arr
index: 11 index: 11
} }
@ -114,7 +114,7 @@ pub fn (mut i Iterator<T>) next<T>() ?T {
} }
pub fn iter_data<T>(data []T) Iterator<T> { pub fn iter_data<T>(data []T) Iterator<T> {
return Iterator{ return Iterator<T>{
data: data data: data
} }
} }

View File

@ -7,7 +7,7 @@ mut:
} }
pub fn new_some<T, B>(value T, b B) Optional<T> { pub fn new_some<T, B>(value T, b B) Optional<T> {
return Optional{ return Optional<T>{
value: value value: value
some: true some: true
typ: typeof(b).name typ: typeof(b).name
@ -54,7 +54,7 @@ pub struct Foo {
} }
pub fn (f Foo) new_some<T, B>(value T, b B) Optional<T> { pub fn (f Foo) new_some<T, B>(value T, b B) Optional<T> {
return Optional{ return Optional<T>{
value: value value: value
some: true some: true
typ: typeof(b).name typ: typeof(b).name

View File

@ -5,7 +5,7 @@ mut:
} }
fn new_foo<A, B>(a A, b B) Foo<A, B> { fn new_foo<A, B>(a A, b B) Foo<A, B> {
return Foo{ return Foo<A,B>{
a: a a: a
b: b b: b
} }

View File

@ -5,7 +5,7 @@ mut:
} }
fn make_node<T>(val []T) Node<T> { fn make_node<T>(val []T) Node<T> {
return Node{ return Node<T>{
val: val[0] val: val[0]
next: 0 next: 0
} }

View File

@ -3,7 +3,7 @@ struct Foo<T> {
} }
fn new_foo<T>(len int) &Foo<T> { fn new_foo<T>(len int) &Foo<T> {
return &Foo{ return &Foo<T>{
data: []T{len: len} data: []T{len: len}
} }
} }

View File

@ -10,7 +10,7 @@ fn group_new<T>(val ...T) Group<T> {
for i in val { for i in val {
arr << i arr << i
} }
mut g := Group{ mut g := Group<T>{
len: val.len len: val.len
val: arr val: arr
} }

View File

@ -13,11 +13,11 @@ mut:
fn create<T>(arr []T) &List<T> { fn create<T>(arr []T) &List<T> {
assert arr.len > 0 assert arr.len > 0
mut n := &ListNode{ mut n := &ListNode<T>{
val: arr[0] val: arr[0]
next: 0 next: 0
} }
mut l := &List{ mut l := &List<T>{
first: n first: n
last: n last: n
count: 1 count: 1
@ -26,7 +26,23 @@ fn create<T>(arr []T) &List<T> {
} }
fn test_generics_with_generic_structs_init() { fn test_generics_with_generic_structs_init() {
n := create([1, 2, 3]) list1 := create([1, 2, 3])
println(n) println(list1)
assert n.count == 1 assert list1.count == 1
assert list1.first.val == 1
list2 := create(['a', 'b', 'c'])
println(list2)
assert list2.count == 1
assert list2.first.val == 'a'
list3 := create([1.1, 2.2, 3.3])
println(list3)
assert list3.count == 1
assert list3.first.val == 1.1
list4 := create([true, false, true])
println(list4)
assert list4.count == 1
assert list4.first.val == true
} }

View File

@ -17,7 +17,7 @@ fn init_singlylinkedlist<T>(nodes ...Node<T>) SinglyLinkedList<T> {
current_node.next = &nodes[i + 1] current_node.next = &nodes[i + 1]
} }
return SinglyLinkedList{&nodes[0]} return SinglyLinkedList<T>{&nodes[0]}
} }
fn test_generic_with_variadic_generic_args() { fn test_generic_with_variadic_generic_args() {