1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: check sumtype as mismatched type (#12743)

This commit is contained in:
yuyi 2021-12-07 06:31:47 +08:00 committed by GitHub
parent ef16a8ec54
commit 36fbd3c4fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 25 additions and 8 deletions

View File

@ -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
}
}

View File

@ -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

View File

@ -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 {

View File

@ -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)

View File

@ -0,0 +1,8 @@
type Type = bool | int | string
fn main() {
mut t := Type(123)
v := t as &int
t = 456
println(v)
}

View File

@ -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 {