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 struct Fn {
pub: pub:
return_type Type is_variadic bool
is_variadic bool language Language
language Language generic_names []string
generic_names []string is_pub bool
is_pub bool is_deprecated bool // `[deprecated] fn abc(){}`
is_deprecated bool // `[deprecated] fn abc(){}` is_unsafe bool // `[unsafe] fn abc(){}`
is_unsafe bool // `[unsafe] fn abc(){}` is_placeholder bool
is_placeholder bool is_main bool // `fn main(){}`
is_main bool // `fn main(){}` is_test bool // `fn test_abc(){}`
is_test bool // `fn test_abc(){}` is_conditional bool // `[if abc]fn(){}`
is_conditional bool // `[if abc]fn(){}` is_keep_alive bool // passed memory must not be freed (by GC) before function returns
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.
no_body bool // a pure declaration like `fn abc(x int)`; used in .vh files, C./JS. fns. mod string
mod string ctdefine string // compile time define. "myflag", when [if myflag] tag
ctdefine string // compile time define. "myflag", when [if myflag] tag attrs []Attr
attrs []Attr
//
pos token.Position pos token.Position
return_type_pos token.Position return_type_pos token.Position
pub mut: pub mut:
name string return_type Type
params []Param name string
source_fn voidptr // set in the checker, while processing fn declarations params []Param
usages int source_fn voidptr // set in the checker, while processing fn declarations
usages int
} }
fn (f &Fn) method_equals(o &Fn) bool { 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) 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 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)')
}