diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index b11f24f45a..85930d72fc 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -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', 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 { diff --git a/vlib/v/checker/tests/generics_struct_init_type_parameter_count_err.out b/vlib/v/checker/tests/generics_struct_init_type_parameter_count_err.out new file mode 100644 index 0000000000..8884a6c1e9 --- /dev/null +++ b/vlib/v/checker/tests/generics_struct_init_type_parameter_count_err.out @@ -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(res A, b B) string { + 6 | msg := Response{ + | ~~~~~~~~~~~~~~~ + 7 | result: res + 8 | } diff --git a/vlib/v/checker/tests/generics_struct_init_type_parameter_count_err.vv b/vlib/v/checker/tests/generics_struct_init_type_parameter_count_err.vv new file mode 100644 index 0000000000..6d7e98c78d --- /dev/null +++ b/vlib/v/checker/tests/generics_struct_init_type_parameter_count_err.vv @@ -0,0 +1,16 @@ +struct Response { + result U +} + +pub fn send(res A, b B) string { + msg := Response{ + result: res + } + println(b) + return '$msg' +} + +fn main() { + mut ret := send(123, 22.2) + println(ret) +} diff --git a/vlib/v/checker/tests/generics_struct_init_type_parameter_err.out b/vlib/v/checker/tests/generics_struct_init_type_parameter_err.out new file mode 100644 index 0000000000..40df99cfa9 --- /dev/null +++ b/vlib/v/checker/tests/generics_struct_init_type_parameter_err.out @@ -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(res A, b B) string { + 6 | msg := Response{ + | ~~~~~~~~~~~~ + 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(res A, b B) string { + 6 | msg := Response{ + 7 | result: res + | ~~~~~~~~~~~ + 8 | } + 9 | println(b) diff --git a/vlib/v/checker/tests/generics_struct_init_type_parameter_err.vv b/vlib/v/checker/tests/generics_struct_init_type_parameter_err.vv new file mode 100644 index 0000000000..75b9429555 --- /dev/null +++ b/vlib/v/checker/tests/generics_struct_init_type_parameter_err.vv @@ -0,0 +1,16 @@ +struct Response { + result U +} + +pub fn send(res A, b B) string { + msg := Response{ + result: res + } + println(b) + return '$msg' +} + +fn main() { + mut ret := send(123, 22.2) + println(ret) +}