From a93387e2318b7c41cc21bd5b48853e56517f23c7 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 25 Mar 2026 16:42:21 +0300 Subject: [PATCH] cgen: fix duplicate code generated when using interface from a package (fixes #18326) --- vlib/v/gen/c/auto_eq_methods.v | 45 ++++++++++--------- .../imported_interface_auto_eq_18326/extra.v | 19 ++++++++ .../imported_interface_auto_eq_18326_test.v | 16 +++++++ .../vest/vest.v | 3 ++ 4 files changed, 63 insertions(+), 20 deletions(-) create mode 100644 vlib/v/tests/modules/imported_interface_auto_eq_18326/extra.v create mode 100644 vlib/v/tests/modules/imported_interface_auto_eq_18326/imported_interface_auto_eq_18326_test.v create mode 100644 vlib/v/tests/modules/imported_interface_auto_eq_18326/vest/vest.v diff --git a/vlib/v/gen/c/auto_eq_methods.v b/vlib/v/gen/c/auto_eq_methods.v index 8d38ed071..683b2022b 100644 --- a/vlib/v/gen/c/auto_eq_methods.v +++ b/vlib/v/gen/c/auto_eq_methods.v @@ -6,41 +6,46 @@ import strings import v.ast fn (mut g Gen) equality_fn(typ ast.Type) string { - g.needed_equality_fns << typ.set_nr_muls(0) - t1 := g.unwrap_generic(typ) - t2 := t1.set_nr_muls(0) - st2 := g.styp(t2) + eq_key := g.eq_fn_key(typ) + g.needed_equality_fns << eq_key + st2 := g.styp(eq_key) res := st2.replace('struct ', '') return res } +@[inline] +fn (mut g Gen) eq_fn_key(typ ast.Type) ast.Type { + return g.unwrap_generic(typ).set_nr_muls(0) +} + fn (mut g Gen) gen_equality_fns() { for needed_typ in g.needed_equality_fns { - if needed_typ in g.generated_eq_fns { + eq_key := g.eq_fn_key(needed_typ) + if eq_key in g.generated_eq_fns { continue } - sym := g.table.sym(needed_typ) + sym := g.table.sym(eq_key) match sym.kind { .sum_type { - g.gen_sumtype_equality_fn(needed_typ) + g.gen_sumtype_equality_fn(eq_key) } .struct { - g.gen_struct_equality_fn(needed_typ) + g.gen_struct_equality_fn(eq_key) } .array { - g.gen_array_equality_fn(needed_typ) + g.gen_array_equality_fn(eq_key) } .array_fixed { - g.gen_fixed_array_equality_fn(needed_typ) + g.gen_fixed_array_equality_fn(eq_key) } .map { - g.gen_map_equality_fn(needed_typ) + g.gen_map_equality_fn(eq_key) } .alias { - g.gen_alias_equality_fn(needed_typ) + g.gen_alias_equality_fn(eq_key) } .interface { - g.gen_interface_equality_fn(needed_typ) + g.gen_interface_equality_fn(eq_key) } else { verror('could not generate equality function for type ${sym.kind}') @@ -53,7 +58,7 @@ fn (mut g Gen) gen_sumtype_equality_fn(left_type ast.Type) string { left := g.unwrap(left_type) ptr_styp := g.styp(left.typ.set_nr_muls(0)) - left_no_ptr := left_type.set_nr_muls(0) + left_no_ptr := g.eq_fn_key(left_type) if left_no_ptr in g.generated_eq_fns { return ptr_styp } @@ -177,7 +182,7 @@ fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string { ptr_styp := g.styp(left.typ.set_nr_muls(0)) fn_name := ptr_styp.replace('struct ', '') - left_no_ptr := left_type.set_nr_muls(0) + left_no_ptr := g.eq_fn_key(left_type) if left_no_ptr in g.generated_eq_fns { return fn_name } @@ -294,7 +299,7 @@ fn (mut g Gen) gen_alias_equality_fn(left_type ast.Type) string { left := g.unwrap(left_type) ptr_styp := g.styp(left.typ.set_nr_muls(0)) - left_no_ptr := left_type.set_nr_muls(0) + left_no_ptr := g.eq_fn_key(left_type) if left_no_ptr in g.generated_eq_fns { return ptr_styp } @@ -354,7 +359,7 @@ fn (mut g Gen) gen_array_equality_fn(left_type ast.Type) string { left := g.unwrap(left_type) ptr_styp := g.styp(left.typ.set_nr_muls(0)) - left_no_ptr := left_type.set_nr_muls(0) + left_no_ptr := g.eq_fn_key(left_type) if left_no_ptr in g.generated_eq_fns { return ptr_styp } @@ -437,7 +442,7 @@ fn (mut g Gen) gen_fixed_array_equality_fn(left_type ast.Type) string { left_typ := g.unwrap(left_type) ptr_styp := g.styp(left_typ.typ.set_nr_muls(0)) - left_no_ptr := left_type.set_nr_muls(0) + left_no_ptr := g.eq_fn_key(left_type) if left_no_ptr in g.generated_eq_fns { return ptr_styp } @@ -516,7 +521,7 @@ fn (mut g Gen) gen_map_equality_fn(left_type ast.Type) string { left := g.unwrap(left_type) ptr_styp := g.styp(left.typ.set_nr_muls(0)) - left_no_ptr := left_type.set_nr_muls(0) + left_no_ptr := g.eq_fn_key(left_type) if left_no_ptr in g.generated_eq_fns { return ptr_styp } @@ -613,7 +618,7 @@ fn (mut g Gen) gen_interface_equality_fn(left_type ast.Type) string { idx_fn := g.styp(left.typ.set_nr_muls(0).clear_flag(.option)) fn_name := ptr_styp.replace('interface ', '') - left_no_ptr := left_type.set_nr_muls(0) + left_no_ptr := g.eq_fn_key(left_type) if left_no_ptr in g.generated_eq_fns { return fn_name } diff --git a/vlib/v/tests/modules/imported_interface_auto_eq_18326/extra.v b/vlib/v/tests/modules/imported_interface_auto_eq_18326/extra.v new file mode 100644 index 000000000..98605c999 --- /dev/null +++ b/vlib/v/tests/modules/imported_interface_auto_eq_18326/extra.v @@ -0,0 +1,19 @@ +module main + +import imported_interface_auto_eq_18326.vest + +struct ObjectImpl {} + +fn generic_interface_equal[T](a T, b T) bool { + return a == b +} + +fn concrete_interface_equal(a vest.Object, b vest.Object) bool { + return a == b +} + +fn exercise_imported_interface_equality_helpers() bool { + a := vest.Object(ObjectImpl{}) + b := vest.Object(ObjectImpl{}) + return generic_interface_equal[vest.Object](a, b) && concrete_interface_equal(a, b) +} diff --git a/vlib/v/tests/modules/imported_interface_auto_eq_18326/imported_interface_auto_eq_18326_test.v b/vlib/v/tests/modules/imported_interface_auto_eq_18326/imported_interface_auto_eq_18326_test.v new file mode 100644 index 000000000..ddd8aad5e --- /dev/null +++ b/vlib/v/tests/modules/imported_interface_auto_eq_18326/imported_interface_auto_eq_18326_test.v @@ -0,0 +1,16 @@ +module main + +import imported_interface_auto_eq_18326.vest + +struct WebModule { + controllers []vest.Object +} + +fn test_imported_interface_array_field_auto_eq() { + mut mod := WebModule{} + assert mod == mod +} + +fn test_imported_interface_equality_helper_deduping() { + assert exercise_imported_interface_equality_helpers() +} diff --git a/vlib/v/tests/modules/imported_interface_auto_eq_18326/vest/vest.v b/vlib/v/tests/modules/imported_interface_auto_eq_18326/vest/vest.v new file mode 100644 index 000000000..a0dfd259d --- /dev/null +++ b/vlib/v/tests/modules/imported_interface_auto_eq_18326/vest/vest.v @@ -0,0 +1,3 @@ +module vest + +pub interface Object {} -- 2.39.5