Skip to content

Commit dafa6fd

Browse files
authored
checker: force all fn declarations to follow after all other top level statements (fix #25889) (#25890)
1 parent d9f1e33 commit dafa6fd

File tree

5 files changed

+81
-20
lines changed

5 files changed

+81
-20
lines changed

vlib/v/checker/checker.v

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ pub fn (mut c Checker) check(mut ast_file ast.File) {
266266
}
267267
}
268268
}
269+
c.reorder_fns_at_the_end(mut ast_file)
269270
c.stmt_level = 0
270271
for mut stmt in ast_file.stmts {
271272
if stmt in [ast.ConstDecl, ast.ExprStmt] {
@@ -303,6 +304,31 @@ pub fn (mut c Checker) check(mut ast_file ast.File) {
303304
c.check_unused_labels()
304305
}
305306

307+
pub fn (mut c Checker) reorder_fns_at_the_end(mut ast_file ast.File) {
308+
mut fdeclarations := 0
309+
for mut stmt in ast_file.stmts {
310+
if stmt is ast.FnDecl {
311+
fdeclarations++
312+
}
313+
}
314+
if fdeclarations == 0 {
315+
return
316+
}
317+
// eprintln('>>> ast_file: ${ast_file.path:-60s} | fdeclarations: ${fdeclarations}')
318+
mut stmts := []ast.Stmt{cap: ast_file.stmts.len}
319+
for stmt in ast_file.stmts {
320+
if stmt !is ast.FnDecl {
321+
stmts << stmt
322+
}
323+
}
324+
for stmt in ast_file.stmts {
325+
if stmt is ast.FnDecl {
326+
stmts << stmt
327+
}
328+
}
329+
ast_file.stmts = stmts
330+
}
331+
306332
pub fn (mut c Checker) check_scope_vars(sc &ast.Scope) {
307333
if !c.pref.is_repl && !c.file.is_test {
308334
for _, obj in sc.objects {

vlib/v/checker/tests/c_js_struct_and_fn_as_generics_error.out

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ vlib/v/checker/tests/c_js_struct_and_fn_as_generics_error.vv:1:1: error: C struc
33
| ~~~~~~~~~~~~
44
2 | ptr &T
55
3 | }
6+
vlib/v/checker/tests/c_js_struct_and_fn_as_generics_error.vv:9:1: error: JS structs cannot be declared as generic
7+
7 | fn JS.encode[T](data string) T
8+
8 |
9+
9 | struct JS.Some[T] {
10+
| ~~~~~~~~~~~~~~
11+
10 | i T
12+
11 | }
613
vlib/v/checker/tests/c_js_struct_and_fn_as_generics_error.vv:5:1: error: C functions cannot be declared as generic
714
3 | }
815
4 |
@@ -17,10 +24,3 @@ vlib/v/checker/tests/c_js_struct_and_fn_as_generics_error.vv:7:1: error: JS func
1724
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1825
8 |
1926
9 | struct JS.Some[T] {
20-
vlib/v/checker/tests/c_js_struct_and_fn_as_generics_error.vv:9:1: error: JS structs cannot be declared as generic
21-
7 | fn JS.encode[T](data string) T
22-
8 |
23-
9 | struct JS.Some[T] {
24-
| ~~~~~~~~~~~~~~
25-
10 | i T
26-
11 | }
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1+
vlib/v/checker/tests/duplicate_field_method_err.vv:9:2: error: type `Foo` has both field and method named `bar`
2+
7 | interface Foo {
3+
8 | bar fn ()
4+
9 | bar()
5+
| ~~~~~
6+
10 | }
17
vlib/v/checker/tests/duplicate_field_method_err.vv:5:1: error: type `St` has both field and method named `attr`
28
3 | }
39
4 |
410
5 | fn (s St) attr() {}
511
| ~~~~~~~~~~~~~~~~
612
6 |
713
7 | interface Foo {
8-
vlib/v/checker/tests/duplicate_field_method_err.vv:9:2: error: type `Foo` has both field and method named `bar`
9-
7 | interface Foo {
10-
8 | bar fn ()
11-
9 | bar()
12-
| ~~~~~
13-
10 | }
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
vlib/v/checker/tests/invalid_parameter_name_err.vv:4:24: error: invalid use of reserved type `char` as a parameter name
2-
2 | }
3-
3 |
4-
4 | fn (mut b Buffer) put8(char u8) ! {
5-
| ~~~~
6-
5 | return error('-')
7-
6 | }
81
vlib/v/checker/tests/invalid_parameter_name_err.vv:10:6: error: invalid use of reserved type `char` as a parameter name
92
8 | interface Writer {
103
9 | mut:
114
10 | put(char u8) !
125
| ~~~~
136
11 | }
147
12 |
8+
vlib/v/checker/tests/invalid_parameter_name_err.vv:4:24: error: invalid use of reserved type `char` as a parameter name
9+
2 | }
10+
3 |
11+
4 | fn (mut b Buffer) put8(char u8) ! {
12+
| ~~~~
13+
5 | return error('-')
14+
6 | }
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
interface Speaker {
2+
speak()
3+
}
4+
5+
struct Cat {}
6+
7+
fn (c &Cat) speak() {}
8+
9+
struct EventA {
10+
a u32
11+
}
12+
13+
struct EventB {
14+
b u32
15+
}
16+
17+
type Event = EventA | EventB
18+
19+
fn some_func() {
20+
queue := Queue.new[Speaker]()
21+
}
22+
23+
struct Queue[T] {
24+
mut:
25+
data &T = unsafe { nil }
26+
}
27+
28+
fn Queue.new[T]() Queue[T] {
29+
return Queue[T]{}
30+
}
31+
32+
fn test_main() {
33+
some_func()
34+
assert true
35+
}

0 commit comments

Comments
 (0)