checker: add error for `if c >= A && c <= Z {` in non generic functions
							parent
							
								
									96a9faf2fd
								
							
						
					
					
						commit
						4b3c3d9082
					
				|  | @ -89,6 +89,7 @@ pub mut: | |||
| 	inside_defer              bool // true inside `defer {}` blocks
 | ||||
| 	inside_fn_arg             bool // `a`, `b` in `a.f(b)`
 | ||||
| 	inside_ct_attr            bool // true inside `[if expr]`
 | ||||
| 	inside_x_is_type          bool // true inside the Type expression of `if x is Type {`
 | ||||
| 	inside_comptime_for_field bool | ||||
| 	skip_flags                bool      // should `#flag` and `#include` be skipped
 | ||||
| 	fn_level                  int       // 0 for the top level, 1 for `fn abc() {}`, 2 for a nested fn, etc
 | ||||
|  | @ -156,6 +157,7 @@ fn (mut c Checker) reset_checker_state_at_start_of_new_file() { | |||
| 	c.inside_defer = false | ||||
| 	c.inside_fn_arg = false | ||||
| 	c.inside_ct_attr = false | ||||
| 	c.inside_x_is_type = false | ||||
| 	c.skip_flags = false | ||||
| 	c.fn_level = 0 | ||||
| 	c.expr_level = 0 | ||||
|  | @ -1605,9 +1607,10 @@ fn (mut c Checker) assert_stmt(node ast.AssertStmt) { | |||
| 
 | ||||
| fn (mut c Checker) block(node ast.Block) { | ||||
| 	if node.is_unsafe { | ||||
| 		prev_unsafe := c.inside_unsafe | ||||
| 		c.inside_unsafe = true | ||||
| 		c.stmts(node.stmts) | ||||
| 		c.inside_unsafe = false | ||||
| 		c.inside_unsafe = prev_unsafe | ||||
| 	} else { | ||||
| 		c.stmts(node.stmts) | ||||
| 	} | ||||
|  | @ -2021,7 +2024,9 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type { | |||
| 			c.error('incorrect use of compile-time type', node.pos) | ||||
| 		} | ||||
| 		ast.EmptyExpr { | ||||
| 			print_backtrace() | ||||
| 			c.error('checker.expr(): unhandled EmptyExpr', token.Pos{}) | ||||
| 			return ast.void_type | ||||
| 		} | ||||
| 		ast.CTempVar { | ||||
| 			return node.typ | ||||
|  | @ -2269,6 +2274,11 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type { | |||
| 			return c.struct_init(mut node) | ||||
| 		} | ||||
| 		ast.TypeNode { | ||||
| 			if !c.inside_x_is_type && node.typ.has_flag(.generic) && unsafe { c.table.cur_fn != 0 } | ||||
| 				&& c.table.cur_fn.generic_names.len == 0 { | ||||
| 				c.error('unexpected generic variable in non-generic function `$c.table.cur_fn.name`', | ||||
| 					node.pos) | ||||
| 			} | ||||
| 			return node.typ | ||||
| 		} | ||||
| 		ast.TypeOf { | ||||
|  |  | |||
|  | @ -9,7 +9,9 @@ import v.util | |||
| import v.pkgconfig | ||||
| 
 | ||||
| fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type { | ||||
| 	if node.left !is ast.EmptyExpr { | ||||
| 		node.left_type = c.expr(node.left) | ||||
| 	} | ||||
| 	if node.method_name == 'compile_error' { | ||||
| 		c.error(node.args_var, node.pos) | ||||
| 		return ast.void_type | ||||
|  |  | |||
|  | @ -165,10 +165,13 @@ fn (mut c Checker) for_stmt(mut node ast.ForStmt) { | |||
| 	c.in_for_count++ | ||||
| 	prev_loop_label := c.loop_label | ||||
| 	c.expected_type = ast.bool_type | ||||
| 	if node.cond !is ast.EmptyExpr { | ||||
| 		typ := c.expr(node.cond) | ||||
| 	if !node.is_inf && typ.idx() != ast.bool_type_idx && !c.pref.translated && !c.file.is_translated { | ||||
| 		if !node.is_inf && typ.idx() != ast.bool_type_idx && !c.pref.translated | ||||
| 			&& !c.file.is_translated { | ||||
| 			c.error('non-bool used as for condition', node.pos) | ||||
| 		} | ||||
| 	} | ||||
| 	if mut node.cond is ast.InfixExpr { | ||||
| 		if node.cond.op == .key_is { | ||||
| 			if node.cond.right is ast.TypeNode && node.cond.left in [ast.Ident, ast.SelectorExpr] { | ||||
|  |  | |||
|  | @ -12,7 +12,14 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { | |||
| 	mut left_type := c.expr(node.left) | ||||
| 	node.left_type = left_type | ||||
| 	c.expected_type = left_type | ||||
| 
 | ||||
| 	if node.op == .key_is { | ||||
| 		c.inside_x_is_type = true | ||||
| 	} | ||||
| 	mut right_type := c.expr(node.right) | ||||
| 	if node.op == .key_is { | ||||
| 		c.inside_x_is_type = false | ||||
| 	} | ||||
| 	node.right_type = right_type | ||||
| 	if left_type.is_number() && !left_type.is_ptr() | ||||
| 		&& right_type in [ast.int_literal_type, ast.float_literal_type] { | ||||
|  |  | |||
|  | @ -0,0 +1,7 @@ | |||
| vlib/v/checker/tests/generic_type_name_in_non_generic_function.vv:3:10: error: unexpected generic variable in non-generic function `main` | ||||
|     1 | fn main() { | ||||
|     2 |     c := u8(`D`) | ||||
|     3 |     if c >= A && c <= Z { | ||||
|       |             ^ | ||||
|     4 |         println('yes') | ||||
|     5 |     } else { | ||||
|  | @ -0,0 +1,8 @@ | |||
| fn main() { | ||||
| 	c := u8(`D`) | ||||
| 	if c >= A && c <= Z { | ||||
| 		println('yes') | ||||
| 	} else { | ||||
| 		println('no') | ||||
| 	} | ||||
| } | ||||
|  | @ -252,7 +252,7 @@ pub fn (mut ctx Context) file(f_path string) Result { | |||
| 		return Result{} | ||||
| 	} | ||||
| 	content_type := vweb.mime_types[ext] | ||||
| 	if content_type.len == O { | ||||
| 	if content_type.len == 0 { | ||||
| 		eprintln('no MIME type found for extension $ext') | ||||
| 		ctx.server_error(500) | ||||
| 	} else { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue