From c6afba84ade4f27bf4ba448bac7b300bffbacd37 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 15 Apr 2026 06:06:51 +0300 Subject: [PATCH] checker: fix wrong error when smartcasting references to sumtypes (fixes #17236) --- vlib/v/checker/infix.v | 10 ++++++++-- vlib/v/gen/c/cgen.v | 2 +- vlib/v/gen/c/infix.v | 14 +++++++++++++- vlib/v/tests/conditions/ifs/if_smartcast_test.v | 17 +++++++++++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v index 09ddd2e15..4fc6907bc 100644 --- a/vlib/v/checker/infix.v +++ b/vlib/v/checker/infix.v @@ -883,8 +883,14 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { && !c.comptime.is_comptime(node.left) { c.error('`${op}` can only be used with interfaces and sum types', node.pos) // can be used in sql too, but keep err simple } else if mut left_sym.info is ast.SumType { - if typ !in left_sym.info.variants - && c.unwrap_generic(typ) !in left_sym.info.variants { + variant_typ := if left_type.nr_muls() > 0 + && typ.nr_muls() <= left_type.nr_muls() { + typ.set_nr_muls(0) + } else { + typ + } + if variant_typ !in left_sym.info.variants + && c.unwrap_generic(variant_typ) !in left_sym.info.variants { c.error('`${left_sym.name}` has no variant `${typ_sym.name}`', right_pos) } } else if left_sym.info is ast.Interface { diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index f5991587b..0727e3f3e 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -7757,7 +7757,7 @@ fn (mut g Gen) ident(node ast.Ident) { styp := g.base_type(resolved_var.typ) g.write('*(${styp}*)') } - } else if !g.arg_no_auto_deref { + } else if !g.arg_no_auto_deref && !typ.is_ptr() { g.write('*') } } else if interface_var_needs_deref diff --git a/vlib/v/gen/c/infix.v b/vlib/v/gen/c/infix.v index 81b3bc41e..9bc2bbe3f 100644 --- a/vlib/v/gen/c/infix.v +++ b/vlib/v/gen/c/infix.v @@ -1093,6 +1093,11 @@ fn (mut g Gen) infix_expr_is_op(node ast.InfixExpr) { node.left_type))) is_aggregate := node.left is ast.Ident && g.comptime.get_ct_type_var(node.left) == .aggregate right_sym := g.table.sym(node.right_type) + mut right_type := node.right_type + if (left_sym.kind == .sum_type || is_aggregate) && node.left_type.nr_muls() > 0 + && right_type.nr_muls() <= node.left_type.nr_muls() { + right_type = right_type.set_nr_muls(0) + } if left_sym.kind == .interface && right_sym.kind == .interface { g.gen_interface_is_op(node) return @@ -1139,7 +1144,14 @@ fn (mut g Gen) infix_expr_is_op(node ast.InfixExpr) { } else if node.right is ast.Ident && node.right.name == g.comptime.comptime_for_variant_var { variant_idx := g.type_resolver.get_ct_type_or_default('${g.comptime.comptime_for_variant_var}.typ', ast.void_type) - g.write('${int(variant_idx)}') + if (left_sym.kind == .sum_type || is_aggregate) && node.left_type.nr_muls() > 0 + && variant_idx.nr_muls() <= node.left_type.nr_muls() { + g.write('${int(variant_idx.set_nr_muls(0))}') + } else { + g.write('${int(variant_idx)}') + } + } else if node.right is ast.TypeNode { + g.write('${int(right_type)}') } else { g.expr(node.right) } diff --git a/vlib/v/tests/conditions/ifs/if_smartcast_test.v b/vlib/v/tests/conditions/ifs/if_smartcast_test.v index 62c4cdbd3..96113891c 100644 --- a/vlib/v/tests/conditions/ifs/if_smartcast_test.v +++ b/vlib/v/tests/conditions/ifs/if_smartcast_test.v @@ -325,3 +325,20 @@ fn test_nested_pointer_smartcast() { } } } + +struct RefVariantType { + value int +} + +type RefSmartcastSum = RefVariantType | int + +fn test_reference_sumtype_variant_smartcast() { + sum_ref := &RefSmartcastSum(RefVariantType{ + value: 7 + }) + if sum_ref is &RefVariantType { + assert sum_ref.value == 7 + } else { + assert false + } +} -- 2.39.5