Replace ResolvePrevInstForMerge with decl logic. (#3936)

This addresses the const reliance of ResolvePrevInstForMerge by checking
the imported instruction, testing with `alias` name conflicts. Given the
need to examine structure, the helper function feels like it now gets in
the way, so I'm just removing it.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This commit is contained in:
Jon Ross-Perkins
2024-05-06 21:27:21 +00:00
committed by GitHub
co-authored by Richard Smith
parent d5c0c9cfe3
commit 292a9d3cb4
10 changed files with 400 additions and 97 deletions
+42 -27
View File
@@ -48,38 +48,53 @@ static auto MergeOrAddName(Context& context, Parse::AnyClassDeclId node_id,
bool is_extern) -> void {
auto prev_id =
context.decl_name_stack().LookupOrAddName(name_context, class_decl_id);
if (prev_id.is_valid()) {
auto prev_inst_for_merge = ResolvePrevInstForMerge(context, prev_id);
if (!prev_id.is_valid()) {
return;
}
auto prev_class_id = SemIR::ClassId::Invalid;
CARBON_KIND_SWITCH(prev_inst_for_merge.inst) {
case CARBON_KIND(SemIR::ClassDecl class_decl): {
prev_class_id = class_decl.class_id;
break;
}
case CARBON_KIND(SemIR::ClassType class_type): {
prev_class_id = class_type.class_id;
break;
}
default:
// This is a redeclaration of something other than a class.
context.DiagnoseDuplicateName(class_decl_id, prev_id);
break;
auto prev_class_id = SemIR::ClassId::Invalid;
auto prev_import_ir_id = SemIR::ImportIRId::Invalid;
CARBON_KIND_SWITCH(context.insts().Get(prev_id)) {
case CARBON_KIND(SemIR::ClassDecl class_decl): {
prev_class_id = class_decl.class_id;
break;
}
case CARBON_KIND(SemIR::ImportRefLoaded import_ref): {
auto import_ir_inst =
context.import_ir_insts().Get(import_ref.import_ir_inst_id);
if (prev_class_id.is_valid()) {
// TODO: Fix prev_is_extern logic.
if (MergeClassRedecl(context, node_id, class_info,
/*new_is_import=*/false, is_definition, is_extern,
prev_class_id, /*prev_is_extern=*/false,
prev_inst_for_merge.import_ir_inst_id)) {
// When merging, use the existing entity rather than adding a new one.
class_decl.class_id = prev_class_id;
// Verify the decl so that things like aliases are name conflicts.
const auto* import_ir =
context.import_irs().Get(import_ir_inst.ir_id).sem_ir;
if (!import_ir->insts().Is<SemIR::ClassDecl>(import_ir_inst.inst_id)) {
break;
}
} else {
// This is a redeclaration of something other than a class.
context.DiagnoseDuplicateName(class_decl_id, prev_id);
// Use the type to get the ID.
if (auto class_type = context.insts().TryGetAs<SemIR::ClassType>(
context.constant_values().Get(prev_id).inst_id())) {
prev_class_id = class_type->class_id;
prev_import_ir_id = import_ir_inst.ir_id;
}
break;
}
default:
break;
}
if (!prev_class_id.is_valid()) {
// This is a redeclaration of something other than a class.
context.DiagnoseDuplicateName(class_decl_id, prev_id);
return;
}
// TODO: Fix prev_is_extern logic.
if (MergeClassRedecl(context, node_id, class_info,
/*new_is_import=*/false, is_definition, is_extern,
prev_class_id, /*prev_is_extern=*/false,
prev_import_ir_id)) {
// When merging, use the existing entity rather than adding a new one.
class_decl.class_id = prev_class_id;
}
}