@@ -74,7 +74,8 @@ fn (mut c Checker) effective_fn_generic_names(node &ast.FnDecl) []string {
7474 if ! node.is_method {
7575 return []string {}
7676 }
77- if ! node.receiver.typ.has_flag (.generic) && ! c.type_has_unresolved_generic_parts (node.receiver.typ) {
77+ if ! node.receiver.typ.has_flag (.generic)
78+ && ! c.type_has_unresolved_generic_parts (node.receiver.typ) {
7879 return []string {}
7980 }
8081 rec_sym := c.table.sym (c.unwrap_generic (node.receiver.typ))
@@ -89,6 +90,61 @@ fn (mut c Checker) effective_fn_generic_names(node &ast.FnDecl) []string {
8990 return c.table.generic_type_names (node.receiver.typ)
9091}
9192
93+ fn (mut c Checker) receiver_requires_generic_names (node & ast.FnDecl) bool {
94+ if ! node.is_method {
95+ return false
96+ }
97+ return node.receiver.typ.has_flag (.generic)
98+ }
99+
100+ fn (mut c Checker) check_receiver_decl_generic_type_names (node & ast.FnDecl) {
101+ if ! node.is_method {
102+ return
103+ }
104+ receiver_sym := c.table.final_sym (node.receiver.typ)
105+ match receiver_sym.info {
106+ ast.Struct {
107+ if receiver_sym.info.generic_types.len > 0 && ! node.receiver.typ.has_flag (.generic)
108+ && receiver_sym.info.concrete_types.len == 0 {
109+ pure_sym_name := receiver_sym.embed_name ()
110+ c.error ('generic struct `${pure_sym_name} ` in fn declaration must specify the generic type names, e.g. ${pure_sym_name} [T]' ,
111+ node.receiver.type_pos)
112+ }
113+ }
114+ ast.Interface {
115+ if receiver_sym.info.generic_types.len > 0 && ! node.receiver.typ.has_flag (.generic)
116+ && receiver_sym.info.concrete_types.len == 0 {
117+ pure_sym_name := receiver_sym.embed_name ()
118+ c.error ('generic interface `${pure_sym_name} ` in fn declaration must specify the generic type names, e.g. ${pure_sym_name} [T]' ,
119+ node.receiver.type_pos)
120+ }
121+ }
122+ ast.SumType {
123+ if receiver_sym.info.generic_types.len > 0 && ! node.receiver.typ.has_flag (.generic)
124+ && receiver_sym.info.concrete_types.len == 0 {
125+ pure_sym_name := receiver_sym.embed_name ()
126+ c.error ('generic sumtype `${pure_sym_name} ` in fn declaration must specify the generic type names, e.g. ${pure_sym_name} [T]' ,
127+ node.receiver.type_pos)
128+ }
129+ }
130+ else {}
131+ }
132+ }
133+
134+ fn (mut c Checker) check_receiver_decl_generic_name_mentions (node & ast.FnDecl) {
135+ if ! node.is_method || ! node.receiver.typ.has_flag (.generic) {
136+ return
137+ }
138+ generic_names := c.table.generic_type_names (node.receiver.typ)
139+ for name in generic_names {
140+ if name ! in node.generic_names {
141+ fn_generic_names := node.generic_names.join (', ' )
142+ c.error ('generic type name `${name} ` is not mentioned in fn `${node.name} [${fn_generic_names} ]`' ,
143+ node.receiver.type_pos)
144+ }
145+ }
146+ }
147+
92148fn (mut c Checker) fn_decl (mut node ast.FnDecl) {
93149 // handle vls go to definition for method receiver types
94150 if c.pref.is_vls {
@@ -138,9 +194,36 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
138194 }
139195 }
140196 }
197+ mut need_generic_names := false
198+ if node.generic_names.len == 0 {
199+ if node.return_type.has_flag (.generic) {
200+ need_generic_names = true
201+ } else if c.receiver_requires_generic_names (node) {
202+ need_generic_names = true
203+ } else {
204+ for param in node.params {
205+ if param.typ.has_flag (.generic) {
206+ need_generic_names = true
207+ break
208+ }
209+ }
210+ }
211+ if need_generic_names {
212+ if node.is_method {
213+ c.add_error_detail ('use `fn (r SomeType[T]) foo[T]() {`, not just `fn (r SomeType[T]) foo() {`' )
214+ c.error ('generic method declaration must specify generic type names' ,
215+ node.pos)
216+ } else {
217+ c.add_error_detail ('use `fn foo[T](x T) {`, not just `fn foo(x T) {`' )
218+ c.error ('generic function declaration must specify generic type names' ,
219+ node.pos)
220+ }
221+ }
222+ }
223+ c.check_receiver_decl_generic_type_names (node)
224+ c.check_receiver_decl_generic_name_mentions (node)
141225 effective_generic_names := c.effective_fn_generic_names (node)
142- if effective_generic_names.len > 0
143- && c.table.cur_concrete_types.len == 0 {
226+ if effective_generic_names.len > 0 && c.table.cur_concrete_types.len == 0 {
144227 // Just remember the generic function for now.
145228 // It will be processed later in c.post_process_generic_fns,
146229 // after all other normal functions are processed.
@@ -183,30 +266,6 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
183266 c.fn_scope = prev_fn_scope
184267 }
185268 // Check generics fn/method without generic type parameters
186- mut need_generic_names := false
187- if node.generic_names.len == 0 {
188- if node.return_type.has_flag (.generic) {
189- need_generic_names = true
190- } else {
191- for param in node.params {
192- if param.typ.has_flag (.generic) {
193- need_generic_names = true
194- break
195- }
196- }
197- }
198- if need_generic_names {
199- if node.is_method {
200- c.add_error_detail ('use `fn (r SomeType[T]) foo[T]() {`, not just `fn (r SomeType[T]) foo() {`' )
201- c.error ('generic method declaration must specify generic type names' ,
202- node.pos)
203- } else {
204- c.add_error_detail ('use `fn foo[T](x T) {`, not just `fn foo(x T) {`' )
205- c.error ('generic function declaration must specify generic type names' ,
206- node.pos)
207- }
208- }
209- }
210269 if node.language == .v && ! c.is_builtin_mod && ! node.is_anon {
211270 c.check_valid_snake_case (node.get_name (), 'function name' , node.pos)
212271 if ! node.is_method && node.mod == 'main' && node.short_name in c.table.builtin_pub_fns {
@@ -613,7 +672,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
613672 }
614673 c.expected_type = ast.void_type
615674 mut effective_cur_fn := unsafe { node }
616- if c.table.cur_concrete_types.len > 0 && effective_generic_names.len == c.table.cur_concrete_types.len
675+ if c.table.cur_concrete_types.len > 0
676+ && effective_generic_names.len == c.table.cur_concrete_types.len
617677 && node.generic_names != effective_generic_names {
618678 effective_cur_fn = & ast.FnDecl{
619679 ...* node
@@ -2368,10 +2428,12 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool)
23682428 }
23692429 }
23702430 if final_left_sym.kind == .array && array_builtin_methods_chk.matches (method_name)
2371- && (! left_sym.has_method (method_name) || use_builtin_array_sort) {
2431+ && (! (left_sym.kind == .alias && left_sym.has_method (method_name))
2432+ || use_builtin_array_sort) {
23722433 return c.array_builtin_method_call (mut node, left_type)
23732434 } else if final_left_sym.kind == .array_fixed
2374- && fixed_array_builtin_methods_chk.matches (method_name) && ! left_sym.has_method (method_name) {
2435+ && fixed_array_builtin_methods_chk.matches (method_name) && ! (left_sym.kind == .alias
2436+ && left_sym.has_method (method_name)) {
23752437 return c.fixed_array_builtin_method_call (mut node, left_type)
23762438 } else if final_left_sym.kind == .map && node.kind in [.clone, .keys, .values, .move, .delete]
23772439 && ! (left_sym.kind == .alias && left_sym.has_method (method_name)) {
@@ -3169,30 +3231,6 @@ fn (mut c Checker) post_process_generic_fns() ! {
31693231 for concrete_types in gtypes {
31703232 c.table.cur_concrete_types = concrete_types
31713233 mut concrete_fn := c.file.generic_fns[i]
3172- original_generic_names := concrete_fn.generic_names.clone ()
3173- if concrete_fn.is_method && concrete_types.len > original_generic_names.len {
3174- receiver_generic_names := c.table.generic_type_names (concrete_fn.receiver.typ)
3175- if receiver_generic_names.len > 0 {
3176- mut effective_generic_names := []string {cap: receiver_generic_names.len +
3177- original_generic_names.len}
3178- for name in receiver_generic_names {
3179- if name ! in effective_generic_names {
3180- effective_generic_names << name
3181- }
3182- }
3183- for name in original_generic_names {
3184- if name ! in effective_generic_names {
3185- effective_generic_names << name
3186- }
3187- }
3188- if effective_generic_names.len == concrete_types.len {
3189- concrete_fn = & ast.FnDecl{
3190- ...* concrete_fn
3191- generic_names: effective_generic_names
3192- }
3193- }
3194- }
3195- }
31963234 c.fn_decl (mut concrete_fn)
31973235 if concrete_fn.name in ['veb.run' , 'veb.run_at' , 'x.vweb.run' , 'x.vweb.run_at' ,
31983236 'vweb.run' , 'vweb.run_at' ] {
0 commit comments