diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 864d99f6ef..87e345e0a3 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2090,12 +2090,11 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { expr_type_sym := c.table.get_type_symbol(node.expr_type) type_sym := c.table.get_type_symbol(node.typ) if expr_type_sym.kind == .sum_type { - info := expr_type_sym.info as table.SumType if type_sym.kind == .placeholder { // Unknown type used in the right part of `as` c.error('unknown type `$type_sym.name`', node.pos) } - if node.typ !in info.variants { + if !c.table.sumtype_has_variant(node.expr_type, node.typ) { c.error('cannot cast `$expr_type_sym.name` to `$type_sym.name`', node.pos) // c.error('only $info.variants can be casted to `$typ`', node.pos) } @@ -2122,16 +2121,27 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { } ast.CastExpr { node.expr_type = c.expr(node.expr) - sym := c.table.get_type_symbol(node.expr_type) - if node.typ == table.string_type && !(sym.kind in [.byte, .byteptr] || - (sym.kind == .array && sym.name == 'array_byte')) { + from_type_sym := c.table.get_type_symbol(node.expr_type) + to_type_sym := c.table.get_type_symbol(node.typ) + if to_type_sym.kind == .sum_type { + if node.expr_type in [table.any_int_type, table.any_flt_type] { + node.expr_type = c.promote_num( + node.expr_type, + if node.expr_type == table.any_int_type { table.int_type } else { table.f64_type }, + ) + } + if !c.table.sumtype_has_variant(node.typ, node.expr_type) { + c.error('cannot cast `$from_type_sym.name` to `$to_type_sym.name`', node.pos) + } + } + else if node.typ == table.string_type && !(from_type_sym.kind in [.byte, .byteptr] || + (from_type_sym.kind == .array && from_type_sym.name == 'array_byte')) { type_name := c.table.type_to_str(node.expr_type) c.error('cannot cast type `$type_name` to string, use `x.str()` instead', node.pos) } - if node.expr_type == table.string_type { - cast_to_type_sym := c.table.get_type_symbol(node.typ) - if cast_to_type_sym.kind !in [.alias, .sum_type] { + else if node.expr_type == table.string_type { + if to_type_sym.kind !in [.alias] { mut error_msg := 'cannot cast a string' if node.expr is ast.StringLiteral { str_lit := node.expr as ast.StringLiteral diff --git a/vlib/v/tests/sum_type_test.v b/vlib/v/tests/sum_type_test.v index be0b1e8bb6..722985ce30 100644 --- a/vlib/v/tests/sum_type_test.v +++ b/vlib/v/tests/sum_type_test.v @@ -133,11 +133,20 @@ type Abc = int | string fn test_string_cast_to_sumtype() { a := Abc('test') + b := Abc(111) match a { + int { + assert false + } string { assert true } + } + match b { int { + assert true + } + string { assert false } }