diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 4ff7b9f639..9866ccfe11 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -8258,6 +8258,25 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { mut v := node.scope.find_var(param.name) or { continue } v.is_auto_heap = true } + if info.generic_types.len > 0 && !param.typ.has_flag(.generic) + && info.concrete_types.len == 0 { + c.error('generic struct in fn declaration must specify the generic type names, e.g. Foo', + param.type_pos) + } + } else if arg_typ_sym.kind == .interface_ { + info := arg_typ_sym.info as ast.Interface + if info.generic_types.len > 0 && !param.typ.has_flag(.generic) + && info.concrete_types.len == 0 { + c.error('generic interface in fn declaration must specify the generic type names, e.g. Foo', + param.type_pos) + } + } else if arg_typ_sym.kind == .sum_type { + info := arg_typ_sym.info as ast.SumType + if info.generic_types.len > 0 && !param.typ.has_flag(.generic) + && info.concrete_types.len == 0 { + c.error('generic sumtype in fn declaration must specify the generic type names, e.g. Foo', + param.type_pos) + } } } if c.pref.translated && node.is_variadic && node.params.len == 1 && param.typ.is_ptr() { @@ -8366,15 +8385,6 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { c.error('missing return at end of function `$node.name`', node.pos) } } - if node.is_method { - sym := c.table.get_type_symbol(node.receiver.typ) - if sym.kind == .struct_ { - info := sym.info as ast.Struct - if info.is_generic && c.table.cur_fn.generic_names.len == 0 { - c.error('receiver must specify the generic type names, e.g. Foo', node.method_type_pos) - } - } - } node.source_file = c.file } diff --git a/vlib/v/checker/tests/generics_fn_arg_type_err.out b/vlib/v/checker/tests/generics_fn_arg_type_err.out new file mode 100644 index 0000000000..b12cac6bee --- /dev/null +++ b/vlib/v/checker/tests/generics_fn_arg_type_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/generics_fn_arg_type_err.vv:14:23: error: generic interface in fn declaration must specify the generic type names, e.g. Foo + 12 | } + 13 | + 14 | fn do_list_thing(list List) { // <--- Error here + | ~~~~ + 15 | // ... + 16 | } diff --git a/vlib/v/checker/tests/generics_fn_arg_type_err.vv b/vlib/v/checker/tests/generics_fn_arg_type_err.vv new file mode 100644 index 0000000000..8df936cfeb --- /dev/null +++ b/vlib/v/checker/tests/generics_fn_arg_type_err.vv @@ -0,0 +1,19 @@ +interface List { +mut: + add(e T) bool +} + +struct LinkedList { + // ... +} + +fn (mut list LinkedList) add(e T) { + // ... +} + +fn do_list_thing(list List) { // <--- Error here + // ... +} + +fn main() { +} diff --git a/vlib/v/checker/tests/generics_method_receiver_type_err.out b/vlib/v/checker/tests/generics_method_receiver_type_err.out index 1a8b84de53..94d6ec41c1 100644 --- a/vlib/v/checker/tests/generics_method_receiver_type_err.out +++ b/vlib/v/checker/tests/generics_method_receiver_type_err.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/generics_method_receiver_type_err.vv:6:11: error: receiver must specify the generic type names, e.g. Foo +vlib/v/checker/tests/generics_method_receiver_type_err.vv:6:11: error: generic struct in fn declaration must specify the generic type names, e.g. Foo 4 | } 5 | 6 | pub fn (x Node) str() string {