v.checker,v.gen: allow for `&IAbc(voidptr(0))` where IAbc contains fields

pull/10479/head
Delyan Angelov 2021-06-16 10:48:50 +03:00
parent e7cc93a120
commit 862c4cf371
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
3 changed files with 38 additions and 7 deletions

View File

@ -2721,8 +2721,11 @@ fn (mut c Checker) type_implements(typ ast.Type, interface_type ast.Type, pos to
}
continue
}
c.error("`$styp` doesn't implement field `$ifield.name` of interface `$inter_sym.name`",
pos)
// voidptr is an escape hatch, it should be allowed to be passed
if utyp != ast.voidptr_type {
c.error("`$styp` doesn't implement field `$ifield.name` of interface `$inter_sym.name`",
pos)
}
}
inter_sym.info.types << utyp
}

View File

@ -6549,11 +6549,13 @@ fn (mut g Gen) interface_table() string {
} else {
// the field is embedded in another struct
cast_struct.write_string('\t\t.$cname = ($field_styp*)((char*)x')
for embed_type in st_sym.struct_info().embeds {
embed_sym := g.table.get_type_symbol(embed_type)
if _ := embed_sym.find_field(field.name) {
cast_struct.write_string(' + __offsetof_ptr(x, $cctype, $embed_sym.embed_name()) + __offsetof_ptr(x, $embed_sym.cname, $cname)')
break
if st != ast.voidptr_type {
for embed_type in st_sym.struct_info().embeds {
embed_sym := g.table.get_type_symbol(embed_type)
if _ := embed_sym.find_field(field.name) {
cast_struct.write_string(' + __offsetof_ptr(x, $cctype, $embed_sym.embed_name()) + __offsetof_ptr(x, $embed_sym.cname, $cname)')
break
}
}
}
cast_struct.writeln('),')

View File

@ -0,0 +1,26 @@
interface IAbc {
name string
xyz()
}
struct Abc {
name string
x int = 123
}
fn (a Abc) xyz() {}
fn f(i &IAbc) string {
return '$i'
}
fn test_voidptr_casted_as_an_interface_reference() {
mut pi := &IAbc(voidptr(0))
dump(pi)
assert f(pi) == '&IAbc(0)'
//
i := IAbc(Abc{})
pi = &i
dump(pi)
assert f(pi).contains('x: 123')
}