v.checker: fix multi insts of generics fn with generic struct (#11161)
parent
576664e31f
commit
579aa7b1b5
|
@ -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) {
|
||||||
|
|
|
@ -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 |
|
||||||
|
|
|
@ -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 | }
|
|
||||||
|
|
|
@ -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{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue