From 62f2313ed9d73664e315542077be4264b8eeeeec Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Mon, 22 Dec 2025 19:04:47 +0800 Subject: [PATCH 1/5] checker: fix cast_expr() for alias --- vlib/v/checker/checker.v | 6 ++++++ vlib/v/tests/casts/cast_to_alias_test.v | 26 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 61d8db7c316d81..405400347bbe0a 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3539,6 +3539,12 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { } else { to_type } + + if final_to_sym == final_from_sym { + // type alias + return to_type + } + 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/tests/casts/cast_to_alias_test.v b/vlib/v/tests/casts/cast_to_alias_test.v index 80556a43dde20d..342bbf6ab334cc 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' +} From 1172aed996978f3511482b5c6cbd9f1ee42fa1f7 Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Mon, 22 Dec 2025 20:03:22 +0800 Subject: [PATCH 2/5] fix flags --- vlib/v/ast/types.v | 6 ++++++ vlib/v/checker/checker.v | 7 ++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/vlib/v/ast/types.v b/vlib/v/ast/types.v index 4a2e51ba943581..e20eb5b4657d43 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 405400347bbe0a..bee28ab5a3b4f2 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3540,9 +3540,10 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { to_type } - if final_to_sym == final_from_sym { - // type alias - return 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() From 1aa2afc1e1a924c3cb9ae805de669d518d8f6844 Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Mon, 22 Dec 2025 22:08:29 +0800 Subject: [PATCH 3/5] fix cgen, use ptr for struct alias --- vlib/v/gen/c/cgen.v | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 32b5a0a7549370..e017548462d2d5 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5652,6 +5652,7 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { node_typ := g.unwrap_generic(node.typ) mut expr_type := node.expr_type sym := g.table.sym(node_typ) + final_sym := g.table.final_sym(node_typ) if g.comptime.is_comptime(node.expr) { expr_type = g.unwrap_generic(g.type_resolver.get_type(node.expr)) } @@ -5671,8 +5672,9 @@ 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) + || (sym.kind == .alias && final_sym.kind == .struct)) { // deprecated, replaced by Struct{...exr} styp := g.styp(node_typ) g.write('*((${styp} *)(&') From d17faa6bd398b3ff8ce1ecf961767e04eb1925e8 Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Mon, 22 Dec 2025 23:08:33 +0800 Subject: [PATCH 4/5] fix --- vlib/v/gen/c/cgen.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index e017548462d2d5..3b46dfe12690f0 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5674,7 +5674,7 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { } } else if !node_typ_is_option && !node_typ.is_ptr() && !expr_type.is_ptr() && ((sym.info is ast.Struct && !sym.info.is_typedef) - || (sym.kind == .alias && final_sym.kind == .struct)) { + || (sym.kind == .alias && final_sym.info is ast.Struct && !final_sym.info.is_typedef)) { // deprecated, replaced by Struct{...exr} styp := g.styp(node_typ) g.write('*((${styp} *)(&') From 6422d704cc3d308c92eb5e508fa07c4941a5a342 Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Tue, 23 Dec 2025 09:20:03 +0800 Subject: [PATCH 5/5] fix expr_sym --- vlib/v/gen/c/cgen.v | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 3b46dfe12690f0..8888448f0f87ee 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5652,10 +5652,11 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { node_typ := g.unwrap_generic(node.typ) mut expr_type := node.expr_type sym := g.table.sym(node_typ) - final_sym := g.table.final_sym(node_typ) 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 { @@ -5674,7 +5675,8 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { } } else if !node_typ_is_option && !node_typ.is_ptr() && !expr_type.is_ptr() && ((sym.info is ast.Struct && !sym.info.is_typedef) - || (sym.kind == .alias && final_sym.info is ast.Struct && !final_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} *)(&')