table: fix generics struct with anon fn fields (#10024)

pull/10029/head
yuyi 2021-05-07 01:24:08 +08:00 committed by GitHub
parent ac2eaa05c7
commit a6764e3cc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 21 deletions

View File

@ -63,30 +63,29 @@ pub fn (t &Table) panic(message string) {
pub struct Fn {
pub:
return_type Type
is_variadic bool
language Language
generic_names []string
is_pub bool
is_deprecated bool // `[deprecated] fn abc(){}`
is_unsafe bool // `[unsafe] fn abc(){}`
is_placeholder bool
is_main bool // `fn main(){}`
is_test bool // `fn test_abc(){}`
is_conditional bool // `[if abc]fn(){}`
is_keep_alive bool // passed memory must not be freed (by GC) before function returns
no_body bool // a pure declaration like `fn abc(x int)`; used in .vh files, C./JS. fns.
mod string
ctdefine string // compile time define. "myflag", when [if myflag] tag
attrs []Attr
//
is_variadic bool
language Language
generic_names []string
is_pub bool
is_deprecated bool // `[deprecated] fn abc(){}`
is_unsafe bool // `[unsafe] fn abc(){}`
is_placeholder bool
is_main bool // `fn main(){}`
is_test bool // `fn test_abc(){}`
is_conditional bool // `[if abc]fn(){}`
is_keep_alive bool // passed memory must not be freed (by GC) before function returns
no_body bool // a pure declaration like `fn abc(x int)`; used in .vh files, C./JS. fns.
mod string
ctdefine string // compile time define. "myflag", when [if myflag] tag
attrs []Attr
pos token.Position
return_type_pos token.Position
pub mut:
name string
params []Param
source_fn voidptr // set in the checker, while processing fn declarations
usages int
return_type Type
name string
params []Param
source_fn voidptr // set in the checker, while processing fn declarations
usages int
}
fn (f &Fn) method_equals(o &Fn) bool {
@ -1108,6 +1107,26 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
}
return new_type(idx).derive(generic_type).clear_flag(.generic)
}
} else if mut sym.info is FnType {
mut func := sym.info.func
if func.return_type.has_flag(.generic) {
if typ := t.resolve_generic_to_concrete(func.return_type, generic_names, concrete_types,
is_inst)
{
func.return_type = typ
}
}
for mut param in func.params {
if param.typ.has_flag(.generic) {
if typ := t.resolve_generic_to_concrete(param.typ, generic_names, concrete_types,
is_inst)
{
param.typ = typ
}
}
}
idx := t.find_or_register_fn_type('', func, true, false)
return new_type(idx).derive(generic_type).clear_flag(.generic)
}
return none
}

View File

@ -0,0 +1,14 @@
struct Scope<T> {
before fn () T
specs []fn (T) T
after fn (T)
}
fn test_generics_struct_anon_fn_fields() {
s := Scope<u32>{}
println(s)
ts := '$s'
assert ts.contains('before: fn () u32')
assert ts.contains('specs: []')
assert ts.contains('after: fn (u32)')
}