Avoid crash when deduce fails for imported generic (#5001)

An imported generic has bindings which are of type ImportRefLoaded, and
if they come from another package, they have no entity name attached to
them.

Since a binding name is always a constant-time value, we can get the
constant value instruction for the imported instruction to get a
canonical non-imported instruction. And that one will have a local
`NameId`.

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
This commit is contained in:
Dana Jansens
2025-02-26 22:39:11 +00:00
committed by GitHub
co-authored by josh11b
parent 9fc40f86f9
commit e5feced884
2 changed files with 254 additions and 5 deletions
+20 -5
View File
@@ -506,6 +506,25 @@ auto DeductionContext::Deduce() -> bool {
return true;
}
// Gets the entity name of a generic binding. The generic binding may be an
// imported instruction.
static auto GetEntityNameForGenericBinding(Context& context,
SemIR::InstId binding_id)
-> SemIR::NameId {
// If `binding_id` is imported, it may not have an entity name. Get a
// canonical local instruction from its constant value which does.
if (context.insts().Is<SemIR::ImportRefLoaded>(binding_id)) {
binding_id = context.constant_values().GetConstantInstId(binding_id);
}
if (auto bind_name =
context.insts().TryGetAs<SemIR::AnyBindName>(binding_id)) {
return context.entity_names().Get(bind_name->entity_name_id).name_id;
} else {
CARBON_FATAL("Instruction without entity name in generic binding position");
}
}
auto DeductionContext::CheckDeductionIsComplete() -> bool {
// Check we deduced an argument value for every parameter, and convert each
// argument to match the final parameter type after substituting any deduced
@@ -518,16 +537,12 @@ auto DeductionContext::CheckDeductionIsComplete() -> bool {
context().generics().Get(generic_id_).bindings_id)[binding_index];
if (!deduced_arg_id.has_value()) {
if (diagnose_) {
auto entity_name_id = context()
.insts()
.GetAs<SemIR::AnyBindName>(binding_id)
.entity_name_id;
CARBON_DIAGNOSTIC(DeductionIncomplete, Error,
"cannot deduce value for generic parameter `{0}`",
SemIR::NameId);
auto diag = context().emitter().Build(
loc_id_, DeductionIncomplete,
context().entity_names().Get(entity_name_id).name_id);
GetEntityNameForGenericBinding(context(), binding_id));
NoteGenericHere(context(), generic_id_, diag);
diag.Emit();
}