checker: avert if else is unnecessary

pull/4599/head
Enzo Baldisserri 2020-04-25 21:51:44 +02:00 committed by GitHub
parent e0f9c042c1
commit 3e68e429b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 96 additions and 58 deletions

View File

@ -21,7 +21,6 @@ fn tag(l Level) string {
.warn { term.yellow('WARN ') } .warn { term.yellow('WARN ') }
.info { term.white('INFO ') } .info { term.white('INFO ') }
.debug { term.blue('DEBUG') } .debug { term.blue('DEBUG') }
else { ' ' }
} }
} }

View File

@ -150,8 +150,7 @@ mut res := match fmt_date {
.space{ .space{
' ' ' '
} }
else { })
'unknown enumeration $fmt_dlmtr'}})
return res return res
} }

View File

@ -42,10 +42,6 @@ pub fn compile(command string, pref &pref.Preferences) {
.x64 { .x64 {
b.compile_x64() b.compile_x64()
} }
else {
eprintln('backend not implemented `$pref.backend`')
exit(1)
}
} }
if pref.is_stats { if pref.is_stats {
tmark.stop() tmark.stop()

View File

@ -1601,22 +1601,14 @@ fn (mut c Checker) match_exprs(node mut ast.MatchExpr, type_sym table.TypeSymbol
// this is achieved either by putting an else // this is achieved either by putting an else
// or, when the match is on a sum type or an enum // or, when the match is on a sum type or an enum
// by listing all variants or values // by listing all variants or values
if !node.branches[node.branches.len - 1].is_else { mut is_exhaustive := true
for i, branch in node.branches { mut unhandled := []string
if branch.is_else && i != node.branches.len - 1 {
c.error('`else` must be the last branch of `match`', branch.pos)
return
}
}
mut err := false
mut err_details := 'match must be exhaustive'
unhandled := []string
match type_sym.info { match type_sym.info {
table.SumType { table.SumType {
for v in it.variants { for v in it.variants {
v_str := c.table.type_to_str(v) v_str := c.table.type_to_str(v)
if v_str !in branch_exprs { if v_str !in branch_exprs {
err = true is_exhaustive = false
unhandled << '`$v_str`' unhandled << '`$v_str`'
} }
} }
@ -1624,24 +1616,43 @@ fn (mut c Checker) match_exprs(node mut ast.MatchExpr, type_sym table.TypeSymbol
table.Enum { table.Enum {
for v in it.vals { for v in it.vals {
if v !in branch_exprs { if v !in branch_exprs {
err = true is_exhaustive = false
unhandled << '`.$v`' unhandled << '`.$v`'
} }
} }
} }
else { else {
println('else') is_exhaustive = false
err = true
} }
} }
if err { mut else_branch := node.branches[node.branches.len - 1]
mut has_else := else_branch.is_else
if !has_else {
for i, branch in node.branches {
if branch.is_else && i != node.branches.len - 1 {
c.error('`else` must be the last branch of `match`', branch.pos)
else_branch = branch
has_else = true
}
}
}
if is_exhaustive {
if has_else {
c.error('match expression is exhaustive, `else` is unnecessary', else_branch.pos)
}
return
}
if has_else {
return
}
mut err_details := 'match must be exhaustive'
if unhandled.len > 0 { if unhandled.len > 0 {
err_details += ' (add match branches for: ' + unhandled.join(', ') + ' or `else {}` at the end)' err_details += ' (add match branches for: ' + unhandled.join(', ') + ' or `else {}` at the end)'
} else {
err_details += ' (add `else {}` at the end)'
} }
c.error(err_details, node.pos) c.error(err_details, node.pos)
} }
}
}
pub fn (mut c Checker) if_expr(node mut ast.IfExpr) table.Type { pub fn (mut c Checker) if_expr(node mut ast.IfExpr) table.Type {
if c.expected_type != table.void_type { if c.expected_type != table.void_type {

View File

@ -5,3 +5,17 @@ vlib/v/checker/tests/inout/match_expr_else.v:5:6: error: match must be exhaustiv
~~~~~~~~~ ~~~~~~~~~
6| int { 6| int {
7| 'int' 7| 'int'
vlib/v/checker/tests/inout/match_expr_else.v:23:3: error: match expression is exhaustive, `else` is unnecessary
21| 'f64'
22| }
23| else {
~~~~~~
24| 'else'
25| }
vlib/v/checker/tests/inout/match_expr_else.v:34:3: error: `else` must be the last branch of `match`
32| 'string'
33| }
34| else {
~~~~~~
35| 'else'
36| }

View File

@ -10,4 +10,32 @@ fn main() {
'string' 'string'
} }
} }
_ := match x {
int {
'int'
}
string {
'string'
}
f64 {
'f64'
}
else {
'else'
}
}
_ := match x {
int {
'int'
}
string {
'string'
}
else {
'else'
}
f64 {
'f64'
}
}
} }

View File

@ -107,11 +107,6 @@ pub fn (o OS) str() string {
.haiku { .haiku {
return 'Haiku' return 'Haiku'
} }
else {
//TODO Remove when V is smart enough to know that there's no other possibilities
//should never be reached as all enum types have been enumerated
panic('unknown OS enum type: $o')
}
} }
} }

View File

@ -55,10 +55,6 @@ fn test_match_expression_on_sumtype_full(){
c = 2 c = 2
eprintln('hi') eprintln('hi')
'a string' 'a string'
}else{
c = 3
eprintln('hi')
'unknown'
} }
} }
assert res == 'an integer' assert res == 'an integer'