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

checker: fix sum type operator check (#6815)

This commit is contained in:
Daniel Däschle 2020-11-17 21:26:40 +01:00 committed by GitHub
parent ee5ad2a653
commit ed874ffc5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 42 additions and 4 deletions

View File

@ -861,6 +861,12 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
c.error('string types only have the following operators defined: `==`, `!=`, `<`, `>`, `<=`, `>=`, and `+`', c.error('string types only have the following operators defined: `==`, `!=`, `<`, `>`, `<=`, `>=`, and `+`',
infix_expr.pos) infix_expr.pos)
} }
// sum types can't have any infix operation except of "is", is is checked before and doesn't reach this
if c.table.type_kind(left_type) == .union_sum_type {
c.error('cannot use operator `$infix_expr.op` with `$left.name`', infix_expr.pos)
} else if c.table.type_kind(right_type) == .union_sum_type {
c.error('cannot use operator `$infix_expr.op` with `$right.name`', infix_expr.pos)
}
// Dual sides check (compatibility check) // Dual sides check (compatibility check)
if !c.symmetric_check(right_type, left_type) && !c.pref.translated { if !c.symmetric_check(right_type, left_type) && !c.pref.translated {
// for type-unresolved consts // for type-unresolved consts

View File

@ -0,0 +1,14 @@
vlib/v/checker/tests/sum_type_infix_err.vv:5:9: error: cannot use operator `+` with `Abc`
3 | fn main() {
4 | x := Abc(0)
5 | _ := x + Abc(5)
| ^
6 | _ := 'test' + x
7 | _ = unsafe{&x + 5}
vlib/v/checker/tests/sum_type_infix_err.vv:6:14: error: cannot use operator `+` with `Abc`
4 | x := Abc(0)
5 | _ := x + Abc(5)
6 | _ := 'test' + x
| ^
7 | _ = unsafe{&x + 5}
8 | }

View File

@ -0,0 +1,8 @@
__type Abc = int | string
fn main() {
x := Abc(0)
_ := x + Abc(5)
_ := 'test' + x
_ = unsafe{&x + 5}
}

View File

@ -1,18 +1,18 @@
vlib/v/checker/tests/sum_type_mutable_cast_err.vv:23:10: error: infix expr: cannot use `any_int` (right expression) as `Abc` vlib/v/checker/tests/sum_type_mutable_cast_err.vv:23:10: error: cannot use operator `+` with `Abc`
21 | mut x := Abc(0) 21 | mut x := Abc(0)
22 | if x is int { 22 | if x is int {
23 | _ := x + 5 23 | _ := x + 5
| ^ | ^
24 | } 24 | }
25 | f := Foo{Bar{Abc(0)}} 25 | f := Foo{Bar{Abc(0)}}
vlib/v/checker/tests/sum_type_mutable_cast_err.vv:27:14: error: infix expr: cannot use `any_int` (right expression) as `Abc` vlib/v/checker/tests/sum_type_mutable_cast_err.vv:27:14: error: cannot use operator `+` with `Abc`
25 | f := Foo{Bar{Abc(0)}} 25 | f := Foo{Bar{Abc(0)}}
26 | if f.b.a is int { 26 | if f.b.a is int {
27 | _ := f.b.a + 5 27 | _ := f.b.a + 5
| ^ | ^
28 | } 28 | }
29 | mut f2 := Foo2{Bar2{Abc(0)}} 29 | mut f2 := Foo2{Bar2{Abc(0)}}
vlib/v/checker/tests/sum_type_mutable_cast_err.vv:31:14: error: infix expr: cannot use `any_int` (right expression) as `Abc` vlib/v/checker/tests/sum_type_mutable_cast_err.vv:31:14: error: cannot use operator `+` with `Abc`
29 | mut f2 := Foo2{Bar2{Abc(0)}} 29 | mut f2 := Foo2{Bar2{Abc(0)}}
30 | if f2.b.a is int { 30 | if f2.b.a is int {
31 | _ := f.b.a + 5 31 | _ := f.b.a + 5

View File

@ -26,7 +26,9 @@ pub enum Language {
// Represents a type that only needs an identifier, e.g. int, array_int. // Represents a type that only needs an identifier, e.g. int, array_int.
// A pointer type `&T` would have a TypeSymbol `T`. // A pointer type `&T` would have a TypeSymbol `T`.
// Note: For a Type, use Table.type_to_str(typ) not TypeSymbol.name. // Note: For a Type, use:
// * Table.type_to_str(typ) not TypeSymbol.name.
// * Table.type_kind(typ) not TypeSymbol.kind.
// Each TypeSymbol is entered into `Table.types`. // Each TypeSymbol is entered into `Table.types`.
// See also: Table.get_type_symbol. // See also: Table.get_type_symbol.
pub struct TypeSymbol { pub struct TypeSymbol {
@ -363,6 +365,14 @@ pub:
func Fn func Fn
} }
// returns TypeSymbol kind only if there are no type modifiers
pub fn (table &Table) type_kind(typ Type) Kind {
if typ.nr_muls() > 0 || typ.has_flag(.optional) {
return Kind.placeholder
}
return table.get_type_symbol(typ).kind
}
pub enum Kind { pub enum Kind {
placeholder placeholder
void void