From 65b2bc6d4efab9804150322d899814d23713ef95 Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Tue, 23 Dec 2025 18:12:32 +0800 Subject: [PATCH] checker,cgen: fix cast_expr() for alias (fix #26076) (#26079) --- vlib/v/ast/types.v | 6 ++++++ vlib/v/checker/checker.v | 7 +++++++ vlib/v/gen/c/cgen.v | 8 ++++++-- vlib/v/tests/casts/cast_to_alias_test.v | 26 +++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/vlib/v/ast/types.v b/vlib/v/ast/types.v index 4a2e51ba9..e20eb5b46 100644 --- a/vlib/v/ast/types.v +++ b/vlib/v/ast/types.v @@ -397,6 +397,12 @@ pub fn (t Type) deref() Type { return t & 0xff00ffff | (nr_muls - 1) << 16 } +// flags returns type's flags +@[inline] +pub fn (t Type) flags() int { + return t >> 16 +} + // has_flag returns whether the given named `flag` is set @[inline] pub fn (t Type) has_flag(flag TypeFlag) bool { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 61d8db7c3..bee28ab5a 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3539,6 +3539,13 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { } else { to_type } + + if final_to_sym == final_from_sym && final_to_type.flags() == from_type.flags() + && to_type.flags() == from_type.flags() { + // type alias, and flags are same, e.g. option, result, nr_muls... + return node.typ + } + final_to_is_ptr := to_type.is_ptr() || final_to_type.is_ptr() c.markused_castexpr(mut node, to_type, mut final_to_sym) if to_type.has_flag(.result) { diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 2be6f1c03..baf0f988f 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5663,6 +5663,8 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { if g.comptime.is_comptime(node.expr) { expr_type = g.unwrap_generic(g.type_resolver.get_type(node.expr)) } + expr_sym := g.table.sym(expr_type) + final_expr_sym := g.table.final_sym(expr_type) node_typ_is_option := node.typ.has_flag(.option) if sym.kind in [.sum_type, .interface] { if g.table.unaliased_type(expr_type) == node_typ { @@ -5679,8 +5681,10 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { } else { g.expr_with_cast(node.expr, expr_type, node_typ) } - } else if !node_typ_is_option && !node_typ.is_ptr() && sym.info is ast.Struct - && !sym.info.is_typedef { + } else if !node_typ_is_option && !node_typ.is_ptr() && !expr_type.is_ptr() + && ((sym.info is ast.Struct && !sym.info.is_typedef) + || (expr_sym.kind == .alias && final_expr_sym.info is ast.Struct + && !final_expr_sym.info.is_typedef)) { // deprecated, replaced by Struct{...exr} styp := g.styp(node_typ) g.write('*((${styp} *)(&') diff --git a/vlib/v/tests/casts/cast_to_alias_test.v b/vlib/v/tests/casts/cast_to_alias_test.v index 80556a43d..342bbf6ab 100644 --- a/vlib/v/tests/casts/cast_to_alias_test.v +++ b/vlib/v/tests/casts/cast_to_alias_test.v @@ -49,3 +49,29 @@ fn test_cast_to_alias_of_ref_struct() { println(typeof(bar).name) assert typeof(bar).name == '&Alias' } + +type Bar1 = Foo +type Bar2 = Foo +type Bar3 = Foo + +fn test_cast_to_from_alias() { + bar2 := Bar2{ + x: 100 + } + foo := Foo(bar2) + bar1 := Bar1(bar2) + bar3 := Bar3(bar2) + assert typeof(foo).name == 'Foo' + assert typeof(bar1).name == 'Bar1' + assert typeof(bar2).name == 'Bar2' + assert typeof(bar3).name == 'Bar3' + + foo1_1 := Foo(foo) + bar1_1 := Bar1(foo) + bar2_1 := Bar2(foo) + bar3_1 := Bar3(foo) + assert typeof(foo1_1).name == 'Foo' + assert typeof(bar1_1).name == 'Bar1' + assert typeof(bar2_1).name == 'Bar2' + assert typeof(bar3_1).name == 'Bar3' +} -- 2.39.5