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

parser: ensure generic function declaration specifies type names (fix #9959) (#9967)

This commit is contained in:
yuyi 2021-05-03 00:30:39 +08:00 committed by GitHub
parent 3175525b5e
commit ae22967d1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 71 additions and 4 deletions

View File

@ -6752,6 +6752,24 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
c.file.generic_fns << node
return
}
// Check generics fn/method without generic type parameters
mut need_generic_names := false
if node.generic_names.len == 0 {
if node.return_type.has_flag(.generic) {
need_generic_names = true
} else {
for param in node.params {
if param.typ.has_flag(.generic) {
need_generic_names = true
break
}
}
}
if need_generic_names {
c.error('generic function declaration must specify generic type names, e.g. foo<T>',
node.pos)
}
}
if node.language == .v && !c.is_builtin_mod {
c.check_valid_snake_case(node.name, 'function name', node.pos)
}

View File

@ -0,0 +1,14 @@
vlib/v/checker/tests/generic_fn_decl_without_generic_names_err.vv:26:1: error: generic function declaration must specify generic type names, e.g. foo<T>
24 | }
25 |
26 | fn g_worker(g Generic<T>) {
| ~~~~~~~~~~~~~~~~~~~~~~~~~
27 | t := <-g.ch
28 | handle(t)
vlib/v/checker/tests/generic_fn_decl_without_generic_names_err.vv:32:1: error: generic function declaration must specify generic type names, e.g. foo<T>
30 | }
31 |
32 | fn handle(t T) {
| ~~~~~~~~~~~~~~
33 | println("hi")
34 | }

View File

@ -0,0 +1,34 @@
struct Generic<T> {
ch chan T
}
struct Concrete {
msg string
}
fn main() {
g := create_generic_t<Concrete>()
g.ch <- Concrete{
msg: 'hello'
}
}
fn create_generic_t<T>() Generic<T> {
g := Generic{
ch: chan T{}
}
go g_worker(g)
return g
}
fn g_worker(g Generic<T>) {
t := <-g.ch
handle(t)
// println("${t.msg}")
}
fn handle(t T) {
println("hi")
}

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/receiver_unknown_type_single_letter.vv:1:5: error: unknown type `A`
1 | fn (p A) foo() {}
| ~~~
vlib/v/checker/tests/receiver_unknown_type_single_letter.vv:1:1: error: unknown type `Abc`
1 | fn (p Abc) foo() {}
| ~~~~~~~~~~~~~~~~
2 |

View File

@ -1,2 +1,2 @@
fn (p A) foo() {}
fn (p Abc) foo() {}

View File

@ -336,6 +336,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
short_fn_name := name
is_main := short_fn_name == 'main' && p.mod == 'main'
is_test := short_fn_name.starts_with('test_') || short_fn_name.starts_with('testsuite_')
// Register
if is_method {
mut type_sym := p.table.get_type_symbol(rec.typ)