Skip to content

Commit ac9397b

Browse files
committed
Resolve anonymous arg crash
1 parent 67d58db commit ac9397b

File tree

5 files changed

+35
-8
lines changed

5 files changed

+35
-8
lines changed

parser/prism/Factory.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,9 @@ pm_call_node_t *Factory::createCallNode(pm_node_t *receiver, pm_constant_id_t me
182182
}
183183

184184
pm_node_t *Factory::SymbolFromConstant(core::LocOffsets nameLoc, pm_constant_id_t nameId) const {
185+
ENFORCE(nameId != PM_CONSTANT_ID_UNSET,
186+
"SymbolFromConstant called with PM_CONSTANT_ID_UNSET (anonymous parameter name). "
187+
"Caller must check for PM_CONSTANT_ID_UNSET before calling.");
185188
auto nameView = parser.resolveConstant(nameId);
186189

187190
pm_symbol_node_t *symbolNode = allocateNode<pm_symbol_node_t>();

parser/prism/Parser.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ core::LocOffsets Parser::translateLocation(const uint8_t *start, const uint8_t *
4646
}
4747

4848
string_view Parser::resolveConstant(pm_constant_id_t constantId) const {
49+
ENFORCE(constantId != PM_CONSTANT_ID_UNSET,
50+
"resolveConstant called with PM_CONSTANT_ID_UNSET (anonymous parameter name). "
51+
"Caller must check for PM_CONSTANT_ID_UNSET before calling.");
4952
pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser.constant_pool, constantId);
5053

5154
return cast_prism_string(constant->start, constant->length);

parser/prism/Translator.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2840,7 +2840,7 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
28402840
constexpr uint32_t length = "**"sv.size();
28412841
kwrestLoc = core::LocOffsets{location.beginPos() + length, location.endPos()};
28422842
} else { // An anonymous keyword rest parameter, like `def foo(**)`
2843-
sorbetName = nextUniqueParserName(core::Names::starStar());
2843+
sorbetName = core::Names::starStar();
28442844

28452845
// This location *does* include the whole `**`.
28462846
kwrestLoc = location;
@@ -4208,7 +4208,7 @@ Translator::translateParametersNode(pm_parameters_node *paramsNode, core::LocOff
42084208
constexpr uint32_t length = "&"sv.size();
42094209
blockParamLoc = core::LocOffsets{blockParamLoc.beginPos() + length, blockParamLoc.endPos()};
42104210
} else { // An anonymous block parameter, like `def foo(&)`
4211-
enclosingBlockParamName = nextUniqueParserName(core::Names::ampersand());
4211+
enclosingBlockParamName = core::Names::ampersand();
42124212
}
42134213

42144214
auto blockParamExpr = MK::BlockParam(blockParamLoc, MK::Local(blockParamLoc, enclosingBlockParamName));

rbs/prism/AssertionsRewriterPrism.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ vector<pair<core::LocOffsets, core::NameRef>>
6363
extractTypeParamsPrism(core::MutableContext ctx, const parser::Prism::Parser &parser, pm_node_t *block) {
6464
vector<pair<core::LocOffsets, core::NameRef>> typeParams;
6565

66-
// Do we have a block?
6766
if (!block || !PM_NODE_TYPE_P(block, PM_BLOCK_NODE)) {
6867
return typeParams;
6968
}

rbs/prism/MethodTypeToParserNodePrism.cc

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,21 @@ string_view nodeKindToString(const pm_node_t *node) {
201201
}
202202
}
203203

204+
// Get the NameRef for an anonymous parameter node
205+
core::NameRef anonymousParamName(core::MutableContext ctx, const pm_node_t *node) {
206+
switch (PM_NODE_TYPE(node)) {
207+
case PM_REST_PARAMETER_NODE:
208+
return core::Names::star();
209+
case PM_KEYWORD_REST_PARAMETER_NODE:
210+
return core::Names::starStar();
211+
case PM_BLOCK_PARAMETER_NODE:
212+
return core::Names::ampersand();
213+
default:
214+
ENFORCE(false, "Unexpected anonymous parameter node type");
215+
return core::NameRef::noName();
216+
}
217+
}
218+
204219
optional<core::AutocorrectSuggestion> autocorrectArg(core::MutableContext ctx, pm_node_t *methodArg, RBSArg arg,
205220
const parser::Prism::Parser &prismParser,
206221
const RBSDeclaration &declaration) {
@@ -624,7 +639,13 @@ pm_node_t *MethodTypeToParserNodePrism::methodSignature(pm_node_t *methodDef, co
624639
pm_node_t *methodParam = methodParams[i];
625640
if (!checkParameterKindMatch(arg, methodParam)) {
626641
if (auto e = ctx.beginIndexerError(arg.loc, core::errors::Rewriter::RBSIncorrectParameterKind)) {
627-
auto methodParamNameStr = prismParser.resolveConstant(getParamName(methodParams[i]));
642+
auto paramNameId = getParamName(methodParams[i]);
643+
string_view methodParamNameStr;
644+
if (paramNameId != PM_CONSTANT_ID_UNSET) {
645+
methodParamNameStr = prismParser.resolveConstant(paramNameId);
646+
} else {
647+
methodParamNameStr = anonymousParamName(ctx, methodParam).shortName(ctx.state);
648+
}
628649
e.setHeader("Argument kind mismatch for `{}`, method declares `{}`, but RBS signature declares `{}`",
629650
methodParamNameStr, nodeKindToString(methodParam), argKindToString(arg.kind));
630651

@@ -641,11 +662,12 @@ pm_node_t *MethodTypeToParserNodePrism::methodSignature(pm_node_t *methodDef, co
641662
auto *methodParam = methodParams[i];
642663
auto methodParamName = getParamName(methodParam);
643664

644-
// Special case: anonymous block parameter (&) should use symbol :&
645-
if (arg.kind == RBSArg::Kind::Block && methodParamName == PM_CONSTANT_ID_UNSET) {
646-
symbolNode = prism.Symbol(tinyLocOffsets, "&"sv);
647-
} else {
665+
if (methodParamName != PM_CONSTANT_ID_UNSET) {
648666
symbolNode = prism.SymbolFromConstant(tinyLocOffsets, methodParamName);
667+
} else {
668+
// Anonymous parameter - use the canonical name (*, **, &)
669+
auto name = anonymousParamName(ctx, methodParam);
670+
symbolNode = prism.Symbol(tinyLocOffsets, name.shortName(ctx.state));
649671
}
650672
}
651673

0 commit comments

Comments
 (0)