Skip to content

Commit

Permalink
checker: check sumtype as mismatched type (#12743)
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyi98 committed Dec 6, 2021
1 parent ef16a8e commit 36fbd3c
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 8 deletions.
6 changes: 3 additions & 3 deletions vlib/v/ast/table.v
Expand Up @@ -1121,22 +1121,22 @@ 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
var_sym := t.get_type_symbol(variant)
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
}
}
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/check_types.v
Expand Up @@ -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
Expand Down
8 changes: 5 additions & 3 deletions vlib/v/checker/checker.v
Expand Up @@ -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 {}
Expand Down Expand Up @@ -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 {
Expand Down
7 changes: 7 additions & 0 deletions vlib/v/checker/tests/sumtype_as_mismatched_type.out
@@ -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)
8 changes: 8 additions & 0 deletions vlib/v/checker/tests/sumtype_as_mismatched_type.vv
@@ -0,0 +1,8 @@
type Type = bool | int | string

fn main() {
mut t := Type(123)
v := t as &int
t = 456
println(v)
}
2 changes: 1 addition & 1 deletion vlib/v/gen/c/cgen.v
Expand Up @@ -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 {
Expand Down

0 comments on commit 36fbd3c

Please sign in to comment.