checker: check generic struct init without type parameter (#10193)
parent
da88235bdc
commit
0e6f0c1de0
|
@ -690,6 +690,14 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) ast.Type {
|
||||||
struct_init.typ = c.expected_type
|
struct_init.typ = c.expected_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
struct_sym := c.table.get_type_symbol(struct_init.typ)
|
||||||
|
if struct_sym.info is ast.Struct {
|
||||||
|
if struct_sym.info.generic_types.len > 0 && struct_sym.info.concrete_types.len == 0
|
||||||
|
&& c.cur_concrete_types.len == 0 {
|
||||||
|
c.error('generic struct init must specify type parameter, e.g. Foo<int>',
|
||||||
|
struct_init.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
utyp := c.unwrap_generic_struct(struct_init.typ, c.table.cur_fn.generic_names, c.cur_concrete_types)
|
utyp := c.unwrap_generic_struct(struct_init.typ, c.table.cur_fn.generic_names, c.cur_concrete_types)
|
||||||
c.ensure_type_exists(utyp, struct_init.pos) or {}
|
c.ensure_type_exists(utyp, struct_init.pos) or {}
|
||||||
type_sym := c.table.get_type_symbol(utyp)
|
type_sym := c.table.get_type_symbol(utyp)
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
vlib/v/checker/tests/generics_struct_init_err.vv:58:8: error: generic struct init must specify type parameter, e.g. Foo<int>
|
||||||
|
56 | ret = holder_call_12(neg, 3)
|
||||||
|
57 | assert ret == -3
|
||||||
|
58 | ret = FnHolder1{neg}.call(4)
|
||||||
|
| ~~~~~~~~~~~~~~
|
||||||
|
59 | assert ret == -4
|
||||||
|
60 |
|
||||||
|
vlib/v/checker/tests/generics_struct_init_err.vv:67:8: error: generic struct init must specify type parameter, e.g. Foo<int>
|
||||||
|
65 | ret = holder_call_22(neg, 5)
|
||||||
|
66 | assert ret == -5
|
||||||
|
67 | ret = FnHolder2{neg}.call(6)
|
||||||
|
| ~~~~~~~~~~~~~~
|
||||||
|
68 | assert ret == -6
|
||||||
|
69 | }
|
|
@ -0,0 +1,69 @@
|
||||||
|
fn neg(a int) int {
|
||||||
|
return -a
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FnHolder1<T> {
|
||||||
|
func T
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (self FnHolder1<T>) call(a int) int {
|
||||||
|
return self.func(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FnHolder2<T> {
|
||||||
|
func fn (int) int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (self FnHolder2<T>) call(a int) int {
|
||||||
|
return self.func(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn holder_call_1<T>(func T, a int) int {
|
||||||
|
h := FnHolder1{func}
|
||||||
|
return h.call(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn holder_call_2<T>(func T, a int) int {
|
||||||
|
h := FnHolder2{func}
|
||||||
|
return h.call(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn holder_call_11<T>(func T, a int) int {
|
||||||
|
f := func
|
||||||
|
h := FnHolder1{f}
|
||||||
|
return h.call(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn holder_call_21<T>(func T, a int) int {
|
||||||
|
f := func
|
||||||
|
h := FnHolder2{f}
|
||||||
|
return h.call(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn holder_call_12<T>(func T, a int) int {
|
||||||
|
return FnHolder1{func}.call(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn holder_call_22<T>(func T, a int) int {
|
||||||
|
return FnHolder2{func}.call(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
mut ret := holder_call_1(neg, 1)
|
||||||
|
assert ret == -1
|
||||||
|
ret = holder_call_11(neg, 2)
|
||||||
|
assert ret == -2
|
||||||
|
ret = holder_call_12(neg, 3)
|
||||||
|
assert ret == -3
|
||||||
|
ret = FnHolder1{neg}.call(4)
|
||||||
|
assert ret == -4
|
||||||
|
|
||||||
|
ret = holder_call_2(neg, 3)
|
||||||
|
assert ret == -3
|
||||||
|
ret = holder_call_21(neg, 4)
|
||||||
|
assert ret == -4
|
||||||
|
ret = holder_call_22(neg, 5)
|
||||||
|
assert ret == -5
|
||||||
|
ret = FnHolder2{neg}.call(6)
|
||||||
|
assert ret == -6
|
||||||
|
}
|
Loading…
Reference in New Issue