diff --git a/vlib/builtin/builtin.v b/vlib/builtin/builtin.v index 4d2f8c1987..d88e7d0684 100644 --- a/vlib/builtin/builtin.v +++ b/vlib/builtin/builtin.v @@ -170,3 +170,10 @@ pub fn is_atty(fd int) int { return C.isatty(fd) } } + +fn __as_cast(obj voidptr, obj_type, expected_type int) voidptr { + if obj_type != expected_type { + panic('as cast: cannot cast $obj_type to $expected_type') + } + return obj +} diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 32017a07fe..db5d274b51 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -945,13 +945,7 @@ fn (mut g Gen) expr(node ast.Expr) { } } ast.AsCast { - styp := g.typ(it.typ) - expr_type_sym := g.table.get_type_symbol(it.expr_type) - if expr_type_sym.kind == .sum_type { - g.write('/* as */ *($styp*)') - g.expr(it.expr) - g.write('.obj') - } + g.as_cast(it) } ast.AssignExpr { g.assign_expr(it) @@ -1396,7 +1390,8 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { g.expr_with_cast(node.right, node.right_type, info.elem_type) g.write(' })') } - } else if (node.left_type == node.right_type) && table.is_float(node.left_type) && node.op in [.eq, .ne] { + } else if (node.left_type == node.right_type) && table.is_float(node.left_type) && node.op in + [.eq, .ne] { // floats should be compared with epsilon if node.left_type == table.f64_type_idx { if node.op == .eq { @@ -2911,6 +2906,26 @@ fn (mut g Gen) go_stmt(node ast.GoStmt) { } } +fn (mut g Gen) as_cast(node ast.AsCast) { + // Make sure the sum type can be cast to this type (the types + // are the same), otherwise panic. + // g.insert_before(' + styp := g.typ(node.typ) + expr_type_sym := g.table.get_type_symbol(node.expr_type) + if expr_type_sym.kind == .sum_type { + g.write('/* as */ *($styp*)') + g.expr(node.expr) + g.write('.obj') + /* + g.write('/* as */ *($styp*)__as_cast(') + g.expr(node.expr) + g.write('.obj, ') + g.expr(node.expr) + g.write('.typ, /*expected:*/$node.typ)') +*/ + } +} + fn (mut g Gen) is_expr(node ast.InfixExpr) { g.expr(node.left) g.write('.typ == ') diff --git a/vlib/v/tests/inout/bad_st_as.out b/vlib/v/tests/inout/bad_st_as.out new file mode 100644 index 0000000000..f3355d49b5 --- /dev/null +++ b/vlib/v/tests/inout/bad_st_as.out @@ -0,0 +1,2 @@ +Foo +V panic: as cast: cannot cast diff --git a/vlib/v/tests/inout/bad_st_as.vv b/vlib/v/tests/inout/bad_st_as.vv new file mode 100644 index 0000000000..d099b15b55 --- /dev/null +++ b/vlib/v/tests/inout/bad_st_as.vv @@ -0,0 +1,13 @@ +struct Struct {struct_name string } +struct Interface {interface_name string} + +type Info = Struct | Interface + +fn main() { + mut info := Info{} + info = Struct{struct_name: 'Foo'} + s := info as Struct + println(s.struct_name) + i := info as Interface // wrong + println(i.interface_name) +}