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_defer              bool // true inside `defer {}` blocks
 | ||||||
| 	inside_fn_arg             bool // `a`, `b` in `a.f(b)`
 | 	inside_fn_arg             bool // `a`, `b` in `a.f(b)`
 | ||||||
| 	inside_ct_attr            bool // true inside `[if expr]`
 | 	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 | 	inside_comptime_for_field bool | ||||||
| 	skip_flags                bool      // should `#flag` and `#include` be skipped
 | 	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
 | 	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_defer = false | ||||||
| 	c.inside_fn_arg = false | 	c.inside_fn_arg = false | ||||||
| 	c.inside_ct_attr = false | 	c.inside_ct_attr = false | ||||||
|  | 	c.inside_x_is_type = false | ||||||
| 	c.skip_flags = false | 	c.skip_flags = false | ||||||
| 	c.fn_level = 0 | 	c.fn_level = 0 | ||||||
| 	c.expr_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) { | fn (mut c Checker) block(node ast.Block) { | ||||||
| 	if node.is_unsafe { | 	if node.is_unsafe { | ||||||
|  | 		prev_unsafe := c.inside_unsafe | ||||||
| 		c.inside_unsafe = true | 		c.inside_unsafe = true | ||||||
| 		c.stmts(node.stmts) | 		c.stmts(node.stmts) | ||||||
| 		c.inside_unsafe = false | 		c.inside_unsafe = prev_unsafe | ||||||
| 	} else { | 	} else { | ||||||
| 		c.stmts(node.stmts) | 		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) | 			c.error('incorrect use of compile-time type', node.pos) | ||||||
| 		} | 		} | ||||||
| 		ast.EmptyExpr { | 		ast.EmptyExpr { | ||||||
|  | 			print_backtrace() | ||||||
| 			c.error('checker.expr(): unhandled EmptyExpr', token.Pos{}) | 			c.error('checker.expr(): unhandled EmptyExpr', token.Pos{}) | ||||||
|  | 			return ast.void_type | ||||||
| 		} | 		} | ||||||
| 		ast.CTempVar { | 		ast.CTempVar { | ||||||
| 			return node.typ | 			return node.typ | ||||||
|  | @ -2269,6 +2274,11 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type { | ||||||
| 			return c.struct_init(mut node) | 			return c.struct_init(mut node) | ||||||
| 		} | 		} | ||||||
| 		ast.TypeNode { | 		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 | 			return node.typ | ||||||
| 		} | 		} | ||||||
| 		ast.TypeOf { | 		ast.TypeOf { | ||||||
|  |  | ||||||
|  | @ -9,7 +9,9 @@ import v.util | ||||||
| import v.pkgconfig | import v.pkgconfig | ||||||
| 
 | 
 | ||||||
| fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type { | fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type { | ||||||
| 	node.left_type = c.expr(node.left) | 	if node.left !is ast.EmptyExpr { | ||||||
|  | 		node.left_type = c.expr(node.left) | ||||||
|  | 	} | ||||||
| 	if node.method_name == 'compile_error' { | 	if node.method_name == 'compile_error' { | ||||||
| 		c.error(node.args_var, node.pos) | 		c.error(node.args_var, node.pos) | ||||||
| 		return ast.void_type | 		return ast.void_type | ||||||
|  |  | ||||||
|  | @ -165,9 +165,12 @@ fn (mut c Checker) for_stmt(mut node ast.ForStmt) { | ||||||
| 	c.in_for_count++ | 	c.in_for_count++ | ||||||
| 	prev_loop_label := c.loop_label | 	prev_loop_label := c.loop_label | ||||||
| 	c.expected_type = ast.bool_type | 	c.expected_type = ast.bool_type | ||||||
| 	typ := c.expr(node.cond) | 	if node.cond !is ast.EmptyExpr { | ||||||
| 	if !node.is_inf && typ.idx() != ast.bool_type_idx && !c.pref.translated && !c.file.is_translated { | 		typ := c.expr(node.cond) | ||||||
| 		c.error('non-bool used as for condition', node.pos) | 		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 mut node.cond is ast.InfixExpr { | ||||||
| 		if node.cond.op == .key_is { | 		if node.cond.op == .key_is { | ||||||
|  |  | ||||||
|  | @ -12,7 +12,14 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { | ||||||
| 	mut left_type := c.expr(node.left) | 	mut left_type := c.expr(node.left) | ||||||
| 	node.left_type = left_type | 	node.left_type = left_type | ||||||
| 	c.expected_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) | 	mut right_type := c.expr(node.right) | ||||||
|  | 	if node.op == .key_is { | ||||||
|  | 		c.inside_x_is_type = false | ||||||
|  | 	} | ||||||
| 	node.right_type = right_type | 	node.right_type = right_type | ||||||
| 	if left_type.is_number() && !left_type.is_ptr() | 	if left_type.is_number() && !left_type.is_ptr() | ||||||
| 		&& right_type in [ast.int_literal_type, ast.float_literal_type] { | 		&& 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{} | 		return Result{} | ||||||
| 	} | 	} | ||||||
| 	content_type := vweb.mime_types[ext] | 	content_type := vweb.mime_types[ext] | ||||||
| 	if content_type.len == O { | 	if content_type.len == 0 { | ||||||
| 		eprintln('no MIME type found for extension $ext') | 		eprintln('no MIME type found for extension $ext') | ||||||
| 		ctx.server_error(500) | 		ctx.server_error(500) | ||||||
| 	} else { | 	} else { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue