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