From 862c4cf371a5ca38ec48c6a11add6cab3a35a733 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Wed, 16 Jun 2021 10:48:50 +0300 Subject: [PATCH] v.checker,v.gen: allow for `&IAbc(voidptr(0))` where IAbc contains fields --- vlib/v/checker/checker.v | 7 +++-- vlib/v/gen/c/cgen.v | 12 +++++---- .../voidptr_casted_as_an_interface_test.v | 26 +++++++++++++++++++ 3 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 vlib/v/tests/interface_edge_cases/voidptr_casted_as_an_interface_test.v diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index cf88401336..ebc28828ab 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -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 } diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index dd44e3ab77..64b41f593e 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -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('),') diff --git a/vlib/v/tests/interface_edge_cases/voidptr_casted_as_an_interface_test.v b/vlib/v/tests/interface_edge_cases/voidptr_casted_as_an_interface_test.v new file mode 100644 index 0000000000..2908c35c42 --- /dev/null +++ b/vlib/v/tests/interface_edge_cases/voidptr_casted_as_an_interface_test.v @@ -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') +}