From f7d957c4900620864bb7b5615d22b1becdf47c45 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 25 Mar 2026 22:40:45 +0300 Subject: [PATCH] cgen, checker: fix multiple bugs related to alias + reference (fixes #24010) --- vlib/v/gen/c/fn.v | 6 +++ ...s_generic_mut_reference_issue_24010_test.v | 44 +++++++++++++++++++ vlib/v/type_resolver/comptime_resolver.v | 3 ++ 3 files changed, 53 insertions(+) create mode 100644 vlib/v/tests/aliases/alias_generic_mut_reference_issue_24010_test.v diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 6a132ceb2..ae22ff577 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -2990,6 +2990,12 @@ fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type_ ast.Type, lang a exp_sym := g.table.sym(expected_type) mut needs_closing := false old_inside_smartcast := g.inside_smartcast + if arg.is_mut && arg.expr.is_auto_deref_var() && arg_typ.is_ptr() && expected_type.is_ptr() { + g.arg_no_auto_deref = true + g.expr_with_cast(arg.expr, arg_typ, expected_type) + g.arg_no_auto_deref = false + return + } if arg.is_mut && !exp_is_ptr { g.write('&/*mut*/') } else if arg.is_mut && arg_typ.is_ptr() && expected_type.is_ptr() diff --git a/vlib/v/tests/aliases/alias_generic_mut_reference_issue_24010_test.v b/vlib/v/tests/aliases/alias_generic_mut_reference_issue_24010_test.v new file mode 100644 index 000000000..d777c25dc --- /dev/null +++ b/vlib/v/tests/aliases/alias_generic_mut_reference_issue_24010_test.v @@ -0,0 +1,44 @@ +pub struct User { + name string + age int + height f64 +} + +type Users = map[string]User + +fn one() { + assert typeof[Users]().unaliased_typ == typeof[map[string]User]().idx +} + +fn two[T](mut mutable_val T, val T) { + assert mutable_val == val + assert T.idx == typeof(val).idx + assert typeof(mutable_val).idx == typeof(val).idx +} + +fn three[T, V](mut mutable_val T, val V) { + assert mutable_val == val + assert T.idx == typeof(val).idx + assert V.idx == typeof(val).idx + assert typeof(mutable_val).idx == typeof(val).idx +} + +fn decode_map[K, V](mut val map[K]V) { + assert typeof(val).idx == typeof[map[string]User]().idx +} + +fn four[T](mut mutable_val T) { + $if T.unaliased_typ is $map { + decode_map(mut mutable_val) + } +} + +fn test_alias_generic_mut_reference_issue_24010() { + mut mutable_users := Users(map[string]User{}) + users := Users(map[string]User{}) + + one() + two(mut mutable_users, users) + three(mut mutable_users, users) + four(mut mutable_users) +} diff --git a/vlib/v/type_resolver/comptime_resolver.v b/vlib/v/type_resolver/comptime_resolver.v index f38a67eb2..9e275b455 100644 --- a/vlib/v/type_resolver/comptime_resolver.v +++ b/vlib/v/type_resolver/comptime_resolver.v @@ -72,6 +72,9 @@ pub fn (t &ResolverInfo) is_comptime_variant_var(node ast.Ident) bool { // typeof_type resolves type for typeof() expr where field.typ is resolved to real type instead of int type to make type(field.typ).name working pub fn (mut t TypeResolver) typeof_type(node ast.Expr, default_type ast.Type) ast.Type { if node is ast.Ident { + if node.obj is ast.Var && node.obj.is_arg && node.obj.is_auto_deref && node.obj.typ.is_ptr() { + return node.obj.typ.deref().clear_flag(.option_mut_param_t) + } if t.info.inside_comptime_for && t.info.comptime_for_field_var != '' { if node.obj is ast.Var { obj_typ := node.obj.typ -- 2.39.5