Skip to content

Commit 485983e

Browse files
authored
checker: disallow static fn call when receiver type is unknown (#21970)
1 parent 2d43f38 commit 485983e

File tree

5 files changed

+25
-0
lines changed

5 files changed

+25
-0
lines changed

vlib/v/ast/ast.v

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,7 @@ pub:
558558
receiver_pos token.Pos // `(u User)` in `fn (u User) name()` position
559559
is_method bool
560560
is_static_type_method bool // true for `fn Foo.bar() {}`
561+
static_type_pos token.Pos // `Foo` in `fn Foo.bar() {}`
561562
method_type_pos token.Pos // `User` in ` fn (u User)` position
562563
method_idx int
563564
rec_mut bool // is receiver mutable

vlib/v/checker/fn.v

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,13 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
312312
&& node.name.after_char(`.`) in reserved_type_names {
313313
c.error('top level declaration cannot shadow builtin type', node.pos)
314314
}
315+
if _ := node.name.index('__static__') {
316+
if sym := c.table.find_sym(node.name.all_before('__static__')) {
317+
if sym.kind == .placeholder {
318+
c.error('unknown type `${sym.name}`', node.static_type_pos)
319+
}
320+
}
321+
}
315322
}
316323
}
317324
if node.return_type != ast.Type(0) {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
vlib/v/checker/tests/static_fn_call_no_struct_decl_err.vv:5:4: error: unknown type `Mystery`
2+
3 | }
3+
4 |
4+
5 | fn Mystery.hey() {
5+
| ~~~~~~~
6+
6 | println('hey')
7+
7 | }
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
Mystery.hey()
3+
}
4+
5+
fn Mystery.hey() {
6+
println('hey')
7+
}

vlib/v/parser/fn.v

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,13 +308,15 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
308308
mut name := ''
309309
mut type_sym := p.table.sym(rec.typ)
310310
mut name_pos := p.tok.pos()
311+
mut static_type_pos := p.tok.pos()
311312
if p.tok.kind == .name {
312313
mut check_name := ''
313314
// TODO: high order fn
314315
is_static_type_method = p.tok.lit.len > 0 && p.tok.lit[0].is_capital()
315316
&& p.peek_tok.kind == .dot && language == .v // `fn Foo.bar() {}`
316317
if is_static_type_method {
317318
type_name := p.tok.lit // "Foo"
319+
static_type_pos = p.tok.pos()
318320
rec.typ = p.parse_type()
319321
p.check(.dot)
320322
check_name = p.check_name()
@@ -647,6 +649,7 @@ run them via `v file.v` instead',
647649
receiver_pos: rec.pos
648650
is_method: is_method
649651
is_static_type_method: is_static_type_method
652+
static_type_pos: static_type_pos
650653
method_type_pos: rec.type_pos
651654
method_idx: type_sym_method_idx
652655
rec_mut: rec.is_mut

0 commit comments

Comments
 (0)