checker: check the arity and the kinds of the type parameters in generic struct inits (#13429)

pull/13440/head
yuyi 2022-02-11 17:21:07 +08:00 committed by GitHub
parent 7f29418c63
commit a21f4563b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 0 deletions

View File

@ -138,6 +138,20 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
} else if node.generic_types.len == 0 {
c.error('generic struct init must specify type parameter, e.g. Foo<T>',
node.pos)
} else if node.generic_types.len > 0
&& node.generic_types.len != struct_sym.info.generic_types.len {
c.error('generic struct init expects $struct_sym.info.generic_types.len generic parameter, but got $node.generic_types.len',
node.pos)
} else if node.generic_types.len > 0 {
for gtyp in node.generic_types {
gtyp_name := c.table.sym(gtyp).name
if gtyp_name !in c.table.cur_fn.generic_names {
cur_generic_names := '(' + c.table.cur_fn.generic_names.join(',') + ')'
c.error('generic struct init type parameter `$gtyp_name` must be within the parameters `$cur_generic_names` of the current generic function',
node.pos)
break
}
}
}
}
if node.generic_types.len > 0 && struct_sym.info.generic_types != node.generic_types {

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/generics_struct_init_type_parameter_count_err.vv:6:9: error: generic struct init expects 1 generic parameter, but got 2
4 |
5 | pub fn send<A, B>(res A, b B) string {
6 | msg := Response<A, B>{
| ~~~~~~~~~~~~~~~
7 | result: res
8 | }

View File

@ -0,0 +1,16 @@
struct Response<U> {
result U
}
pub fn send<A, B>(res A, b B) string {
msg := Response<A, B>{
result: res
}
println(b)
return '$msg'
}
fn main() {
mut ret := send(123, 22.2)
println(ret)
}

View File

@ -0,0 +1,14 @@
vlib/v/checker/tests/generics_struct_init_type_parameter_err.vv:6:9: error: generic struct init type parameter `U` must be within the parameters `(A,B)` of the current generic function
4 |
5 | pub fn send<A, B>(res A, b B) string {
6 | msg := Response<U>{
| ~~~~~~~~~~~~
7 | result: res
8 | }
vlib/v/checker/tests/generics_struct_init_type_parameter_err.vv:7:3: error: cannot assign to field `result`: expected `U`, not `int`
5 | pub fn send<A, B>(res A, b B) string {
6 | msg := Response<U>{
7 | result: res
| ~~~~~~~~~~~
8 | }
9 | println(b)

View File

@ -0,0 +1,16 @@
struct Response<U> {
result U
}
pub fn send<A, B>(res A, b B) string {
msg := Response<U>{
result: res
}
println(b)
return '$msg'
}
fn main() {
mut ret := send(123, 22.2)
println(ret)
}