From eee9ee52006ae004c2224533b4fc208ad403bb2d Mon Sep 17 00:00:00 2001 From: Swastik Baranwal Date: Tue, 12 Nov 2024 16:33:51 +0530 Subject: [PATCH] checker: disallow `foo[T]` as a value (#22820) --- vlib/v/checker/checker.v | 11 ++++++++++ ...generic_fn_generic_name_unresolved_err.out | 21 +++++++++++++++++++ .../generic_fn_generic_name_unresolved_err.vv | 15 +++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 vlib/v/checker/tests/generic_fn_generic_name_unresolved_err.out create mode 100644 vlib/v/checker/tests/generic_fn_generic_name_unresolved_err.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 9e778a83b..c9a22a27d 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -4009,6 +4009,17 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type { c.error('`${node.name}` is a generic fn, you should pass its concrete types, e.g. ${node.name}[int]', node.pos) } + mut has_generic := false // foo[T] instead of foo[int] + for concrete_type in node.concrete_types { + if concrete_type.has_flag(.generic) { + has_generic = true + } + } + if c.table.cur_fn != unsafe { nil } && c.table.cur_concrete_types.len == 0 + && has_generic && c.table.sym(c.expected_type).kind != .function { + c.error('a generic fn with generic types, cannot be used outside of another generic fn', + node.pos) + } } return c.resolve_var_fn(func, mut node, name) } diff --git a/vlib/v/checker/tests/generic_fn_generic_name_unresolved_err.out b/vlib/v/checker/tests/generic_fn_generic_name_unresolved_err.out new file mode 100644 index 000000000..4a5f4c1ff --- /dev/null +++ b/vlib/v/checker/tests/generic_fn_generic_name_unresolved_err.out @@ -0,0 +1,21 @@ +vlib/v/checker/tests/generic_fn_generic_name_unresolved_err.vv:8:7: error: a generic fn with generic types, cannot be used outside of another generic fn + 6 | + 7 | fn main() { + 8 | _ := func[T] + | ~~~~ + 9 | _ := { + 10 | 'test': func[T] +vlib/v/checker/tests/generic_fn_generic_name_unresolved_err.vv:10:11: error: a generic fn with generic types, cannot be used outside of another generic fn + 8 | _ := func[T] + 9 | _ := { + 10 | 'test': func[T] + | ~~~~ + 11 | } + 12 | _ := { +vlib/v/checker/tests/generic_fn_generic_name_unresolved_err.vv:13:3: error: a generic fn with generic types, cannot be used outside of another generic fn + 11 | } + 12 | _ := { + 13 | func[T]: 'test' + | ~~~~ + 14 | } + 15 | } diff --git a/vlib/v/checker/tests/generic_fn_generic_name_unresolved_err.vv b/vlib/v/checker/tests/generic_fn_generic_name_unresolved_err.vv new file mode 100644 index 000000000..ad6ed25de --- /dev/null +++ b/vlib/v/checker/tests/generic_fn_generic_name_unresolved_err.vv @@ -0,0 +1,15 @@ +module main + +fn func[T](arg string, val T) int { + return 2 +} + +fn main() { + _ := func[T] + _ := { + 'test': func[T] + } + _ := { + func[T]: 'test' + } +} -- 2.39.5