From 6aa81fa49ace053b11154656519fd1dcd7ab87c0 Mon Sep 17 00:00:00 2001 From: CreeperFace <165158232+dy-tea@users.noreply.github.com> Date: Sat, 29 Nov 2025 06:55:12 +0000 Subject: [PATCH] parser: disallow untyped `chan` used as a fn parameter type (fix #25818) (#25854) --- vlib/v/parser/fn.v | 8 +++++++ vlib/v/parser/messages.v | 5 +++++ vlib/v/parser/parse_type.v | 21 +++++++++++++++++++ .../tests/chan_no_type_array_fn_arg_err.out | 3 +++ .../tests/chan_no_type_array_fn_arg_err.vv | 1 + vlib/v/parser/tests/chan_no_type_err.out | 3 +++ vlib/v/parser/tests/chan_no_type_err.vv | 1 + .../parser/tests/chan_no_type_fn_arg_err.out | 3 +++ .../v/parser/tests/chan_no_type_fn_arg_err.vv | 1 + .../tests/chan_no_type_map_fn_arg_err.out | 3 +++ .../tests/chan_no_type_map_fn_arg_err.vv | 1 + .../parser/tests/chan_no_type_option_err.out | 3 +++ .../v/parser/tests/chan_no_type_option_err.vv | 1 + vlib/v/parser/tests/chan_no_type_ref_err.out | 3 +++ vlib/v/parser/tests/chan_no_type_ref_err.vv | 1 + 15 files changed, 58 insertions(+) create mode 100644 vlib/v/parser/tests/chan_no_type_array_fn_arg_err.out create mode 100644 vlib/v/parser/tests/chan_no_type_array_fn_arg_err.vv create mode 100644 vlib/v/parser/tests/chan_no_type_err.out create mode 100644 vlib/v/parser/tests/chan_no_type_err.vv create mode 100644 vlib/v/parser/tests/chan_no_type_fn_arg_err.out create mode 100644 vlib/v/parser/tests/chan_no_type_fn_arg_err.vv create mode 100644 vlib/v/parser/tests/chan_no_type_map_fn_arg_err.out create mode 100644 vlib/v/parser/tests/chan_no_type_map_fn_arg_err.vv create mode 100644 vlib/v/parser/tests/chan_no_type_option_err.out create mode 100644 vlib/v/parser/tests/chan_no_type_option_err.vv create mode 100644 vlib/v/parser/tests/chan_no_type_ref_err.out create mode 100644 vlib/v/parser/tests/chan_no_type_ref_err.vv diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 44a7b2817..7de3ee48e 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -1047,6 +1047,10 @@ fn (mut p Parser) fn_params() ([]ast.Param, bool, bool, bool) { // error is added in parse_type return []ast.Param{}, false, false, false } + if param_type == ast.chan_type { + p.chan_type_error() + return []ast.Param{}, false, false, false + } if is_mut { if !param_type.has_flag(.generic) { if is_variadic { @@ -1177,6 +1181,10 @@ fn (mut p Parser) fn_params() ([]ast.Param, bool, bool, bool) { // error is added in parse_type return []ast.Param{}, false, false, false } + if typ == ast.chan_type { + p.chan_type_error() + return []ast.Param{}, false, false, false + } if is_mut { if !typ.has_flag(.generic) { if is_variadic { diff --git a/vlib/v/parser/messages.v b/vlib/v/parser/messages.v index 8997f7188..6ea9b8b36 100644 --- a/vlib/v/parser/messages.v +++ b/vlib/v/parser/messages.v @@ -220,3 +220,8 @@ fn (mut p Parser) unexpected_with_pos(pos token.Pos, params ParamsForUnexpected) } return p.error_with_pos(msg, pos) } + +fn (mut p Parser) chan_type_error() { + p.error_with_pos('`chan` has no type specified. Use `chan Type` instead of `chan`', + p.prev_tok.pos()) +} diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index d54f725dd..13fb50023 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -124,6 +124,10 @@ fn (mut p Parser) parse_array_type(expecting token.Kind, is_option bool) ast.Typ // error is handled by parse_type return 0 } + if elem_type == ast.chan_type { + p.chan_type_error() + return 0 + } // has been explicitly resolved, but size is 0 if fixed_size <= 0 && !size_unresolved { p.error_with_pos('fixed size cannot be zero or negative', size_expr.pos()) @@ -142,6 +146,10 @@ fn (mut p Parser) parse_array_type(expecting token.Kind, is_option bool) ast.Typ // error is set in parse_type return 0 } + if elem_type == ast.chan_type { + p.chan_type_error() + return 0 + } if elem_type.idx() == ast.thread_type_idx { p.register_auto_import('sync.threads') } @@ -201,6 +209,10 @@ fn (mut p Parser) parse_map_type() ast.Type { // error is reported in parse_type return 0 } + if value_type == ast.chan_type { + p.chan_type_error() + return 0 + } if value_type.idx() == ast.void_type_idx { p.error_with_pos('map value type is missing: use `map[KeyType]ValueType`', p.tok.pos()) return 0 @@ -293,6 +305,10 @@ fn (mut p Parser) parse_multi_return_type() ast.Type { if mr_type.idx() == 0 { break } + if mr_type == ast.chan_type { + p.chan_type_error() + break + } if mr_type.has_flag(.generic) { has_generic = true } @@ -568,6 +584,11 @@ fn (mut p Parser) parse_type() ast.Type { // error is set in parse_type return 0 } + // !p.inside_receiver_param check can be removed once (ch chan) functions are removed + if typ == ast.chan_type && !p.inside_receiver_param { + p.chan_type_error() + return 0 + } if typ == ast.void_type { p.error_with_pos('use `?` instead of `?void`', pos) return 0 diff --git a/vlib/v/parser/tests/chan_no_type_array_fn_arg_err.out b/vlib/v/parser/tests/chan_no_type_array_fn_arg_err.out new file mode 100644 index 000000000..308e98669 --- /dev/null +++ b/vlib/v/parser/tests/chan_no_type_array_fn_arg_err.out @@ -0,0 +1,3 @@ +vlib/v/parser/tests/chan_no_type_array_fn_arg_err.vv:1:24: error: `chan` has no type specified. Use `chan Type` instead of `chan` + 1 | fn takes_array(chans []chan) {} + | ~~~~ diff --git a/vlib/v/parser/tests/chan_no_type_array_fn_arg_err.vv b/vlib/v/parser/tests/chan_no_type_array_fn_arg_err.vv new file mode 100644 index 000000000..5efa99054 --- /dev/null +++ b/vlib/v/parser/tests/chan_no_type_array_fn_arg_err.vv @@ -0,0 +1 @@ +fn takes_array(chans []chan) {} diff --git a/vlib/v/parser/tests/chan_no_type_err.out b/vlib/v/parser/tests/chan_no_type_err.out new file mode 100644 index 000000000..3c68e8a27 --- /dev/null +++ b/vlib/v/parser/tests/chan_no_type_err.out @@ -0,0 +1,3 @@ +vlib/v/parser/tests/chan_no_type_err.vv:1:6: error: `chan` has no type specified. Use `chan Type{}` instead of `chan{}` + 1 | a := chan{} + | ~~~~~~ diff --git a/vlib/v/parser/tests/chan_no_type_err.vv b/vlib/v/parser/tests/chan_no_type_err.vv new file mode 100644 index 000000000..c956d27ab --- /dev/null +++ b/vlib/v/parser/tests/chan_no_type_err.vv @@ -0,0 +1 @@ +a := chan{} diff --git a/vlib/v/parser/tests/chan_no_type_fn_arg_err.out b/vlib/v/parser/tests/chan_no_type_fn_arg_err.out new file mode 100644 index 000000000..89f0a4459 --- /dev/null +++ b/vlib/v/parser/tests/chan_no_type_fn_arg_err.out @@ -0,0 +1,3 @@ +vlib/v/parser/tests/chan_no_type_fn_arg_err.vv:1:12: error: `chan` has no type specified. Use `chan Type` instead of `chan` + 1 | fn takes(c chan) {} + | ~~~~ diff --git a/vlib/v/parser/tests/chan_no_type_fn_arg_err.vv b/vlib/v/parser/tests/chan_no_type_fn_arg_err.vv new file mode 100644 index 000000000..6eb50b3de --- /dev/null +++ b/vlib/v/parser/tests/chan_no_type_fn_arg_err.vv @@ -0,0 +1 @@ +fn takes(c chan) {} diff --git a/vlib/v/parser/tests/chan_no_type_map_fn_arg_err.out b/vlib/v/parser/tests/chan_no_type_map_fn_arg_err.out new file mode 100644 index 000000000..6da48ed67 --- /dev/null +++ b/vlib/v/parser/tests/chan_no_type_map_fn_arg_err.out @@ -0,0 +1,3 @@ +vlib/v/parser/tests/chan_no_type_map_fn_arg_err.vv:1:31: error: `chan` has no type specified. Use `chan Type` instead of `chan` + 1 | fn takes_map(chans map[string]chan) {} + | ~~~~ diff --git a/vlib/v/parser/tests/chan_no_type_map_fn_arg_err.vv b/vlib/v/parser/tests/chan_no_type_map_fn_arg_err.vv new file mode 100644 index 000000000..0c1c7fe62 --- /dev/null +++ b/vlib/v/parser/tests/chan_no_type_map_fn_arg_err.vv @@ -0,0 +1 @@ +fn takes_map(chans map[string]chan) {} diff --git a/vlib/v/parser/tests/chan_no_type_option_err.out b/vlib/v/parser/tests/chan_no_type_option_err.out new file mode 100644 index 000000000..f4f213734 --- /dev/null +++ b/vlib/v/parser/tests/chan_no_type_option_err.out @@ -0,0 +1,3 @@ +vlib/v/parser/tests/chan_no_type_option_err.vv:1:17: error: `chan` has no type specified. Use `chan Type` instead of `chan` + 1 | fn takes_opt(c ?chan) {} + | ~~~~ diff --git a/vlib/v/parser/tests/chan_no_type_option_err.vv b/vlib/v/parser/tests/chan_no_type_option_err.vv new file mode 100644 index 000000000..082efdef0 --- /dev/null +++ b/vlib/v/parser/tests/chan_no_type_option_err.vv @@ -0,0 +1 @@ +fn takes_opt(c ?chan) {} diff --git a/vlib/v/parser/tests/chan_no_type_ref_err.out b/vlib/v/parser/tests/chan_no_type_ref_err.out new file mode 100644 index 000000000..41f2ed4a6 --- /dev/null +++ b/vlib/v/parser/tests/chan_no_type_ref_err.out @@ -0,0 +1,3 @@ +vlib/v/parser/tests/chan_no_type_ref_err.vv:1:17: error: `chan` has no type specified. Use `chan Type` instead of `chan` + 1 | fn takes_ref(c &chan) {} + | ~~~~ diff --git a/vlib/v/parser/tests/chan_no_type_ref_err.vv b/vlib/v/parser/tests/chan_no_type_ref_err.vv new file mode 100644 index 000000000..2077d6e81 --- /dev/null +++ b/vlib/v/parser/tests/chan_no_type_ref_err.vv @@ -0,0 +1 @@ +fn takes_ref(c &chan) {} -- 2.39.5