Skip to content

Commit 65b2bc6

Browse files
authored
checker,cgen: fix cast_expr() for alias (fix #26076) (#26079)
1 parent 5d6f1a9 commit 65b2bc6

4 files changed

Lines changed: 45 additions & 2 deletions

File tree

‎vlib/v/ast/types.v‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,12 @@ pub fn (t Type) deref() Type {
397397
return t & 0xff00ffff | (nr_muls - 1) << 16
398398
}
399399

400+
// flags returns type's flags
401+
@[inline]
402+
pub fn (t Type) flags() int {
403+
return t >> 16
404+
}
405+
400406
// has_flag returns whether the given named `flag` is set
401407
@[inline]
402408
pub fn (t Type) has_flag(flag TypeFlag) bool {

‎vlib/v/checker/checker.v‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3539,6 +3539,13 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
35393539
} else {
35403540
to_type
35413541
}
3542+
3543+
if final_to_sym == final_from_sym && final_to_type.flags() == from_type.flags()
3544+
&& to_type.flags() == from_type.flags() {
3545+
// type alias, and flags are same, e.g. option, result, nr_muls...
3546+
return node.typ
3547+
}
3548+
35423549
final_to_is_ptr := to_type.is_ptr() || final_to_type.is_ptr()
35433550
c.markused_castexpr(mut node, to_type, mut final_to_sym)
35443551
if to_type.has_flag(.result) {

‎vlib/v/gen/c/cgen.v‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5663,6 +5663,8 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) {
56635663
if g.comptime.is_comptime(node.expr) {
56645664
expr_type = g.unwrap_generic(g.type_resolver.get_type(node.expr))
56655665
}
5666+
expr_sym := g.table.sym(expr_type)
5667+
final_expr_sym := g.table.final_sym(expr_type)
56665668
node_typ_is_option := node.typ.has_flag(.option)
56675669
if sym.kind in [.sum_type, .interface] {
56685670
if g.table.unaliased_type(expr_type) == node_typ {
@@ -5679,8 +5681,10 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) {
56795681
} else {
56805682
g.expr_with_cast(node.expr, expr_type, node_typ)
56815683
}
5682-
} else if !node_typ_is_option && !node_typ.is_ptr() && sym.info is ast.Struct
5683-
&& !sym.info.is_typedef {
5684+
} else if !node_typ_is_option && !node_typ.is_ptr() && !expr_type.is_ptr()
5685+
&& ((sym.info is ast.Struct && !sym.info.is_typedef)
5686+
|| (expr_sym.kind == .alias && final_expr_sym.info is ast.Struct
5687+
&& !final_expr_sym.info.is_typedef)) {
56845688
// deprecated, replaced by Struct{...exr}
56855689
styp := g.styp(node_typ)
56865690
g.write('*((${styp} *)(&')

‎vlib/v/tests/casts/cast_to_alias_test.v‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,29 @@ fn test_cast_to_alias_of_ref_struct() {
4949
println(typeof(bar).name)
5050
assert typeof(bar).name == '&Alias'
5151
}
52+
53+
type Bar1 = Foo
54+
type Bar2 = Foo
55+
type Bar3 = Foo
56+
57+
fn test_cast_to_from_alias() {
58+
bar2 := Bar2{
59+
x: 100
60+
}
61+
foo := Foo(bar2)
62+
bar1 := Bar1(bar2)
63+
bar3 := Bar3(bar2)
64+
assert typeof(foo).name == 'Foo'
65+
assert typeof(bar1).name == 'Bar1'
66+
assert typeof(bar2).name == 'Bar2'
67+
assert typeof(bar3).name == 'Bar3'
68+
69+
foo1_1 := Foo(foo)
70+
bar1_1 := Bar1(foo)
71+
bar2_1 := Bar2(foo)
72+
bar3_1 := Bar3(foo)
73+
assert typeof(foo1_1).name == 'Foo'
74+
assert typeof(bar1_1).name == 'Bar1'
75+
assert typeof(bar2_1).name == 'Bar2'
76+
assert typeof(bar3_1).name == 'Bar3'
77+
}

0 commit comments

Comments
 (0)