@@ -6435,30 +6435,52 @@ fn (mut g Gen) ref_or_deref_arg_ex(arg ast.CallArg, expected_type_ ast.Type, lan
64356435 expected_ref_inner_type := expected_type.deref ()
64366436 expected_ref_inner_sym := g.table.sym (expected_ref_inner_type)
64376437 if expected_ref_inner_sym.kind in [.interface , .sum_type] {
6438- if arg_typ.is_ptr () && arg_typ.deref () == expected_ref_inner_type {
6439- g.prevent_sum_type_unwrapping_once = g.is_expr_smartcast_to_sumtype (arg.expr,
6438+ mut effective_arg_expr := arg.expr
6439+ mut effective_arg_typ := arg_typ
6440+ if expected_ref_inner_sym.kind == .sum_type && arg.expr is ast.CastExpr {
6441+ cast_expr := arg.expr
6442+ cast_target_type := g.unwrap_generic (if cast_expr.typ != 0 {
6443+ cast_expr.typ
6444+ } else {
6445+ arg_typ
6446+ })
6447+ if cast_target_type.idx () == expected_ref_inner_type.idx ()
6448+ && cast_expr.expr_type != 0 {
6449+ effective_arg_expr = cast_expr.expr
6450+ effective_arg_typ = g.unwrap_generic (cast_expr.expr_type)
6451+ }
6452+ }
6453+ effective_arg_sym := g.table.sym (effective_arg_typ)
6454+ if effective_arg_typ.is_ptr () && effective_arg_typ.deref () == expected_ref_inner_type {
6455+ g.prevent_sum_type_unwrapping_once = g.is_expr_smartcast_to_sumtype (effective_arg_expr,
64406456 expected_ref_inner_type)
6441- g.expr (arg.expr)
6442- } else if arg_sym.kind == expected_ref_inner_sym.kind
6443- && arg_typ.idx () == expected_ref_inner_type.idx ()
6444- && arg.expr in [ast.Ident, ast.SelectorExpr] {
6445- g.prevent_sum_type_unwrapping_once = g.is_expr_smartcast_to_sumtype (arg.expr,
6457+ g.expr (effective_arg_expr)
6458+ } else if effective_arg_sym.kind == expected_ref_inner_sym.kind
6459+ && effective_arg_typ.idx () == expected_ref_inner_type.idx () {
6460+ g.prevent_sum_type_unwrapping_once = g.is_expr_smartcast_to_sumtype (effective_arg_expr,
64466461 expected_ref_inner_type)
6447- g.write ('&' )
6448- g.expr (arg.expr)
6449- } else if arg_typ == ast.nil_type || arg_typ.is_voidptr ()
6450- || (arg.expr is ast.UnsafeExpr && arg.expr.expr is ast.Nil ) {
6462+ if effective_arg_expr in [ast.Ident, ast.SelectorExpr] {
6463+ g.write ('&' )
6464+ g.expr (effective_arg_expr)
6465+ } else {
6466+ g.write ('ADDR(${g.styp(expected_ref_inner_type)} , ' )
6467+ g.expr_with_cast (effective_arg_expr, effective_arg_typ, expected_ref_inner_type)
6468+ g.write (')' )
6469+ }
6470+ } else if effective_arg_typ == ast.nil_type
6471+ || effective_arg_typ.is_voidptr ()
6472+ || (effective_arg_expr is ast.UnsafeExpr && effective_arg_expr.expr is ast.Nil ) {
64516473 g.write ('((void*)0)' )
64526474 } else {
64536475 if expected_ref_inner_sym.kind == .sum_type {
64546476 // `&Variant` -> `&SumType` needs a stable heap-allocated wrapper and
64556477 // must preserve aliasing with the original variant payload.
6456- g.expr_with_cast (arg.expr, arg_typ , expected_type)
6478+ g.expr_with_cast (effective_arg_expr, effective_arg_typ , expected_type)
64576479 } else {
64586480 // interface conversions don't box by reference, so HEAP is needed to
64596481 // ensure the pointer remains valid after the current scope ends.
64606482 g.write ('HEAP(${expected_ref_inner_sym.cname} , ' )
6461- g.expr_with_cast (arg.expr, arg_typ , expected_ref_inner_type)
6483+ g.expr_with_cast (effective_arg_expr, effective_arg_typ , expected_ref_inner_type)
64626484 g.write (')' )
64636485 }
64646486 }
0 commit comments