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 61d8db7c316d81..bee28ab5a3b4f2 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 32b5a0a7549370..8888448f0f87ee 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5655,6 +5655,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 { @@ -5671,8 +5673,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 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' +}