Handle merging of conflicting 'export name' cross-package imports. (#3973)

This commit is contained in:
Jon Ross-Perkins
2024-05-22 22:35:48 +00:00
committed by GitHub
parent 41a84222c2
commit d4025dc6c4
5 changed files with 267 additions and 170 deletions
+2 -48
View File
@@ -217,43 +217,6 @@ static auto CopyEnclosingNameScopesFromImportIR(
return scope_cursor;
}
// Returns the canonical IR inst for an entity. Returns an invalid ir_id for the
// current IR.
static auto GetCanonicalImportIRInst(Context& context,
const SemIR::File* cursor_ir,
SemIR::InstId cursor_inst_id)
-> SemIR::ImportIRInst {
while (true) {
auto inst = cursor_ir->insts().Get(cursor_inst_id);
CARBON_KIND_SWITCH(inst) {
case CARBON_KIND(SemIR::ExportDecl bind_export): {
cursor_inst_id = bind_export.value_id;
continue;
}
case SemIR::ImportRefLoaded::Kind:
case SemIR::ImportRefUnloaded::Kind: {
auto import_ref = inst.As<SemIR::AnyImportRef>();
auto import_ir_inst =
cursor_ir->import_ir_insts().Get(import_ref.import_ir_inst_id);
cursor_ir = cursor_ir->import_irs().Get(import_ir_inst.ir_id).sem_ir;
cursor_inst_id = import_ir_inst.inst_id;
continue;
}
default: {
auto ir_id = SemIR::ImportIRId::Invalid;
if (cursor_ir != &context.sem_ir()) {
// This uses AddImportIR in case it was indirectly found, which can
// happen with two or more steps of exports.
ir_id = AddImportIR(context, {.node_id = Parse::NodeId::Invalid,
.sem_ir = cursor_ir,
.is_export = false});
}
return {.ir_id = ir_id, .inst_id = cursor_inst_id};
}
}
}
}
// Adds an ImportRef for an entity, handling merging if needed.
static auto AddImportRefOrMerge(Context& context, SemIR::ImportIRId ir_id,
const SemIR::File& import_sem_ir,
@@ -275,17 +238,8 @@ static auto AddImportRefOrMerge(Context& context, SemIR::ImportIRId ir_id,
auto prev_ir_inst =
GetCanonicalImportIRInst(context, &context.sem_ir(), it->second);
auto new_ir_inst =
GetCanonicalImportIRInst(context, &import_sem_ir, import_inst_id);
// Diagnose if the imported instructions aren't equal. However, then we need
// to form an instruction for the duplicate diagnostic.
if (prev_ir_inst != new_ir_inst) {
auto conflict_id =
AddImportRef(context, {.ir_id = ir_id, .inst_id = import_inst_id},
SemIR::BindNameId::Invalid);
context.DiagnoseDuplicateName(conflict_id, it->second);
}
VerifySameCanonicalImportIRInst(context, it->second, prev_ir_inst, ir_id,
&import_sem_ir, import_inst_id);
}
auto ImportLibrariesFromCurrentPackage(