checker: make a calling no-body function a checker error (#8265)
							parent
							
								
									2007dbc7b5
								
							
						
					
					
						commit
						3959ba5751
					
				|  | @ -1432,6 +1432,10 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type { | |||
| 			c.fail_if_immutable(call_expr.left) | ||||
| 			// call_expr.is_mut = true
 | ||||
| 		} | ||||
| 		if (!left_type_sym.is_builtin() && method.mod != 'builtin') && method.language == .v | ||||
| 			&& method.no_body { | ||||
| 			c.error('cannot call a method that does not have a body', call_expr.pos) | ||||
| 		} | ||||
| 		if method.return_type == table.void_type && method.ctdefine.len > 0 | ||||
| 			&& method.ctdefine !in c.pref.compile_defines { | ||||
| 			call_expr.should_be_skipped = true | ||||
|  | @ -1726,6 +1730,9 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type { | |||
| 		// builtin C.m*, C.s* only - temp
 | ||||
| 		c.warn('function `$f.name` must be called from an `unsafe` block', call_expr.pos) | ||||
| 	} | ||||
| 	if f.mod != 'builtin' && f.language == .v && f.no_body { | ||||
| 		c.error('cannot call a function that does not have a body', call_expr.pos) | ||||
| 	} | ||||
| 	for generic_type in call_expr.generic_types { | ||||
| 		sym := c.table.get_type_symbol(generic_type) | ||||
| 		if sym.kind == .placeholder { | ||||
|  |  | |||
|  | @ -0,0 +1,13 @@ | |||
| vlib/v/checker/tests/fn_call_no_body.vv:7:9: error: cannot call a method that does not have a body | ||||
|     5 | | ||||
|     6 | fn main() { | ||||
|     7 |     Foo(0).f() | ||||
|       |            ~~~ | ||||
|     8 |     f() | ||||
|     9 | } | ||||
| vlib/v/checker/tests/fn_call_no_body.vv:8:2: error: cannot call a function that does not have a body | ||||
|     6 | fn main() { | ||||
|     7 |     Foo(0).f() | ||||
|     8 |     f() | ||||
|       |     ~~~ | ||||
|     9 | } | ||||
|  | @ -0,0 +1,9 @@ | |||
| type Foo = int | ||||
| fn (_ Foo) f() | ||||
| 
 | ||||
| fn f() | ||||
| 
 | ||||
| fn main() { | ||||
| 	Foo(0).f() | ||||
| 	f() | ||||
| } | ||||
|  | @ -315,6 +315,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { | |||
| 		return_type = p.parse_type() | ||||
| 	} | ||||
| 	mut type_sym_method_idx := 0 | ||||
| 	no_body := p.tok.kind != .lcbr | ||||
| 	// Register
 | ||||
| 	if is_method { | ||||
| 		mut type_sym := p.table.get_type_symbol(rec_type) | ||||
|  | @ -345,6 +346,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { | |||
| 			is_pub: is_pub | ||||
| 			is_deprecated: is_deprecated | ||||
| 			is_unsafe: is_unsafe | ||||
| 			no_body: no_body | ||||
| 			mod: p.mod | ||||
| 			attrs: p.attrs | ||||
| 		}) | ||||
|  | @ -369,6 +371,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { | |||
| 			is_pub: is_pub | ||||
| 			is_deprecated: is_deprecated | ||||
| 			is_unsafe: is_unsafe | ||||
| 			no_body: no_body | ||||
| 			mod: p.mod | ||||
| 			attrs: p.attrs | ||||
| 			language: language | ||||
|  | @ -378,7 +381,6 @@ fn (mut p Parser) fn_decl() ast.FnDecl { | |||
| 	// Body
 | ||||
| 	p.cur_fn_name = name | ||||
| 	mut stmts := []ast.Stmt{} | ||||
| 	no_body := p.tok.kind != .lcbr | ||||
| 	body_start_pos := p.peek_tok.position() | ||||
| 	if p.tok.kind == .lcbr { | ||||
| 		p.inside_fn = true | ||||
|  |  | |||
|  | @ -32,6 +32,7 @@ pub: | |||
| 	is_deprecated  bool | ||||
| 	is_unsafe      bool | ||||
| 	is_placeholder bool | ||||
| 	no_body        bool | ||||
| 	mod            string | ||||
| 	ctdefine       string // compile time define. myflag, when [if myflag] tag
 | ||||
| 	attrs          []Attr | ||||
|  |  | |||
|  | @ -573,6 +573,11 @@ pub fn (t &TypeSymbol) is_primitive() bool { | |||
| 	return t.is_number() || t.is_pointer() || t.is_string() | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (t &TypeSymbol) is_builtin() bool { | ||||
| 	return t.mod == 'builtin' | ||||
| } | ||||
| 
 | ||||
| // for debugging/errors only, perf is not an issue
 | ||||
| pub fn (k Kind) str() string { | ||||
| 	k_str := match k { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue