@@ -13907,6 +13907,43 @@ update_parameter_state(pm_parser_t *parser, pm_token_t *token, pm_parameters_ord
1390713907 return true;
1390813908}
1390913909
13910+ static inline void
13911+ parse_parameters_handle_trailing_comma(
13912+ pm_parser_t *parser,
13913+ pm_parameters_node_t *params,
13914+ pm_parameters_order_t order,
13915+ bool in_block,
13916+ bool allows_trailing_comma
13917+ ) {
13918+ if (!allows_trailing_comma) {
13919+ pm_parser_err_previous(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA);
13920+ return;
13921+ }
13922+
13923+ if (in_block) {
13924+ if (order >= PM_PARAMETERS_ORDER_NAMED) {
13925+ // foo do |bar,|; end
13926+ pm_node_t *param = UP(pm_implicit_rest_node_create(parser, &parser->previous));
13927+
13928+ if (params->rest == NULL) {
13929+ pm_parameters_node_rest_set(params, param);
13930+ } else {
13931+ pm_parser_err_node(parser, UP(param), PM_ERR_PARAMETER_SPLAT_MULTI);
13932+ pm_parameters_node_posts_append(params, UP(param));
13933+ }
13934+ } else {
13935+ // foo do |*bar,|; end
13936+ pm_parser_err_previous(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA);
13937+ }
13938+ } else {
13939+ // https://bugs.ruby-lang.org/issues/19107
13940+ // Allow `def foo(bar,); end`, `def foo(*bar,); end`, etc. but not `def foo(...,); end`
13941+ if (parser->version < PM_OPTIONS_VERSION_CRUBY_4_1 || order == PM_PARAMETERS_ORDER_NOTHING_AFTER) {
13942+ pm_parser_err_previous(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA);
13943+ }
13944+ }
13945+ }
13946+
1391013947/**
1391113948 * Parse a list of parameters on a method definition.
1391213949 */
@@ -14255,20 +14292,7 @@ parse_parameters(
1425514292 }
1425614293 default:
1425714294 if (parser->previous.type == PM_TOKEN_COMMA) {
14258- if (allows_trailing_comma && order >= PM_PARAMETERS_ORDER_NAMED) {
14259- // If we get here, then we have a trailing comma in a
14260- // block parameter list.
14261- pm_node_t *param = UP(pm_implicit_rest_node_create(parser, &parser->previous));
14262-
14263- if (params->rest == NULL) {
14264- pm_parameters_node_rest_set(params, param);
14265- } else {
14266- pm_parser_err_node(parser, UP(param), PM_ERR_PARAMETER_SPLAT_MULTI);
14267- pm_parameters_node_posts_append(params, UP(param));
14268- }
14269- } else {
14270- pm_parser_err_previous(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA);
14271- }
14295+ parse_parameters_handle_trailing_comma(parser, params, order, in_block, allows_trailing_comma);
1427214296 }
1427314297
1427414298 parsing = false;
@@ -18865,7 +18889,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1886518889 if (match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
1886618890 params = NULL;
1886718891 } else {
18868- params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, true, false, true, true, false, (uint16_t) (depth + 1));
18892+ // https://bugs.ruby-lang.org/issues/19107
18893+ bool allow_trailing_comma = parser->version >= PM_OPTIONS_VERSION_CRUBY_4_1;
18894+ params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, true, allow_trailing_comma, true, true, false, (uint16_t) (depth + 1));
1886918895 }
1887018896
1887118897 lex_state_set(parser, PM_LEX_STATE_BEG);
0 commit comments