summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEarlopain <14981592+Earlopain@users.noreply.github.com>2026-02-27 11:51:22 +0100
committerTakashi Kokubun <takashikkbn@gmail.com>2026-03-06 09:02:23 -0800
commite7d2828fb677874fb425e6129e0c4c20acc0e1dd (patch)
tree9616cfe6c04058f38cb5d814ca813e68a27c15bf
parent83c261f30bd43dc3465c0026b96e79af585fdfab (diff)
[ruby/prism] Fix error message for block/lambda with `...` argument
They currently complain that the parent method is not forwarding. But the actual problem is that these types of arguments simply don't accept `...` Fixes [Bug #21927] https://github.com/ruby/prism/commit/0aa2363331
-rw-r--r--prism/config.yml2
-rw-r--r--prism/prism.c28
-rw-r--r--prism/templates/src/diagnostic.c.erb2
-rw-r--r--test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt12
-rw-r--r--test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt12
5 files changed, 51 insertions, 5 deletions
diff --git a/prism/config.yml b/prism/config.yml
index 5e29d6fa18..2d51ca0496 100644
--- a/prism/config.yml
+++ b/prism/config.yml
@@ -17,6 +17,8 @@ errors:
- ARGUMENT_FORWARDING_UNBOUND
- ARGUMENT_NO_FORWARDING_AMPERSAND
- ARGUMENT_NO_FORWARDING_ELLIPSES
+ - ARGUMENT_NO_FORWARDING_ELLIPSES_LAMBDA
+ - ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK
- ARGUMENT_NO_FORWARDING_STAR
- ARGUMENT_NO_FORWARDING_STAR_STAR
- ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT
diff --git a/prism/prism.c b/prism/prism.c
index 1d4bd76a67..6849c5adf3 100644
--- a/prism/prism.c
+++ b/prism/prism.c
@@ -13876,6 +13876,7 @@ parse_parameters(
bool allows_forwarding_parameters,
bool accepts_blocks_in_defaults,
bool in_block,
+ pm_diagnostic_id_t diag_id_forwarding,
uint16_t depth
) {
pm_do_loop_stack_push(parser, false);
@@ -13931,7 +13932,7 @@ parse_parameters(
}
case PM_TOKEN_UDOT_DOT_DOT: {
if (!allows_forwarding_parameters) {
- pm_parser_err_current(parser, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
+ pm_parser_err_current(parser, diag_id_forwarding);
}
bool succeeded = update_parameter_state(parser, &parser->current, &order);
@@ -14611,6 +14612,7 @@ parse_block_parameters(
false,
accepts_blocks_in_defaults,
true,
+ is_lambda_literal ? PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_LAMBDA : PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK,
(uint16_t) (depth + 1)
);
if (!is_lambda_literal) {
@@ -18853,7 +18855,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
params = NULL;
} else {
- params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, true, false, true, true, false, (uint16_t) (depth + 1));
+ params = parse_parameters(
+ parser,
+ PM_BINDING_POWER_DEFINED,
+ true,
+ false,
+ true,
+ true,
+ false,
+ PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES,
+ (uint16_t) (depth + 1)
+ );
}
lex_state_set(parser, PM_LEX_STATE_BEG);
@@ -18878,7 +18890,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
lparen = not_provided(parser);
rparen = not_provided(parser);
- params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, false, false, true, true, false, (uint16_t) (depth + 1));
+ params = parse_parameters(
+ parser,
+ PM_BINDING_POWER_DEFINED,
+ false,
+ false,
+ true,
+ true,
+ false,
+ PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES,
+ (uint16_t) (depth + 1)
+ );
// Reject `def * = 1` and similar. We have to specifically check
// for them because they create ambiguity with optional arguments.
diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb
index 121dd4b2b6..98f9b922ed 100644
--- a/prism/templates/src/diagnostic.c.erb
+++ b/prism/templates/src/diagnostic.c.erb
@@ -102,6 +102,8 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_ARGUMENT_FORWARDING_UNBOUND] = { "unexpected `...` in an non-parenthesized call", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_NO_FORWARDING_AMPERSAND] = { "unexpected `&`; no anonymous block parameter", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = { "unexpected ... when the parent method is not forwarding", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_LAMBDA] = { "unexpected ... in lambda argument", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK] = { "unexpected ... in block argument", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_NO_FORWARDING_STAR] = { "unexpected `*`; no anonymous rest parameter", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR] = { "unexpected `**`; no anonymous keyword rest parameter", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT] = { "unexpected `*` splat argument after a `**` keyword splat argument", PM_ERROR_LEVEL_SYNTAX },
diff --git a/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt b/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt
index df49557617..639dec3af2 100644
--- a/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt
+++ b/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt
@@ -1,3 +1,13 @@
a {|...|}
- ^~~ unexpected ... when the parent method is not forwarding
+ ^~~ unexpected ... in block argument
+
+def foo(...)
+ a {|...|}
+ ^~~ unexpected ... in block argument
+end
+
+def foo
+ a {|...|}
+ ^~~ unexpected ... in block argument
+end
diff --git a/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt b/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt
index c2405a5c66..03e17683e4 100644
--- a/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt
+++ b/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt
@@ -1,3 +1,13 @@
->(...) {}
- ^~~ unexpected ... when the parent method is not forwarding
+ ^~~ unexpected ... in lambda argument
+
+def foo(...)
+ ->(...) {}
+ ^~~ unexpected ... in lambda argument
+end
+
+def foo
+ ->(...) {}
+ ^~~ unexpected ... in lambda argument
+end