From 6945f987cfac23e164b515590f54a230dbaa4cb3 Mon Sep 17 00:00:00 2001 From: crthpl <56052645+crthpl@users.noreply.github.com> Date: Wed, 28 Apr 2021 23:04:02 -0700 Subject: [PATCH] checker: fix sumtype comparison and sumtype in itself (#9917) --- vlib/v/ast/ast.v | 15 ++++----------- vlib/v/checker/checker.v | 6 +++++- vlib/v/checker/tests/sumtype_in_sumtype_err.out | 3 +++ vlib/v/checker/tests/sumtype_in_sumtype_err.vv | 1 + vlib/v/checker/tests/sumtype_mismatched_type.out | 5 +++++ vlib/v/checker/tests/sumtype_mismatched_type.vv | 4 ++++ vlib/v/parser/parser.v | 6 +++--- 7 files changed, 25 insertions(+), 15 deletions(-) create mode 100644 vlib/v/checker/tests/sumtype_in_sumtype_err.out create mode 100644 vlib/v/checker/tests/sumtype_in_sumtype_err.vv create mode 100644 vlib/v/checker/tests/sumtype_mismatched_type.out create mode 100644 vlib/v/checker/tests/sumtype_mismatched_type.vv diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 44d16012f9..4502206271 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -29,7 +29,7 @@ pub type ScopeObject = AsmRegister | ConstField | GlobalField | Var // TODO: replace Param pub type Node = CallArg | ConstField | EmptyNode | EnumField | Expr | File | GlobalField | IfBranch | MatchBranch | NodeError | Param | ScopeObject | SelectBranch | Stmt | StructField | - StructInitField | SumTypeVariant + StructInitField pub struct TypeNode { pub: @@ -952,13 +952,7 @@ pub: comments []Comment typ Type pub mut: - variants []SumTypeVariant -} - -pub struct SumTypeVariant { -pub: - typ Type - pos token.Position + variants []TypeNode } pub struct FnTypeDecl { @@ -1661,8 +1655,7 @@ pub fn (node Node) position() token.Position { StructField { return node.pos.extend(node.type_pos) } - MatchBranch, SelectBranch, EnumField, ConstField, StructInitField, GlobalField, CallArg, - SumTypeVariant { + MatchBranch, SelectBranch, EnumField, ConstField, StructInitField, GlobalField, CallArg { return node.pos } Param { @@ -1810,7 +1803,7 @@ pub fn (node Node) children() []Node { } TypeDecl { if node is SumTypeDecl { - children << node.variants.map(Node(it)) + children << node.variants.map(Node(Expr(it))) } } else {} diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 8b7256f308..09dd52840d 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -350,6 +350,9 @@ pub fn (mut c Checker) sum_type_decl(node ast.SumTypeDecl) { } else if sym.kind == .interface_ { c.error('sum type cannot hold an interface', variant.pos) } + if sym.name.trim_prefix(sym.mod + '.') == node.name { + c.error('sum type cannot hold itself', variant.pos) + } names_used << sym.name } } @@ -1109,7 +1112,8 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) ast.Type { c.error('unwrapped optional cannot be used in an infix expression', left_right_pos) } // Dual sides check (compatibility check) - if !c.symmetric_check(right_type, left_type) && !c.pref.translated { + if !(c.symmetric_check(left_type, right_type) && c.symmetric_check(right_type, left_type)) + && !c.pref.translated { // for type-unresolved consts if left_type == ast.void_type || right_type == ast.void_type { return ast.void_type diff --git a/vlib/v/checker/tests/sumtype_in_sumtype_err.out b/vlib/v/checker/tests/sumtype_in_sumtype_err.out new file mode 100644 index 0000000000..f491079028 --- /dev/null +++ b/vlib/v/checker/tests/sumtype_in_sumtype_err.out @@ -0,0 +1,3 @@ +vlib/v/checker/tests/sumtype_in_sumtype_err.vv:1:11: error: sum type cannot hold itself + 1 | type AA = AA | int + | ~~ \ No newline at end of file diff --git a/vlib/v/checker/tests/sumtype_in_sumtype_err.vv b/vlib/v/checker/tests/sumtype_in_sumtype_err.vv new file mode 100644 index 0000000000..7e53df8bb1 --- /dev/null +++ b/vlib/v/checker/tests/sumtype_in_sumtype_err.vv @@ -0,0 +1 @@ +type AA = AA | int diff --git a/vlib/v/checker/tests/sumtype_mismatched_type.out b/vlib/v/checker/tests/sumtype_mismatched_type.out new file mode 100644 index 0000000000..813f4723c6 --- /dev/null +++ b/vlib/v/checker/tests/sumtype_mismatched_type.out @@ -0,0 +1,5 @@ +vlib/v/checker/tests/sumtype_mismatched_type.vv:4:8: error: infix expr: cannot use `int literal` (right expression) as `AA` + 2 | + 3 | a := AA(3) + 4 | assert a == 3 + | ~~~~~~ \ No newline at end of file diff --git a/vlib/v/checker/tests/sumtype_mismatched_type.vv b/vlib/v/checker/tests/sumtype_mismatched_type.vv new file mode 100644 index 0000000000..d6a998bf5d --- /dev/null +++ b/vlib/v/checker/tests/sumtype_mismatched_type.vv @@ -0,0 +1,4 @@ +type AA = int | string + +a := AA(3) +assert a == 3 diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 801f74a064..f2ec38b509 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -2987,7 +2987,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl { decl_pos) return ast.FnTypeDecl{} } - mut sum_variants := []ast.SumTypeVariant{} + mut sum_variants := []ast.TypeNode{} p.check(.assign) mut type_pos := p.tok.position() mut comments := []ast.Comment{} @@ -3012,7 +3012,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl { mut type_end_pos := p.prev_tok.position() type_pos = type_pos.extend(type_end_pos) p.next() - sum_variants << ast.SumTypeVariant{ + sum_variants << { typ: first_type pos: type_pos } @@ -3024,7 +3024,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl { prev_tok := p.prev_tok type_end_pos = prev_tok.position() type_pos = type_pos.extend(type_end_pos) - sum_variants << ast.SumTypeVariant{ + sum_variants << { typ: variant_type pos: type_pos }