ast: fix generic structs with multiple levels of generic embedding (#20042)

This commit is contained in:
shove 2023-12-01 05:26:21 +08:00 committed by GitHub
parent 0c4abf0c19
commit c19b13e165
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 2 deletions

View File

@ -1936,6 +1936,7 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr
fields = ts.info.fields.clone()
for i in 0 .. fields.len {
if fields[i].typ.has_flag(.generic) {
orig_type := fields[i].typ
sym := t.sym(fields[i].typ)
if sym.kind == .struct_ && fields[i].typ.idx() != typ.idx() {
fields[i].typ = t.unwrap_generic_type(fields[i].typ, t_generic_names,
@ -1947,6 +1948,19 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr
fields[i].typ = t_typ
}
}
// Update type in `info.embeds`, if it's embed
if fields[i].name.len > 1 && fields[i].name[0].is_capital() {
mut parent_sym := t.sym(typ)
mut parent_info := parent_sym.info
if mut parent_info is Struct {
for mut embed in parent_info.embeds {
if embed == orig_type {
embed = fields[i].typ.set_flag(.generic)
break
}
}
}
}
}
}
// update concrete types

View File

@ -2,11 +2,28 @@ struct Foo[T] {
field T
}
struct MainStruct[T] {
struct Bar[T] {
Foo[T]
}
struct Baz[T] {
Bar[T]
}
struct OneLevelEmbed[T] {
Foo[T]
}
fn test_main() {
m := MainStruct[int]{}
m := OneLevelEmbed[int]{}
assert m.field == 0
}
struct MultiLevelEmbed[T] {
Baz[T]
}
fn test_multi_level() {
m := MultiLevelEmbed[int]{}
assert m.field == 0
}