1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: fix overwriting methods of embedded structs + empty struct for interfaces (#12876)

This commit is contained in:
Tim Basel 2021-12-17 14:32:31 +01:00 committed by GitHub
parent b482da74e9
commit 130d189fce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 75 additions and 5 deletions

View File

@ -6034,8 +6034,13 @@ fn (mut g Gen) struct_init(node ast.StructInit) {
typ: embed
fields: init_fields_to_embed
}
inside_cast_in_heap := g.inside_cast_in_heap
g.inside_cast_in_heap = 0 // prevent use of pointers in child structs
g.write('.$embed_name = ')
g.struct_init(default_init)
g.inside_cast_in_heap = inside_cast_in_heap // restore value for further struct inits
if is_multiline {
g.writeln(',')
} else {
@ -7262,9 +7267,7 @@ fn (mut g Gen) interface_table() string {
// i.e. cctype is always just Cat, not Cat_ptr:
cctype := g.cc_type(st, true)
$if debug_interface_table ? {
eprintln(
'>> interface name: $isym.name | concrete type: $st.debug() | st symname: ' +
st_sym.name)
eprintln('>> interface name: $isym.name | concrete type: $st.debug() | st symname: $st_sym.name')
}
// Speaker_Cat_index = 0
interface_index_name := '_${interface_name}_${cctype}_index'
@ -7323,6 +7326,7 @@ static inline $interface_name I_${cctype}_to_Interface_${interface_name}($cctype
}
}
mut methods := st_sym.methods
method_names := methods.map(it.name)
match st_sym.info {
ast.Struct, ast.Interface, ast.SumType {
if st_sym.info.parent_type.has_flag(.generic) {
@ -7341,7 +7345,6 @@ static inline $interface_name I_${cctype}_to_Interface_${interface_name}($cctype
if st_sym.info is ast.Struct {
for embed in st_sym.info.embeds {
embed_sym := g.table.get_type_symbol(embed)
method_names := methods.map(it.name)
for embed_method in embed_sym.methods {
if embed_method.name !in method_names {
methods << embed_method
@ -7396,7 +7399,7 @@ static inline $interface_name I_${cctype}_to_Interface_${interface_name}($cctype
_, embed_types := g.table.find_method_from_embeds(st_sym, method.name) or {
ast.Fn{}, []ast.Type{}
}
if embed_types.len > 0 {
if embed_types.len > 0 && method.name !in method_names {
embed_sym := g.table.get_type_symbol(embed_types.last())
method_name := '${embed_sym.cname}_$method.name'
methods_wrapper.write_string('${method_name}(${fargs[0]}')

View File

@ -0,0 +1,67 @@
module main
interface Getter {
get() string
}
struct Struct {
msg string
}
fn (s Struct) get() string {
return s.msg
}
struct EmbeddingStruct {
Struct
}
fn (s EmbeddingStruct) get() string {
return 'embedded: $s.msg'
}
fn test_struct_embedding() {
s1 := EmbeddingStruct{
msg: '1'
}
getter1 := Getter(s1)
s2 := &EmbeddingStruct{
msg: '2'
}
getter2 := Getter(s2)
getter3 := Getter(EmbeddingStruct{
msg: '3'
})
getter4 := Getter(&EmbeddingStruct{
msg: '4'
})
assert getter1.get() == 'embedded: 1'
assert getter2.get() == 'embedded: 2'
assert getter3.get() == 'embedded: 3'
assert getter4.get() == 'embedded: 4'
}
struct EmptyStruct {}
fn (s EmptyStruct) get() string {
return 'empty'
}
struct EmbeddingEmptyStruct {
EmptyStruct
}
fn test_empty_struct_embedding() {
s1 := EmbeddingEmptyStruct{}
getter1 := Getter(s1)
s2 := &EmbeddingEmptyStruct{}
getter2 := Getter(s2)
getter3 := Getter(EmbeddingEmptyStruct{})
getter4 := Getter(&EmbeddingEmptyStruct{})
assert getter1.get() == 'empty'
assert getter2.get() == 'empty'
assert getter3.get() == 'empty'
assert getter4.get() == 'empty'
}