checker: check sumtype as mismatched type (#12743)
parent
ef16a8ec54
commit
36fbd3c4fa
|
@ -1121,7 +1121,7 @@ pub fn (mut t Table) register_fn_concrete_types(fn_name string, types []Type) bo
|
|||
|
||||
// TODO: there is a bug when casting sumtype the other way if its pointer
|
||||
// so until fixed at least show v (not C) error `x(variant) = y(SumType*)`
|
||||
pub fn (t &Table) sumtype_has_variant(parent Type, variant Type) bool {
|
||||
pub fn (t &Table) sumtype_has_variant(parent Type, variant Type, is_as bool) bool {
|
||||
parent_sym := t.get_type_symbol(parent)
|
||||
if parent_sym.kind == .sum_type {
|
||||
parent_info := parent_sym.info as SumType
|
||||
|
@ -1129,14 +1129,14 @@ pub fn (t &Table) sumtype_has_variant(parent Type, variant Type) bool {
|
|||
if var_sym.kind == .aggregate {
|
||||
var_info := var_sym.info as Aggregate
|
||||
for var_type in var_info.types {
|
||||
if !t.sumtype_has_variant(parent, var_type) {
|
||||
if !t.sumtype_has_variant(parent, var_type, is_as) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
for v in parent_info.variants {
|
||||
if v.idx() == variant.idx() {
|
||||
if v.idx() == variant.idx() && (!is_as || v.nr_muls() == variant.nr_muls()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ pub fn (mut c Checker) check_basic(got ast.Type, expected ast.Type) bool {
|
|||
return true
|
||||
}
|
||||
// sum type
|
||||
if c.table.sumtype_has_variant(expected, c.table.mktyp(got)) {
|
||||
if c.table.sumtype_has_variant(expected, c.table.mktyp(got), false) {
|
||||
return true
|
||||
}
|
||||
// type alias
|
||||
|
|
|
@ -5421,8 +5421,10 @@ pub fn (mut c Checker) expr(node ast.Expr) ast.Type {
|
|||
type_sym := c.table.get_type_symbol(node.typ)
|
||||
if expr_type_sym.kind == .sum_type {
|
||||
c.ensure_type_exists(node.typ, node.pos) or {}
|
||||
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)
|
||||
if !c.table.sumtype_has_variant(node.expr_type, node.typ, true) {
|
||||
addr := '&'.repeat(node.typ.nr_muls())
|
||||
c.error('cannot cast `$expr_type_sym.name` to `$addr$type_sym.name`',
|
||||
node.pos)
|
||||
}
|
||||
} else if expr_type_sym.kind == .interface_ && type_sym.kind == .interface_ {
|
||||
c.ensure_type_exists(node.typ, node.pos) or {}
|
||||
|
@ -5734,7 +5736,7 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
|
|||
node.expr_type = c.promote_num(node.expr_type, xx)
|
||||
from_type = node.expr_type
|
||||
}
|
||||
if !c.table.sumtype_has_variant(to_type, from_type) && !to_type.has_flag(.optional) {
|
||||
if !c.table.sumtype_has_variant(to_type, from_type, false) && !to_type.has_flag(.optional) {
|
||||
c.error('cannot cast `$from_type_sym.name` to `$to_type_sym.name`', node.pos)
|
||||
}
|
||||
} else if mut to_type_sym.info is ast.Alias {
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
vlib/v/checker/tests/sumtype_as_mismatched_type.vv:5:9: error: cannot cast `Type` to `&int`
|
||||
3 | fn main() {
|
||||
4 | mut t := Type(123)
|
||||
5 | v := t as &int
|
||||
| ~~
|
||||
6 | t = 456
|
||||
7 | println(v)
|
|
@ -0,0 +1,8 @@
|
|||
type Type = bool | int | string
|
||||
|
||||
fn main() {
|
||||
mut t := Type(123)
|
||||
v := t as &int
|
||||
t = 456
|
||||
println(v)
|
||||
}
|
|
@ -2364,7 +2364,7 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
|
|||
unwrapped_expected_type
|
||||
}
|
||||
got_deref_type := if got_is_ptr { unwrapped_got_type.deref() } else { unwrapped_got_type }
|
||||
if g.table.sumtype_has_variant(expected_deref_type, got_deref_type) {
|
||||
if g.table.sumtype_has_variant(expected_deref_type, got_deref_type, false) {
|
||||
mut is_already_sum_type := false
|
||||
scope := g.file.scope.innermost(expr.position().pos)
|
||||
if expr is ast.Ident {
|
||||
|
|
Loading…
Reference in New Issue