From d4025dc6c44320e822f303340fb52596522a4f99 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Wed, 22 May 2024 15:35:48 -0700 Subject: [PATCH] Handle merging of conflicting 'export name' cross-package imports. (#3973) --- toolchain/check/context.cpp | 30 +- toolchain/check/import.cpp | 50 +-- toolchain/check/import_ref.cpp | 50 +++ toolchain/check/import_ref.h | 14 + .../no_prelude/cross_package_export.carbon | 293 +++++++++++------- 5 files changed, 267 insertions(+), 170 deletions(-) diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index 20a7db8e761e..1a595aab0f79 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -23,6 +23,7 @@ #include "toolchain/sem_ir/builtin_kind.h" #include "toolchain/sem_ir/file.h" #include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/import_ir.h" #include "toolchain/sem_ir/inst.h" #include "toolchain/sem_ir/inst_kind.h" #include "toolchain/sem_ir/typed_insts.h" @@ -300,7 +301,8 @@ static auto LookupInImportIRScopes(Context& context, SemIRLoc loc, }); auto result_id = SemIR::InstId::Invalid; - auto bind_name_id = SemIR::BindNameId::Invalid; + std::optional canonical_result_inst; + for (auto [import_ir_id, import_scope_id] : scope.import_ir_scopes) { auto& import_ir = context.import_irs().Get(import_ir_id); @@ -330,19 +332,25 @@ static auto LookupInImportIRScopes(Context& context, SemIRLoc loc, continue; } - if (!bind_name_id.is_valid()) { - bind_name_id = context.bind_names().Add( + if (result_id.is_valid()) { + // On a conflict, we verify the canonical instruction is the same. + if (!canonical_result_inst) { + canonical_result_inst = + GetCanonicalImportIRInst(context, &context.sem_ir(), result_id); + } + VerifySameCanonicalImportIRInst(context, result_id, + *canonical_result_inst, import_ir_id, + import_ir.sem_ir, it->second); + } else { + // Add the first result found. + auto bind_name_id = context.bind_names().Add( {.name_id = name_id, .enclosing_scope_id = scope_id, .bind_index = SemIR::CompileTimeBindIndex::Invalid}); - } - auto import_inst_id = AddImportRef( - context, {.ir_id = import_ir_id, .inst_id = it->second}, bind_name_id); - if (result_id.is_valid()) { - context.DiagnoseDuplicateName(import_inst_id, result_id); - } else { - LoadImportRef(context, import_inst_id); - result_id = import_inst_id; + result_id = + AddImportRef(context, {.ir_id = import_ir_id, .inst_id = it->second}, + bind_name_id); + LoadImportRef(context, result_id); } } diff --git a/toolchain/check/import.cpp b/toolchain/check/import.cpp index 5890192d8165..1ea767221fee 100644 --- a/toolchain/check/import.cpp +++ b/toolchain/check/import.cpp @@ -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(); - 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( diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 0a87be35cc8c..569e9c835ed1 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -72,6 +72,56 @@ auto AddImportRef(Context& context, SemIR::ImportIRInst import_ir_inst, return import_ref_id; } +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(); + 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}; + } + } + } +} + +auto VerifySameCanonicalImportIRInst(Context& context, SemIR::InstId prev_id, + SemIR::ImportIRInst prev_import_ir_inst, + SemIR::ImportIRId new_ir_id, + const SemIR::File* new_import_ir, + SemIR::InstId new_inst_id) -> void { + auto new_import_ir_inst = + GetCanonicalImportIRInst(context, new_import_ir, new_inst_id); + if (new_import_ir_inst == prev_import_ir_inst) { + return; + } + auto conflict_id = + AddImportRef(context, {.ir_id = new_ir_id, .inst_id = new_inst_id}, + SemIR::BindNameId::Invalid); + context.DiagnoseDuplicateName(conflict_id, prev_id); +} + // Resolves an instruction from an imported IR into a constant referring to the // current IR. // diff --git a/toolchain/check/import_ref.h b/toolchain/check/import_ref.h index 9a44c187e4a5..9d8d1821fbad 100644 --- a/toolchain/check/import_ref.h +++ b/toolchain/check/import_ref.h @@ -24,6 +24,20 @@ auto AddImportIR(Context& context, SemIR::ImportIR import_ir) auto AddImportRef(Context& context, SemIR::ImportIRInst import_ir_inst, SemIR::BindNameId bind_name_id) -> SemIR::InstId; +// Returns the canonical IR inst for an entity. Returns an invalid ir_id for the +// current IR. +auto GetCanonicalImportIRInst(Context& context, const SemIR::File* cursor_ir, + SemIR::InstId cursor_inst_id) + -> SemIR::ImportIRInst; + +// Verifies a new instruction is the same as a previous instruction. +// prev_import_ir_inst should come from GetCanonicalImportIRInst. +auto VerifySameCanonicalImportIRInst(Context& context, SemIR::InstId prev_id, + SemIR::ImportIRInst prev_import_ir_inst, + SemIR::ImportIRId new_ir_id, + const SemIR::File* new_import_ir, + SemIR::InstId new_inst_id) -> void; + // If the passed in instruction ID is an ImportRefUnloaded, turns it into an // ImportRefLoaded for use. auto LoadImportRef(Context& context, SemIR::InstId inst_id) -> void; diff --git a/toolchain/check/testdata/packages/no_prelude/cross_package_export.carbon b/toolchain/check/testdata/packages/no_prelude/cross_package_export.carbon index 7d3d87a41e59..abdaec54104e 100644 --- a/toolchain/check/testdata/packages/no_prelude/cross_package_export.carbon +++ b/toolchain/check/testdata/packages/no_prelude/cross_package_export.carbon @@ -16,6 +16,12 @@ class C { var x: (); }; +// --- conflict.carbon + +package Other library "conflict"; + +fn C() {} + // --- export_import.carbon package Other library "export_import"; @@ -95,35 +101,13 @@ import Other library "export_name"; var c: Other.C = {.x = ()}; -// --- fail_todo_use_export_name_with_copy.carbon +// --- use_export_name_with_copy.carbon library "use_export_name_with_copy"; import Other library "export_name"; -// CHECK:STDERR: fail_todo_use_export_name_with_copy.carbon:[[@LINE+18]]:1: In import. -// CHECK:STDERR: import Other library "export_name_copy"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: export_name_copy.carbon:4:1: In import. -// CHECK:STDERR: import library "base"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: base.carbon:4:1: ERROR: Duplicate name being declared in the same scope. -// CHECK:STDERR: class C { -// CHECK:STDERR: ^~~~~~~~~ -// CHECK:STDERR: fail_todo_use_export_name_with_copy.carbon:[[@LINE-10]]:1: In import. -// CHECK:STDERR: import Other library "export_name"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: export_name.carbon:4:1: In import. -// CHECK:STDERR: import library "base"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: base.carbon:4:1: Name is previously declared here. -// CHECK:STDERR: class C { -// CHECK:STDERR: ^~~~~~~~~ import Other library "export_name_copy"; -// CHECK:STDERR: fail_todo_use_export_name_with_copy.carbon:[[@LINE+4]]:8: In name lookup for `C`. -// CHECK:STDERR: var c: Other.C = {.x = ()}; -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: var c: Other.C = {.x = ()}; // --- use_export_name_indirect.carbon @@ -134,84 +118,85 @@ import Other library "export_name_indirect"; var c: Other.C = {.x = ()}; -// --- fail_todo_use_export_all.carbon +// --- use_export_all.carbon library "use_export_all"; -// CHECK:STDERR: fail_todo_use_export_all.carbon:[[@LINE+6]]:1: In import. -// CHECK:STDERR: import Other library "export_import"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: base.carbon:4:1: ERROR: Duplicate name being declared in the same scope. -// CHECK:STDERR: class C { -// CHECK:STDERR: ^~~~~~~~~ import Other library "export_import"; -// CHECK:STDERR: fail_todo_use_export_all.carbon:[[@LINE+9]]:1: In import. -// CHECK:STDERR: import Other library "export_name"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: export_name.carbon:4:1: In import. -// CHECK:STDERR: import library "base"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: base.carbon:4:1: Name is previously declared here. -// CHECK:STDERR: class C { -// CHECK:STDERR: ^~~~~~~~~ import Other library "export_name"; import Other library "export_import_copy"; import Other library "export_name_copy"; import Other library "export_import_indirect"; import Other library "export_name_indirect"; -// CHECK:STDERR: fail_todo_use_export_all.carbon:[[@LINE+50]]:8: In name lookup for `C`. -// CHECK:STDERR: var c: Other.C = {.x = ()}; -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: -// CHECK:STDERR: fail_todo_use_export_all.carbon:[[@LINE-8]]:1: In import. -// CHECK:STDERR: import Other library "export_name_copy"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: export_name_copy.carbon:4:1: In import. -// CHECK:STDERR: import library "base"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: base.carbon:4:1: ERROR: Duplicate name being declared in the same scope. -// CHECK:STDERR: class C { -// CHECK:STDERR: ^~~~~~~~~ -// CHECK:STDERR: fail_todo_use_export_all.carbon:[[@LINE-19]]:1: In import. -// CHECK:STDERR: import Other library "export_name"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: export_name.carbon:4:1: In import. -// CHECK:STDERR: import library "base"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: base.carbon:4:1: Name is previously declared here. -// CHECK:STDERR: class C { -// CHECK:STDERR: ^~~~~~~~~ -// CHECK:STDERR: fail_todo_use_export_all.carbon:[[@LINE+28]]:8: In name lookup for `C`. -// CHECK:STDERR: var c: Other.C = {.x = ()}; -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: -// CHECK:STDERR: fail_todo_use_export_all.carbon:[[@LINE-28]]:1: In import. -// CHECK:STDERR: import Other library "export_name_indirect"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: export_name_indirect.carbon:4:1: In import. -// CHECK:STDERR: import library "export_name"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: export_name.carbon:4:1: In import. -// CHECK:STDERR: import library "base"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: base.carbon:4:1: ERROR: Duplicate name being declared in the same scope. -// CHECK:STDERR: class C { -// CHECK:STDERR: ^~~~~~~~~ -// CHECK:STDERR: fail_todo_use_export_all.carbon:[[@LINE-44]]:1: In import. -// CHECK:STDERR: import Other library "export_name"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: export_name.carbon:4:1: In import. -// CHECK:STDERR: import library "base"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: base.carbon:4:1: Name is previously declared here. -// CHECK:STDERR: class C { -// CHECK:STDERR: ^~~~~~~~~ -// CHECK:STDERR: fail_todo_use_export_all.carbon:[[@LINE+3]]:8: In name lookup for `C`. -// CHECK:STDERR: var c: Other.C = {.x = ()}; -// CHECK:STDERR: ^~~~~~~ var c: Other.C = {.x = ()}; +// --- unused_conflict_on_export_import.carbon + +library "unused_conflict_on_export_import"; + +import Other library "export_import"; +import Other library "conflict"; + +// --- unused_conflict_on_export_name.carbon + +library "unused_conflict_on_export_name"; + +import Other library "export_name"; +import Other library "conflict"; + +// --- fail_conflict_on_export_import.carbon + +library "fail_conflict_on_export_import"; + +// CHECK:STDERR: fail_conflict_on_export_import.carbon:[[@LINE+6]]:1: In import. +// CHECK:STDERR: import Other library "export_import"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: base.carbon:4:1: ERROR: Duplicate name being declared in the same scope. +// CHECK:STDERR: class C { +// CHECK:STDERR: ^~~~~~~~~ +import Other library "export_import"; +// CHECK:STDERR: fail_conflict_on_export_import.carbon:[[@LINE+6]]:1: In import. +// CHECK:STDERR: import Other library "conflict"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: conflict.carbon:4:1: Name is previously declared here. +// CHECK:STDERR: fn C() {} +// CHECK:STDERR: ^~~~~~~~ +import Other library "conflict"; + +// CHECK:STDERR: fail_conflict_on_export_import.carbon:[[@LINE+4]]:11: In name lookup for `C`. +// CHECK:STDERR: alias C = Other.C; +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +alias C = Other.C; + +// --- fail_conflict_on_export_name.carbon + +library "fail_conflict_on_export_name"; + +import Other library "export_name"; +// CHECK:STDERR: fail_conflict_on_export_name.carbon:[[@LINE+15]]:1: In import. +// CHECK:STDERR: import Other library "conflict"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: conflict.carbon:4:1: ERROR: Duplicate name being declared in the same scope. +// CHECK:STDERR: fn C() {} +// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: fail_conflict_on_export_name.carbon:[[@LINE-7]]:1: In import. +// CHECK:STDERR: import Other library "export_name"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: export_name.carbon:4:1: In import. +// CHECK:STDERR: import library "base"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: base.carbon:4:1: Name is previously declared here. +// CHECK:STDERR: class C { +// CHECK:STDERR: ^~~~~~~~~ +import Other library "conflict"; + +// CHECK:STDERR: fail_conflict_on_export_name.carbon:[[@LINE+3]]:11: In name lookup for `C`. +// CHECK:STDERR: alias C = Other.C; +// CHECK:STDERR: ^~~~~~~ +alias C = Other.C; + // CHECK:STDOUT: --- base.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -238,6 +223,26 @@ var c: Other.C = {.x = ()}; // CHECK:STDOUT: .x = %.loc5_8 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- conflict.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = fn_type @C [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: C = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: C = fn_decl @C [template = constants.%struct] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @C() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- export_import.carbon // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -517,7 +522,7 @@ var c: Other.C = {.x = ()}; // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_use_export_name_with_copy.carbon +// CHECK:STDOUT: --- use_export_name_with_copy.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %C: type = class_type @C [template] @@ -538,7 +543,6 @@ var c: Other.C = {.x = ()}; // CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+10, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+8, unloaded // CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+9, unloaded -// CHECK:STDOUT: %import_ref.4 = import_ref ir2, inst+10, unloaded // CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C] // CHECK:STDOUT: %c.var: ref C = var c // CHECK:STDOUT: %c: ref C = bind_name c, %c.var @@ -552,14 +556,14 @@ var c: Other.C = {.x = ()}; // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc29_25.1: () = tuple_literal () -// CHECK:STDOUT: %.loc29_26.1: {.x: ()} = struct_literal (%.loc29_25.1) -// CHECK:STDOUT: %.loc29_26.2: ref () = class_element_access file.%c.var, element0 -// CHECK:STDOUT: %.loc29_25.2: init () = tuple_init () to %.loc29_26.2 [template = constants.%tuple] -// CHECK:STDOUT: %.loc29_26.3: init () = converted %.loc29_25.1, %.loc29_25.2 [template = constants.%tuple] -// CHECK:STDOUT: %.loc29_26.4: init C = class_init (%.loc29_26.3), file.%c.var [template = constants.%struct] -// CHECK:STDOUT: %.loc29_27: init C = converted %.loc29_26.1, %.loc29_26.4 [template = constants.%struct] -// CHECK:STDOUT: assign file.%c.var, %.loc29_27 +// CHECK:STDOUT: %.loc7_25.1: () = tuple_literal () +// CHECK:STDOUT: %.loc7_26.1: {.x: ()} = struct_literal (%.loc7_25.1) +// CHECK:STDOUT: %.loc7_26.2: ref () = class_element_access file.%c.var, element0 +// CHECK:STDOUT: %.loc7_25.2: init () = tuple_init () to %.loc7_26.2 [template = constants.%tuple] +// CHECK:STDOUT: %.loc7_26.3: init () = converted %.loc7_25.1, %.loc7_25.2 [template = constants.%tuple] +// CHECK:STDOUT: %.loc7_26.4: init C = class_init (%.loc7_26.3), file.%c.var [template = constants.%struct] +// CHECK:STDOUT: %.loc7_27: init C = converted %.loc7_26.1, %.loc7_26.4 [template = constants.%struct] +// CHECK:STDOUT: assign file.%c.var, %.loc7_27 // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: @@ -608,7 +612,7 @@ var c: Other.C = {.x = ()}; // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_use_export_all.carbon +// CHECK:STDOUT: --- use_export_all.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %C: type = class_type @C [template] @@ -629,9 +633,6 @@ var c: Other.C = {.x = ()}; // CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+10, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+8, unloaded // CHECK:STDOUT: %import_ref.3 = import_ref ir2, inst+9, unloaded -// CHECK:STDOUT: %import_ref.4 = import_ref ir4, inst+10, unloaded -// CHECK:STDOUT: %import_ref.5 = import_ref ir6, inst+10, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref ir7, inst+1, unloaded // CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C] // CHECK:STDOUT: %c.var: ref C = var c // CHECK:STDOUT: %c: ref C = bind_name c, %c.var @@ -645,14 +646,84 @@ var c: Other.C = {.x = ()}; // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc76_25.1: () = tuple_literal () -// CHECK:STDOUT: %.loc76_26.1: {.x: ()} = struct_literal (%.loc76_25.1) -// CHECK:STDOUT: %.loc76_26.2: ref () = class_element_access file.%c.var, element0 -// CHECK:STDOUT: %.loc76_25.2: init () = tuple_init () to %.loc76_26.2 [template = constants.%tuple] -// CHECK:STDOUT: %.loc76_26.3: init () = converted %.loc76_25.1, %.loc76_25.2 [template = constants.%tuple] -// CHECK:STDOUT: %.loc76_26.4: init C = class_init (%.loc76_26.3), file.%c.var [template = constants.%struct] -// CHECK:STDOUT: %.loc76_27: init C = converted %.loc76_26.1, %.loc76_26.4 [template = constants.%struct] -// CHECK:STDOUT: assign file.%c.var, %.loc76_27 +// CHECK:STDOUT: %.loc11_25.1: () = tuple_literal () +// CHECK:STDOUT: %.loc11_26.1: {.x: ()} = struct_literal (%.loc11_25.1) +// CHECK:STDOUT: %.loc11_26.2: ref () = class_element_access file.%c.var, element0 +// CHECK:STDOUT: %.loc11_25.2: init () = tuple_init () to %.loc11_26.2 [template = constants.%tuple] +// CHECK:STDOUT: %.loc11_26.3: init () = converted %.loc11_25.1, %.loc11_25.2 [template = constants.%tuple] +// CHECK:STDOUT: %.loc11_26.4: init C = class_init (%.loc11_26.3), file.%c.var [template = constants.%struct] +// CHECK:STDOUT: %.loc11_27: init C = converted %.loc11_26.1, %.loc11_26.4 [template = constants.%struct] +// CHECK:STDOUT: assign file.%c.var, %.loc11_27 // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- unused_conflict_on_export_import.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Other = %Other +// CHECK:STDOUT: } +// CHECK:STDOUT: %Other: = namespace [template] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- unused_conflict_on_export_name.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Other = %Other +// CHECK:STDOUT: } +// CHECK:STDOUT: %Other: = namespace [template] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_conflict_on_export_import.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = fn_type @C [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: C = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Other = %Other +// CHECK:STDOUT: .C = %C +// CHECK:STDOUT: } +// CHECK:STDOUT: %Other: = namespace [template] {} +// CHECK:STDOUT: %Other.ref: = name_ref Other, %Other [template = %Other] +// CHECK:STDOUT: %import_ref.1: C = import_ref ir2, inst+1, loaded [template = constants.%struct] +// CHECK:STDOUT: %import_ref.2 = import_ref ir3, inst+1, unloaded +// CHECK:STDOUT: %C.ref: C = name_ref C, %import_ref.1 [template = constants.%struct] +// CHECK:STDOUT: %C: C = bind_alias C, %import_ref.1 [template = constants.%struct] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @C(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_conflict_on_export_name.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %.2: type = struct_type {.x: ()} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Other = %Other +// CHECK:STDOUT: .C = %C +// CHECK:STDOUT: } +// CHECK:STDOUT: %Other: = namespace [template] {} +// CHECK:STDOUT: %Other.ref: = name_ref Other, %Other [template = %Other] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+10, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+8, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+9, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref ir2, inst+1, unloaded +// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %C: type = bind_alias C, %import_ref.1 [template = constants.%C] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 +// CHECK:STDOUT: .x = file.%import_ref.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: