checker: make a calling no-body function a checker error (#8265)

pull/8353/head
zakuro 2021-01-26 19:19:48 +09:00 committed by GitHub
parent 2007dbc7b5
commit 3959ba5751
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 38 additions and 1 deletions

View File

@ -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 {

View File

@ -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 | }

View File

@ -0,0 +1,9 @@
type Foo = int
fn (_ Foo) f()
fn f()
fn main() {
Foo(0).f()
f()
}

View File

@ -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

View File

@ -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

View File

@ -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 {