Skip to content

Commit 17d540e

Browse files
authored
cgen: fix interface eq method with option and ref (fix #19441) (#20201)
1 parent 97d01a9 commit 17d540e

File tree

3 files changed

+100
-20
lines changed

3 files changed

+100
-20
lines changed

vlib/v/gen/c/auto_eq_methods.v

Lines changed: 78 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,11 @@ fn (mut g Gen) gen_sumtype_equality_fn(left_type ast.Type) string {
5353
left := g.unwrap(left_type)
5454
ptr_styp := g.typ(left.typ.set_nr_muls(0))
5555

56-
if left_type in g.generated_eq_fns {
56+
left_no_ptr := left_type.set_nr_muls(0)
57+
if left_no_ptr in g.generated_eq_fns {
5758
return ptr_styp
5859
}
59-
g.generated_eq_fns << left_type
60+
g.generated_eq_fns << left_no_ptr
6061

6162
info := left.sym.sumtype_info()
6263
g.definitions.writeln('static bool ${ptr_styp}_sumtype_eq(${ptr_styp} a, ${ptr_styp} b); // auto')
@@ -129,7 +130,17 @@ fn (mut g Gen) read_field(struct_type ast.Type, field_name string, var_name stri
129130
@[inline]
130131
fn (mut g Gen) read_opt_field(struct_type ast.Type, field_name string, var_name string, field_typ ast.Type) string {
131132
return if field_typ.has_flag(.option) {
132-
'*(${g.base_type(field_typ)}*)${g.read_field(struct_type, field_name, var_name)}.data'
133+
field_typ_ := if g.table.sym(field_typ).kind in [.interface_, .string] && field_typ.is_ptr() {
134+
field_typ.deref()
135+
} else {
136+
field_typ
137+
}
138+
opt := if g.table.sym(field_typ).kind == .interface_ && field_typ.is_ptr() {
139+
'_option_'
140+
} else {
141+
''
142+
}
143+
'*(${opt}${g.base_type(field_typ_)}*)${g.read_field(struct_type, field_name, var_name)}.data'
133144
} else {
134145
g.read_field(struct_type, field_name, var_name)
135146
}
@@ -139,10 +150,13 @@ fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string {
139150
left := g.unwrap(left_type)
140151
ptr_styp := g.typ(left.typ.set_nr_muls(0))
141152
fn_name := ptr_styp.replace('struct ', '')
142-
if left_type in g.generated_eq_fns {
153+
154+
left_no_ptr := left_type.set_nr_muls(0)
155+
if left_no_ptr in g.generated_eq_fns {
143156
return fn_name
144157
}
145-
g.generated_eq_fns << left_type
158+
g.generated_eq_fns << left_no_ptr
159+
146160
info := left.sym.struct_info()
147161
g.definitions.writeln('static bool ${fn_name}_struct_eq(${ptr_styp} a, ${ptr_styp} b); // auto')
148162

@@ -176,6 +190,8 @@ fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string {
176190
left_arg_opt := g.read_opt_field(left_type, field_name, 'a', field.typ)
177191
right_arg_opt := g.read_opt_field(left_type, field_name, 'b', field.typ)
178192
fn_builder.write_string('(((${left_arg_opt}).len == (${right_arg_opt}).len && (${left_arg_opt}).len == 0) || string__eq(${left_arg_opt}, ${right_arg_opt}))')
193+
} else if field.typ.is_ptr() {
194+
fn_builder.write_string('((${left_arg}->len == ${right_arg}->len && ${left_arg}->len == 0) || string__eq(*(${left_arg}), *(${right_arg})))')
179195
} else {
180196
fn_builder.write_string('((${left_arg}.len == ${right_arg}.len && ${left_arg}.len == 0) || string__eq(${left_arg}, ${right_arg}))')
181197
}
@@ -200,9 +216,37 @@ fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string {
200216
} else if field_type.sym.kind == .function && !field.typ.has_flag(.option) {
201217
fn_builder.write_string('*((voidptr*)(${left_arg})) == *((voidptr*)(${right_arg}))')
202218
} else if field_type.sym.kind == .interface_ {
203-
ptr := if field.typ.is_ptr() { '*'.repeat(field.typ.nr_muls()) } else { '' }
204-
eq_fn := g.gen_interface_equality_fn(field.typ)
205-
fn_builder.write_string('${eq_fn}_interface_eq(${ptr}${left_arg}, ${ptr}${right_arg})')
219+
if field.typ.has_flag(.option) {
220+
field_typ_ := if field.typ.is_ptr() {
221+
field.typ.deref()
222+
} else {
223+
field.typ
224+
}
225+
if field.typ.is_ptr() {
226+
left_arg_opt := g.read_opt_field(left_type, field_name, 'a', field.typ)
227+
right_arg_opt := g.read_opt_field(left_type, field_name, 'b',
228+
field.typ)
229+
ptr := if field_typ_.is_ptr() {
230+
'*'.repeat(field_typ_.nr_muls())
231+
} else {
232+
''
233+
}
234+
eq_fn := g.gen_interface_equality_fn(field_typ_)
235+
fn_builder.write_string('${eq_fn}_interface_eq(${ptr}${left_arg_opt}, ${ptr}${right_arg_opt})')
236+
} else {
237+
ptr := if field_typ_.is_ptr() {
238+
'*'.repeat(field_typ_.nr_muls())
239+
} else {
240+
''
241+
}
242+
eq_fn := g.gen_interface_equality_fn(field_typ_)
243+
fn_builder.write_string('${eq_fn}_interface_eq(${ptr}${left_arg}, ${ptr}${right_arg})')
244+
}
245+
} else {
246+
ptr := if field.typ.is_ptr() { '*'.repeat(field.typ.nr_muls()) } else { '' }
247+
eq_fn := g.gen_interface_equality_fn(field.typ)
248+
fn_builder.write_string('${eq_fn}_interface_eq(${ptr}${left_arg}, ${ptr}${right_arg})')
249+
}
206250
} else if field.typ.has_flag(.option) {
207251
fn_builder.write_string('${left_arg}.state == ${right_arg}.state && !memcmp(&${left_arg}.data, &${right_arg}.data, sizeof(${g.base_type(field.typ)}))')
208252
} else {
@@ -220,10 +264,13 @@ fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string {
220264
fn (mut g Gen) gen_alias_equality_fn(left_type ast.Type) string {
221265
left := g.unwrap(left_type)
222266
ptr_styp := g.typ(left.typ.set_nr_muls(0))
223-
if left_type in g.generated_eq_fns {
267+
268+
left_no_ptr := left_type.set_nr_muls(0)
269+
if left_no_ptr in g.generated_eq_fns {
224270
return ptr_styp
225271
}
226-
g.generated_eq_fns << left_type
272+
g.generated_eq_fns << left_no_ptr
273+
227274
info := left.sym.info as ast.Alias
228275
g.definitions.writeln('static bool ${ptr_styp}_alias_eq(${ptr_styp} a, ${ptr_styp} b); // auto')
229276

@@ -277,10 +324,13 @@ fn (mut g Gen) gen_alias_equality_fn(left_type ast.Type) string {
277324
fn (mut g Gen) gen_array_equality_fn(left_type ast.Type) string {
278325
left := g.unwrap(left_type)
279326
ptr_styp := g.typ(left.typ.set_nr_muls(0))
280-
if left_type in g.generated_eq_fns {
327+
328+
left_no_ptr := left_type.set_nr_muls(0)
329+
if left_no_ptr in g.generated_eq_fns {
281330
return ptr_styp
282331
}
283-
g.generated_eq_fns << left_type
332+
g.generated_eq_fns << left_no_ptr
333+
284334
elem := g.unwrap(left.sym.array_info().elem_type)
285335
ptr_elem_styp := g.typ(elem.typ)
286336
g.definitions.writeln('static bool ${ptr_styp}_arr_eq(${ptr_styp} a, ${ptr_styp} b); // auto')
@@ -346,10 +396,13 @@ fn (mut g Gen) gen_array_equality_fn(left_type ast.Type) string {
346396
fn (mut g Gen) gen_fixed_array_equality_fn(left_type ast.Type) string {
347397
left_typ := g.unwrap(left_type)
348398
ptr_styp := g.typ(left_typ.typ.set_nr_muls(0))
349-
if left_type in g.generated_eq_fns {
399+
400+
left_no_ptr := left_type.set_nr_muls(0)
401+
if left_no_ptr in g.generated_eq_fns {
350402
return ptr_styp
351403
}
352-
g.generated_eq_fns << left_type
404+
g.generated_eq_fns << left_no_ptr
405+
353406
elem_info := left_typ.sym.array_fixed_info()
354407
elem := g.unwrap(elem_info.elem_type)
355408
size := elem_info.size
@@ -402,10 +455,13 @@ fn (mut g Gen) gen_fixed_array_equality_fn(left_type ast.Type) string {
402455
fn (mut g Gen) gen_map_equality_fn(left_type ast.Type) string {
403456
left := g.unwrap(left_type)
404457
ptr_styp := g.typ(left.typ.set_nr_muls(0))
405-
if left_type in g.generated_eq_fns {
458+
459+
left_no_ptr := left_type.set_nr_muls(0)
460+
if left_no_ptr in g.generated_eq_fns {
406461
return ptr_styp
407462
}
408-
g.generated_eq_fns << left_type
463+
g.generated_eq_fns << left_no_ptr
464+
409465
value := g.unwrap(left.sym.map_info().value_type)
410466
ptr_value_styp := g.typ(value.typ)
411467
g.definitions.writeln('static bool ${ptr_styp}_map_eq(${ptr_styp} a, ${ptr_styp} b); // auto')
@@ -485,10 +541,13 @@ fn (mut g Gen) gen_interface_equality_fn(left_type ast.Type) string {
485541
ptr_styp := g.typ(left.typ.set_nr_muls(0))
486542
idx_fn := g.typ(left.typ.set_nr_muls(0).clear_flag(.option))
487543
fn_name := ptr_styp.replace('interface ', '')
488-
if left_type in g.generated_eq_fns {
544+
545+
left_no_ptr := left_type.set_nr_muls(0)
546+
if left_no_ptr in g.generated_eq_fns {
489547
return fn_name
490548
}
491-
g.generated_eq_fns << left_type
549+
g.generated_eq_fns << left_no_ptr
550+
492551
info := left.sym.info
493552
g.definitions.writeln('static bool ${ptr_styp}_interface_eq(${ptr_styp} a, ${ptr_styp} b); // auto')
494553

@@ -508,7 +567,7 @@ fn (mut g Gen) gen_interface_equality_fn(left_type ast.Type) string {
508567
for typ in info.types {
509568
fn_builder.writeln('\t\tif (idx == ${typ.idx()}) {')
510569
fn_builder.write_string('\t\t\treturn ')
511-
match g.table.type_kind(typ) {
570+
match g.table.type_kind(typ.set_nr_muls(0)) {
512571
.struct_ {
513572
eq_fn := g.gen_struct_equality_fn(typ)
514573
l_eqfn := g.read_field(left_type, '_${eq_fn}', 'a')

vlib/v/gen/c/cgen.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,7 @@ pub fn (mut g Gen) write_typeof_functions() {
972972
g.writeln('static int v_typeof_interface_idx_${sym.cname}(int sidx) { /* ${sym.name} */ ')
973973
for t in inter_info.types {
974974
sub_sym := g.table.sym(ast.mktyp(t))
975-
g.writeln('\tif (sidx == _${sym.cname}_${sub_sym.cname}_index) return ${int(t)};')
975+
g.writeln('\tif (sidx == _${sym.cname}_${sub_sym.cname}_index) return ${int(t.set_nr_muls(0))};')
976976
}
977977
g.writeln('\treturn ${int(ityp)};')
978978
g.writeln('}')
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// for issue 19441
2+
pub interface Iface {}
3+
4+
pub struct Derived {}
5+
6+
pub struct Struct {
7+
field ?&Iface
8+
}
9+
10+
pub struct Mixin {
11+
Derived
12+
Struct
13+
}
14+
15+
fn test_main() {
16+
mut arr := []&Iface{}
17+
arr << &Derived{}
18+
arr << &Derived{}
19+
20+
assert arr[0] == arr[1]
21+
}

0 commit comments

Comments
 (0)