checker: avert if else is unnecessary
							parent
							
								
									e0f9c042c1
								
							
						
					
					
						commit
						3e68e429b6
					
				|  | @ -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 { '     ' } |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -150,8 +150,7 @@ mut 	res := match fmt_date { | ||||||
| 		.space{ | 		.space{ | ||||||
| 			' ' | 			' ' | ||||||
| 		} | 		} | ||||||
| 		else { | 	}) | ||||||
| 			'unknown enumeration $fmt_dlmtr'}}) |  | ||||||
| 	return res | 	return res | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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() | ||||||
|  |  | ||||||
|  | @ -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 { | ||||||
|  |  | ||||||
|  | @ -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|         } | ||||||
|  |  | ||||||
|  | @ -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' | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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') |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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' | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue