@@ -65,31 +65,32 @@ pub struct Table {
6565mut :
6666 parsing_type string // name of the type to enable recursive type parsing
6767pub mut :
68- type_symbols []& TypeSymbol
69- type_idxs map [string ]int
70- fns map [string ]Fn
71- iface_types map [string ][]Type
72- dumps map [int ]string // needed for efficiently generating all _v_dump_expr_TNAME() functions
73- imports []string // List of all imports
74- modules []string // Topologically sorted list of all modules registered by the application
75- global_scope & Scope = unsafe { nil }
76- cflags []cflag.CFlag
77- redefined_fns []string
78- fn_generic_types map [string ][][]Type // for generic functions
79- interfaces map [int ]InterfaceDecl
80- sumtypes map [int ]SumTypeDecl
81- cmod_prefix string // needed for ast.type_to_str(Type) while vfmt; contains `os.`
82- is_fmt bool
83- used_features & UsedFeatures = & UsedFeatures{} // filled in by the builder via markused module, when pref.skip_unused = true;
84- veb_res_idx_cache int // Cache of `veb.Result` type
85- veb_ctx_idx_cache int // Cache of `veb.Context` type
86- panic_handler FnPanicHandler = default_table_panic_handler
87- panic_userdata voidptr = unsafe { nil } // can be used to pass arbitrary data to panic_handler;
88- panic_npanics int
89- cur_fn & FnDecl = unsafe { nil } // previously stored in Checker.cur_fn and Gen.cur_fn
90- cur_lambda & LambdaExpr = unsafe { nil } // current lambda node
91- cur_concrete_types []Type // current concrete types, e.g. [int, string]
92- gostmts int // how many `go` statements there were in the parsed files.
68+ type_symbols []& TypeSymbol
69+ type_idxs map [string ]int
70+ fns map [string ]Fn
71+ iface_types map [string ][]Type
72+ dumps map [int ]string // needed for efficiently generating all _v_dump_expr_TNAME() functions
73+ imports []string // List of all imports
74+ modules []string // Topologically sorted list of all modules registered by the application
75+ global_scope & Scope = unsafe { nil }
76+ cflags []cflag.CFlag
77+ redefined_fns []string
78+ fn_generic_types map [string ][][]Type // for generic functions
79+ structured_receiver_methods map [string ][]Fn
80+ interfaces map [int ]InterfaceDecl
81+ sumtypes map [int ]SumTypeDecl
82+ cmod_prefix string // needed for ast.type_to_str(Type) while vfmt; contains `os.`
83+ is_fmt bool
84+ used_features & UsedFeatures = & UsedFeatures{} // filled in by the builder via markused module, when pref.skip_unused = true;
85+ veb_res_idx_cache int // Cache of `veb.Result` type
86+ veb_ctx_idx_cache int // Cache of `veb.Context` type
87+ panic_handler FnPanicHandler = default_table_panic_handler
88+ panic_userdata voidptr = unsafe { nil } // can be used to pass arbitrary data to panic_handler;
89+ panic_npanics int
90+ cur_fn & FnDecl = unsafe { nil } // previously stored in Checker.cur_fn and Gen.cur_fn
91+ cur_lambda & LambdaExpr = unsafe { nil } // current lambda node
92+ cur_concrete_types []Type // current concrete types, e.g. [int, string]
93+ gostmts int // how many `go` statements there were in the parsed files.
9394 // When table.gostmts > 0, __VTHREADS__ is defined, which can be checked with `$if threads {`
9495 enum_decls map [string ]EnumDecl
9596 vls_info map [string ]VlsInfo
@@ -390,6 +391,21 @@ pub fn (mut t TypeSymbol) register_method(new_fn Fn) int {
390391 return t.methods.len - 1
391392}
392393
394+ fn receiver_pattern_method_key (parent_idx int , name string ) string {
395+ return '${parent_idx }.${name }'
396+ }
397+
398+ pub fn (mut t Table) register_structured_receiver_method (new_fn Fn) {
399+ if ! t.receiver_type_is_structured_generic_pattern (new_fn.receiver_type) {
400+ return
401+ }
402+ receiver := t.receiver_generic_types (new_fn.receiver_type) or { return }
403+ key := receiver_pattern_method_key (receiver.parent_idx, new_fn.name)
404+ mut methods := t.structured_receiver_methods[key] or { []Fn{} }
405+ methods << new_fn
406+ t.structured_receiver_methods[key] = methods
407+ }
408+
393409pub fn (mut t TypeSymbol) update_method (f Fn) int {
394410 for i, m in t.methods {
395411 if m.name == f.name {
@@ -4085,6 +4101,14 @@ fn (mut t Table) should_auto_register_concrete_method(method Fn, parent_type Typ
40854101 if parent_idx == 0 || method.generic_names.len != concrete_types.len {
40864102 return false
40874103 }
4104+ for concrete_type in concrete_types {
4105+ if t.concrete_type_has_unresolved_generic_parts (concrete_type) {
4106+ return false
4107+ }
4108+ }
4109+ if t.receiver_type_is_structured_generic_pattern (method.receiver_type) {
4110+ return false
4111+ }
40884112 for i in 1 .. method.params.len {
40894113 param := method.params[i]
40904114 mut param_typ := param.typ
@@ -4112,6 +4136,144 @@ fn (mut t Table) should_auto_register_concrete_method(method Fn, parent_type Typ
41124136 return ! t.type_contains_transformed_parent_inst (return_type, parent_idx, concrete_types)
41134137}
41144138
4139+ fn (t &Table) concrete_type_has_unresolved_generic_parts (typ Type) bool {
4140+ if typ == 0 {
4141+ return false
4142+ }
4143+ if typ.has_flag (.generic) {
4144+ return true
4145+ }
4146+ idx := typ.idx ()
4147+ if idx < = nil_type_idx {
4148+ return false
4149+ }
4150+ sym := t.sym (typ)
4151+ if sym.kind == .placeholder || (sym.kind == .any && ! sym.is_builtin ()) {
4152+ return true
4153+ }
4154+ match sym.info {
4155+ Array {
4156+ return t.concrete_type_has_unresolved_generic_parts (sym.info.elem_type)
4157+ }
4158+ ArrayFixed {
4159+ return t.concrete_type_has_unresolved_generic_parts (sym.info.elem_type)
4160+ }
4161+ Chan {
4162+ return t.concrete_type_has_unresolved_generic_parts (sym.info.elem_type)
4163+ }
4164+ Thread {
4165+ return t.concrete_type_has_unresolved_generic_parts (sym.info.return_type)
4166+ }
4167+ Map {
4168+ if t.concrete_type_has_unresolved_generic_parts (sym.info.key_type) {
4169+ return true
4170+ }
4171+ return t.concrete_type_has_unresolved_generic_parts (sym.info.value_type)
4172+ }
4173+ FnType {
4174+ if t.concrete_type_has_unresolved_generic_parts (sym.info.func.return_type) {
4175+ return true
4176+ }
4177+ for param in sym.info.func.params {
4178+ if t.concrete_type_has_unresolved_generic_parts (param.typ) {
4179+ return true
4180+ }
4181+ }
4182+ return false
4183+ }
4184+ MultiReturn {
4185+ for typ_ in sym.info.types {
4186+ if t.concrete_type_has_unresolved_generic_parts (typ_) {
4187+ return true
4188+ }
4189+ }
4190+ return false
4191+ }
4192+ Struct {
4193+ if sym.info.concrete_types.len > 0 {
4194+ for concrete_type in sym.info.concrete_types {
4195+ if t.concrete_type_has_unresolved_generic_parts (concrete_type) {
4196+ return true
4197+ }
4198+ }
4199+ return false
4200+ }
4201+ if sym.generic_types.len == sym.info.generic_types.len
4202+ && sym.generic_types != sym.info.generic_types {
4203+ for generic_type in sym.generic_types {
4204+ if t.concrete_type_has_unresolved_generic_parts (generic_type) {
4205+ return true
4206+ }
4207+ }
4208+ return false
4209+ }
4210+ return sym.info.generic_types.len > 0
4211+ }
4212+ Interface {
4213+ if sym.info.concrete_types.len > 0 {
4214+ for concrete_type in sym.info.concrete_types {
4215+ if t.concrete_type_has_unresolved_generic_parts (concrete_type) {
4216+ return true
4217+ }
4218+ }
4219+ return false
4220+ }
4221+ if sym.generic_types.len == sym.info.generic_types.len
4222+ && sym.generic_types != sym.info.generic_types {
4223+ for generic_type in sym.generic_types {
4224+ if t.concrete_type_has_unresolved_generic_parts (generic_type) {
4225+ return true
4226+ }
4227+ }
4228+ return false
4229+ }
4230+ return sym.info.is_generic
4231+ }
4232+ SumType {
4233+ if sym.info.concrete_types.len > 0 {
4234+ for concrete_type in sym.info.concrete_types {
4235+ if t.concrete_type_has_unresolved_generic_parts (concrete_type) {
4236+ return true
4237+ }
4238+ }
4239+ return false
4240+ }
4241+ if sym.generic_types.len == sym.info.generic_types.len
4242+ && sym.generic_types != sym.info.generic_types {
4243+ for generic_type in sym.generic_types {
4244+ if t.concrete_type_has_unresolved_generic_parts (generic_type) {
4245+ return true
4246+ }
4247+ }
4248+ return false
4249+ }
4250+ return sym.info.is_generic
4251+ }
4252+ GenericInst {
4253+ for concrete_type in sym.info.concrete_types {
4254+ if t.concrete_type_has_unresolved_generic_parts (concrete_type) {
4255+ return true
4256+ }
4257+ }
4258+ return false
4259+ }
4260+ UnknownTypeInfo {
4261+ if sym.name.contains ('[' ) && sym.name.contains (']' ) {
4262+ args := sym.name.all_after ('[' ).trim_right (']' ).split (',' )
4263+ for arg in args {
4264+ if util.is_generic_type_name (arg.trim_space ()) {
4265+ return true
4266+ }
4267+ }
4268+ }
4269+ return false
4270+ }
4271+ else {
4272+ return false
4273+ }
4274+ }
4275+ }
4276+
41154277fn (mut t Table) unwrap_method_types (ts & TypeSymbol, generic_names []string , concrete_types []Type) {
41164278 mut needs_unwrap_types := []Type{}
41174279 for method in ts.get_methods () {
0 commit comments