cgen: fix array type as interface (fix #14677) (#14681)

master
ChAoS_UnItY 2022-06-05 10:05:48 +08:00 committed by GitHub
parent 5d429140a4
commit f6ebbc99cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 5 deletions

View File

@ -5654,12 +5654,17 @@ fn (mut g Gen) interface_table() string {
field_styp := g.typ(field.typ) field_styp := g.typ(field.typ)
if _ := st_sym.find_field(field.name) { if _ := st_sym.find_field(field.name) {
cast_struct.writeln('\t\t.$cname = ($field_styp*)((char*)x + __offsetof_ptr(x, $cctype, $cname)),') cast_struct.writeln('\t\t.$cname = ($field_styp*)((char*)x + __offsetof_ptr(x, $cctype, $cname)),')
} else if st_sym.kind == .array
&& field.name in ['element_size', 'data', 'offset', 'len', 'cap', 'flags'] {
// Manaully checking, we already knows array contains above fields
cast_struct.writeln('\t\t.$cname = ($field_styp*)((char*)x + __offsetof_ptr(x, $cctype, $cname)),')
} else { } else {
// the field is embedded in another struct // the field is embedded in another struct
cast_struct.write_string('\t\t.$cname = ($field_styp*)((char*)x') cast_struct.write_string('\t\t.$cname = ($field_styp*)((char*)x')
if st == ast.voidptr_type { if st == ast.voidptr_type {
cast_struct.write_string('/*.... ast.voidptr_type */') cast_struct.write_string('/*.... ast.voidptr_type */')
} else { } else {
if st_sym.kind == .struct_ {
for embed_type in st_sym.struct_info().embeds { for embed_type in st_sym.struct_info().embeds {
embed_sym := g.table.sym(embed_type) embed_sym := g.table.sym(embed_type)
if _ := embed_sym.find_field(field.name) { if _ := embed_sym.find_field(field.name) {
@ -5668,6 +5673,7 @@ fn (mut g Gen) interface_table() string {
} }
} }
} }
}
cast_struct.writeln('),') cast_struct.writeln('),')
} }
} }

View File

@ -0,0 +1,2 @@
4
1

View File

@ -0,0 +1,8 @@
interface Source {
len int
}
fn main() {
println(Source('test').len)
println(Source([`a`]).len)
}

View File

@ -0,0 +1,19 @@
interface Source {
element_size int
data voidptr
offset int
len int
cap int
flags ArrayFlags
}
fn test_array_as_interface() {
arr := []rune{len: 1}
src := Source(arr)
assert arr.element_size == src.element_size
assert arr.data == src.data
assert arr.offset == src.offset
assert arr.len == src.len
assert arr.cap == src.cap
assert arr.flags == src.flags
}