1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: check generic fn declaration (#15104)

This commit is contained in:
yuyi 2022-07-17 19:32:59 +08:00 committed by GitHub
parent 78242627c3
commit 58ad6f7999
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 84 additions and 26 deletions

View File

@ -108,6 +108,17 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
} else if return_sym.kind == .array_fixed {
c.error('fixed array cannot be returned by function', node.return_type_pos)
}
// Ensure each generic type of the parameter was declared in the function's definition
if node.return_type.has_flag(.generic) {
generic_names := c.table.generic_type_names(node.return_type)
for name in generic_names {
if name !in node.generic_names {
fn_generic_names := node.generic_names.join(', ')
c.error('generic type name `$name` is not mentioned in fn `$node.name<$fn_generic_names>`',
node.return_type_pos)
}
}
}
} else {
for mut a in node.attrs {
if a.kind == .comptime_define {
@ -207,6 +218,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
}
}
}
// Ensure each generic type of the parameter was declared in the function's definition
if param.typ.has_flag(.generic) {
generic_names := c.table.generic_type_names(param.typ)
for name in generic_names {

View File

@ -0,0 +1,35 @@
vlib/v/checker/tests/generic_fn_decl_err.vv:19:29: error: generic type name `P` is not mentioned in fn `create1<U>`
17 | }
18 |
19 | fn (r Db) create1<U>(u U, p P) {
| ^
20 | println('Yo')
21 | }
vlib/v/checker/tests/generic_fn_decl_err.vv:23:29: error: generic type name `P` is not mentioned in fn `create2<U>`
21 | }
22 |
23 | fn (r Db) create2<U>(u U, p &P) {
| ~~
24 | println('Yo')
25 | }
vlib/v/checker/tests/generic_fn_decl_err.vv:27:29: error: generic type name `P` is not mentioned in fn `create3<U>`
25 | }
26 |
27 | fn (r Db) create3<U>(u U, p []P) {
| ~~~
28 | println('Yo')
29 | }
vlib/v/checker/tests/generic_fn_decl_err.vv:31:27: error: generic type name `P` is not mentioned in fn `create4<U>`
29 | }
30 |
31 | fn (r Db) create4<U>(u U) P {
| ^
32 | return P{}
33 | }
vlib/v/checker/tests/generic_fn_decl_err.vv:35:27: error: generic type name `P` is not mentioned in fn `create5<U>`
33 | }
34 |
35 | fn (r Db) create5<U>(u U) []P {
| ~~~
36 | return [P{}]
37 | }

View File

@ -0,0 +1,37 @@
module main
struct Db {}
struct User {}
struct Post {}
fn main() {
r := Db{}
u := User{}
p := Post{}
r.create1(u, p)
r.create2(u, &p)
r.create3(u, [p])
r.create4(u)
r.create5(u)
}
fn (r Db) create1<U>(u U, p P) {
println('Yo')
}
fn (r Db) create2<U>(u U, p &P) {
println('Yo')
}
fn (r Db) create3<U>(u U, p []P) {
println('Yo')
}
fn (r Db) create4<U>(u U) P {
return P{}
}
fn (r Db) create5<U>(u U) []P {
return [P{}]
}

View File

@ -1,7 +0,0 @@
vlib/v/checker/tests/generic_fn_decl_err_a.vv:17:28: error: generic type name `P` is not mentioned in fn `create<U>`
15 | }
16 |
17 | fn (r Db) create<U>(u U, p P) {
| ^
18 | println('Yo')
19 | }

View File

@ -1,19 +0,0 @@
module main
struct Db {}
struct User {}
struct Post {}
fn main() {
r := Db{}
u := User{}
p := Post{}
r.create(u, p)
}
fn (r Db) create<U>(u U, p P) {
println('Yo')
}