diff --git a/toolchain/check/check.cpp b/toolchain/check/check.cpp index 61f0947987c09..7dbefecf83cbd 100644 --- a/toolchain/check/check.cpp +++ b/toolchain/check/check.cpp @@ -97,9 +97,37 @@ struct UnitInfo { }; } // namespace -// Collects transitive imports, handling deduplication. -static auto CollectTransitiveImports(const UnitInfo::PackageImports& imports, - int total_ir_count) +// Collects direct imports, for CollectTransitiveImports. +static auto CollectDirectImports(llvm::SmallVector& results, + llvm::MutableArrayRef ir_to_result_index, + const UnitInfo::PackageImports& imports, + bool is_local) -> void { + for (const auto& import : imports.imports) { + const auto& direct_ir = **import.unit_info->unit->sem_ir; + auto& index = ir_to_result_index[direct_ir.check_ir_id().index]; + if (index != -1) { + // This should only happen when doing API imports for an implementation + // file. Don't change the entry; is_export doesn't matter. + continue; + } + index = results.size(); + results.push_back( + // TODO: For !is_local, should this use something valid that points at + // the API's import? That would probably require something other than a + // node_id, such as a LocId. + {.node_id = is_local ? import.names.node_id : Parse::InvalidNodeId(), + .sem_ir = &direct_ir, + // Only tag exports in API files, ignoring the value in implementation + // files. + .is_export = is_local && import.names.is_export}); + } +} + +// Collects transitive imports, handling deduplication. These will be unified +// between local_imports and api_imports. +static auto CollectTransitiveImports( + const UnitInfo::PackageImports* local_imports, + const UnitInfo::PackageImports* api_imports, int total_ir_count) -> llvm::SmallVector { llvm::SmallVector results; @@ -110,12 +138,13 @@ static auto CollectTransitiveImports(const UnitInfo::PackageImports& imports, // First add direct imports. This means that if an entity is imported both // directly and indirectly, the import path will reflect the direct import. - for (const auto& import : imports.imports) { - const auto& direct_ir = **import.unit_info->unit->sem_ir; - ir_to_result_index[direct_ir.check_ir_id().index] = results.size(); - results.push_back({.node_id = import.names.node_id, - .sem_ir = &direct_ir, - .is_export = import.names.is_export}); + if (local_imports) { + CollectDirectImports(results, ir_to_result_index, *local_imports, + /*is_local=*/true); + } + if (api_imports) { + CollectDirectImports(results, ir_to_result_index, *api_imports, + /*is_local=*/false); } // Loop through direct imports for any indirect exports. The underlying vector @@ -171,14 +200,106 @@ static auto ImportCurrentPackage(Context& context, UnitInfo& unit_info, ImportLibrariesFromCurrentPackage( context, namespace_type_id, - CollectTransitiveImports(self_import, total_ir_count)); + CollectTransitiveImports(&self_import, /*api_imports=*/nullptr, + total_ir_count)); context.scope_stack().Push( package_inst_id, SemIR::NameScopeId::Package, context.name_scopes().Get(SemIR::NameScopeId::Package).has_error); } +// Imports all other packages (excluding the current package). +static auto ImportOtherPackages(Context& context, UnitInfo& unit_info, + int total_ir_count, + SemIR::TypeId namespace_type_id) -> void { + // api_imports_list is initially the size of the current file's imports, + // including for API files, for simplicity in iteration. It's only really used + // when processing an implementation file, in order to combine the API file + // imports. + // + // For packages imported by the API file, the IdentifierId is the package name + // and the index is into the API's import list. Otherwise, the initial + // {Invalid, -1} state remains. + llvm::SmallVector> api_imports_list; + api_imports_list.resize(unit_info.package_imports.size(), + {IdentifierId::Invalid, -1}); + + // When there's an API file, add the mapping to api_imports_list. + if (unit_info.api_for_impl) { + const auto& api_identifiers = + unit_info.api_for_impl->unit->value_stores->identifiers(); + auto& impl_identifiers = unit_info.unit->value_stores->identifiers(); + + for (auto [api_imports_index, api_imports] : + llvm::enumerate(unit_info.api_for_impl->package_imports)) { + // Skip the current package. + if (!api_imports.package_id.is_valid()) { + continue; + } + // Translate the package ID from the API file to the implementation file. + auto impl_package_id = + impl_identifiers.Add(api_identifiers.Get(api_imports.package_id)); + if (auto it = unit_info.package_imports_map.find(impl_package_id); + it != unit_info.package_imports_map.end()) { + // On a hit, replace the entry to unify the API and implementation + // imports. + api_imports_list[it->second] = {impl_package_id, api_imports_index}; + } else { + // On a miss, add the package as API-only. + api_imports_list.push_back({impl_package_id, api_imports_index}); + } + } + } + + for (auto [i, api_imports_entry] : llvm::enumerate(api_imports_list)) { + // These variables are updated after figuring out which imports are present. + Parse::ImportDeclId node_id = Parse::InvalidNodeId(); + IdentifierId package_id = IdentifierId::Invalid; + bool has_load_error = false; + + // Identify the local package imports if present. + const UnitInfo::PackageImports* local_imports = nullptr; + if (i < unit_info.package_imports.size()) { + local_imports = &unit_info.package_imports[i]; + if (!local_imports->package_id.is_valid()) { + // Skip the current package. + continue; + } + node_id = local_imports->node_id; + package_id = local_imports->package_id; + has_load_error |= local_imports->has_load_error; + } + + // Identify the API package imports if present. + const UnitInfo::PackageImports* api_imports = nullptr; + if (api_imports_entry.second != -1) { + api_imports = + &unit_info.api_for_impl->package_imports[api_imports_entry.second]; + if (!package_id.is_valid()) { + package_id = api_imports_entry.first; + } else { + CARBON_CHECK(package_id == api_imports_entry.first); + } + has_load_error |= api_imports->has_load_error; + } + + // Do the actual import. + ImportLibrariesFromOtherPackage( + context, namespace_type_id, node_id, package_id, + CollectTransitiveImports(local_imports, api_imports, total_ir_count), + has_load_error); + } +} + // Add imports to the root block. +// TODO: Should this be importing all namespaces before anything else, including +// for imports from other packages? Otherwise, name conflict resolution +// involving something such as `fn F() -> Other.NS.A`, wherein `Other.NS` +// hasn't been imported yet (before `Other.NS` had a constant assigned), could +// result in an inconsistent scoping for `Other.NS.A` versus if it were imported +// as part of scanning `Other.NS` (after `Other.NS` had a constant assigned). +// This will probably require IRs separating out which namespaces they +// declare (or declare entities inside). static auto InitPackageScopeAndImports(Context& context, UnitInfo& unit_info, int total_ir_count) -> void { // First create the constant values map for all imported IRs. We'll populate @@ -217,10 +338,9 @@ static auto InitPackageScopeAndImports(Context& context, UnitInfo& unit_info, // If there is an implicit `api` import, set it first so that it uses the // ImportIRId::ApiForImpl when processed for imports. if (unit_info.api_for_impl) { - SetApiImportIR( - context, - {.node_id = context.parse_tree().packaging_decl()->names.node_id, - .sem_ir = &**unit_info.api_for_impl->unit->sem_ir}); + auto node_id = context.parse_tree().packaging_decl()->names.node_id; + const auto& api_sem_ir = **unit_info.api_for_impl->unit->sem_ir; + ImportApiFile(context, namespace_type_id, node_id, api_sem_ir); } else { SetApiImportIR(context, {.node_id = Parse::InvalidNodeId(), .sem_ir = nullptr}); @@ -229,19 +349,7 @@ static auto InitPackageScopeAndImports(Context& context, UnitInfo& unit_info, ImportCurrentPackage(context, unit_info, total_ir_count, package_inst_id, namespace_type_id); CARBON_CHECK(context.scope_stack().PeekIndex() == ScopeIndex::Package); - - for (auto& package_imports : unit_info.package_imports) { - if (!package_imports.package_id.is_valid()) { - // Current package is handled above. - continue; - } - - ImportLibrariesFromOtherPackage( - context, namespace_type_id, package_imports.node_id, - package_imports.package_id, - CollectTransitiveImports(package_imports, total_ir_count), - package_imports.has_load_error); - } + ImportOtherPackages(context, unit_info, total_ir_count, namespace_type_id); } namespace { diff --git a/toolchain/check/import.cpp b/toolchain/check/import.cpp index 97138eaad43f9..e5cdfa9d728b0 100644 --- a/toolchain/check/import.cpp +++ b/toolchain/check/import.cpp @@ -145,10 +145,10 @@ static auto CacheCopiedNamespace( // Copies a namespace from the import IR, returning its ID. This may diagnose // name conflicts, but that won't change the result because namespaces supersede -// other names in conflicts. +// other names in conflicts. copied_namespaces is optional. static auto CopySingleNameScopeFromImportIR( Context& context, SemIR::TypeId namespace_type_id, - llvm::DenseMap& copied_namespaces, + llvm::DenseMap* copied_namespaces, SemIR::ImportIRId ir_id, SemIR::InstId import_inst_id, SemIR::NameScopeId import_scope_id, SemIR::NameScopeId parent_scope_id, SemIR::NameId name_id) -> SemIR::NameScopeId { @@ -172,7 +172,10 @@ static auto CopySingleNameScopeFromImportIR( context.import_ir_constant_values()[ir_id.index].Set(import_inst_id, namespace_const_id); - CacheCopiedNamespace(copied_namespaces, import_scope_id, namespace_scope_id); + if (copied_namespaces) { + CacheCopiedNamespace(*copied_namespaces, import_scope_id, + namespace_scope_id); + } return namespace_scope_id; } @@ -219,7 +222,7 @@ static auto CopyAncestorNameScopesFromImportIR( auto name_id = CopyNameFromImportIR(context, import_sem_ir, import_scope.name_id); scope_cursor = CopySingleNameScopeFromImportIR( - context, namespace_type_id, copied_namespaces, ir_id, + context, namespace_type_id, &copied_namespaces, ir_id, import_scope.inst_id, import_scope_id, scope_cursor, name_id); } @@ -257,6 +260,91 @@ static auto AddImportRefOrMerge(Context& context, SemIR::ImportIRId ir_id, &import_sem_ir, import_inst_id); } +namespace { +// A scope in the API file that still needs to be copied to the implementation +// file. Only used for API file imports. +struct TodoScope { + // The scope's instruction in the API file. + SemIR::InstId api_inst_id; + // The scope in the API file. + SemIR::NameScopeId api_scope_id; + // The already-translated scope name in the implementation file. + SemIR::NameId impl_name_id; + // The already-copied parent scope in the implementation file. + SemIR::NameScopeId impl_parent_scope_id; +}; +} // namespace + +// Imports entries in a specific scope into the current file. +static auto ImportScopeFromApiFile(Context& context, + const SemIR::File& api_sem_ir, + SemIR::NameScopeId api_scope_id, + SemIR::NameScopeId impl_scope_id, + llvm::SmallVector& todo_scopes) + -> void { + const auto& api_scope = api_sem_ir.name_scopes().Get(api_scope_id); + auto& impl_scope = context.name_scopes().Get(impl_scope_id); + + for (const auto& api_entry : api_scope.names) { + auto impl_name_id = + CopyNameFromImportIR(context, api_sem_ir, api_entry.name_id); + if (auto ns = + api_sem_ir.insts().TryGetAs(api_entry.inst_id)) { + // Ignore cross-package imports. These will be handled through + // ImportLibrariesFromOtherPackage. + if (api_scope_id == SemIR::NameScopeId::Package) { + const auto& ns_scope = api_sem_ir.name_scopes().Get(ns->name_scope_id); + if (!ns_scope.import_ir_scopes.empty()) { + continue; + } + } + + // Namespaces will be recursed into. Name scope creation is delayed in + // order to avoid invalidating api_scope/impl_scope. + todo_scopes.push_back({.api_inst_id = api_entry.inst_id, + .api_scope_id = ns->name_scope_id, + .impl_name_id = impl_name_id, + .impl_parent_scope_id = impl_scope_id}); + } else { + // Add an ImportRef for other instructions. + auto impl_bind_name_id = context.bind_names().Add( + {.name_id = impl_name_id, + .parent_scope_id = impl_scope_id, + .bind_index = SemIR::CompileTimeBindIndex::Invalid}); + auto import_ref_id = AddImportRef(context, + {.ir_id = SemIR::ImportIRId::ApiForImpl, + .inst_id = api_entry.inst_id}, + impl_bind_name_id); + impl_scope.AddRequired({.name_id = impl_name_id, + .inst_id = import_ref_id, + .access_kind = api_entry.access_kind}); + } + } +} + +auto ImportApiFile(Context& context, SemIR::TypeId namespace_type_id, + Parse::ImportDeclId node_id, const SemIR::File& api_sem_ir) + -> void { + SetApiImportIR(context, {.node_id = node_id, .sem_ir = &api_sem_ir}); + context.import_ir_constant_values()[SemIR::ImportIRId::ApiForImpl.index].Set( + SemIR::InstId::PackageNamespace, + context.constant_values().Get(SemIR::InstId::PackageNamespace)); + + llvm::SmallVector todo_scopes = {}; + ImportScopeFromApiFile(context, api_sem_ir, SemIR::NameScopeId::Package, + SemIR::NameScopeId::Package, todo_scopes); + while (!todo_scopes.empty()) { + auto todo_scope = todo_scopes.pop_back_val(); + auto impl_scope_id = CopySingleNameScopeFromImportIR( + context, namespace_type_id, /*copied_namespaces=*/nullptr, + SemIR::ImportIRId::ApiForImpl, todo_scope.api_inst_id, + todo_scope.api_scope_id, todo_scope.impl_parent_scope_id, + todo_scope.impl_name_id); + ImportScopeFromApiFile(context, api_sem_ir, todo_scope.api_scope_id, + impl_scope_id, todo_scopes); + } +} + auto ImportLibrariesFromCurrentPackage( Context& context, SemIR::TypeId namespace_type_id, llvm::ArrayRef import_irs) -> void { @@ -285,7 +373,7 @@ auto ImportLibrariesFromCurrentPackage( // Namespaces are always imported because they're essential for // qualifiers, and the type is simple. CopySingleNameScopeFromImportIR( - context, namespace_type_id, copied_namespaces, ir_id, + context, namespace_type_id, &copied_namespaces, ir_id, import_inst_id, import_namespace_inst->name_scope_id, parent_scope_id, name_id); } else { diff --git a/toolchain/check/import.h b/toolchain/check/import.h index 5e216aab51bc2..aac05113ef883 100644 --- a/toolchain/check/import.h +++ b/toolchain/check/import.h @@ -11,6 +11,14 @@ namespace Carbon::Check { +// Imports the API file's name lookup information into a corresponding +// implementation file. Only information for the current package will be copied; +// information for other packages should be handled through +// ImportLibrariesFromOtherPackage. +auto ImportApiFile(Context& context, SemIR::TypeId namespace_type_id, + Parse::ImportDeclId node_id, const SemIR::File& api_sem_ir) + -> void; + // Add the current package's imports to name lookup. This pulls in all names; // conflicts for things such as `package.a.b.c` will be flagged even though they // are several layers deep. diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index f4bdabdb56eb3..303272434c388 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -577,6 +577,7 @@ class ImportRefResolver { // unresolved constants to the work stack. auto GetLocalNameScopeId(SemIR::NameScopeId name_scope_id) -> SemIR::NameScopeId { + // Get the instruction that created the scope. auto [inst_id, inst] = import_ir_.name_scopes().GetInstIfValid(name_scope_id); if (!inst) { @@ -585,14 +586,29 @@ class ImportRefResolver { // to remap them. return SemIR::NameScopeId::Invalid; } - if (inst->Is()) { - // TODO: Import the scope for an `impl` definition. - return SemIR::NameScopeId::Invalid; + + // Get the constant value for the scope. + auto const_id = SemIR::ConstantId::Invalid; + CARBON_KIND_SWITCH(*inst) { + case SemIR::ImplDecl::Kind: + // TODO: Import the scope for an `impl` definition. + return SemIR::NameScopeId::Invalid; + + case SemIR::Namespace::Kind: + // If the namespace has already been imported, we can use its constant. + // However, if it hasn't, we use Invalid instead of adding it to the + // work stack. That's expected to be okay when resolving references. + const_id = import_ir_constant_values().Get(inst_id); + break; + + default: + const_id = GetLocalConstantId(inst_id); } - auto const_inst_id = GetLocalConstantInstId(inst_id); - if (!const_inst_id.is_valid()) { + if (!const_id.is_valid()) { return SemIR::NameScopeId::Invalid; } + + auto const_inst_id = context_.constant_values().GetInstId(const_id); auto name_scope_inst = context_.insts().Get(const_inst_id); CARBON_KIND_SWITCH(name_scope_inst) { case CARBON_KIND(SemIR::Namespace inst): { @@ -742,6 +758,10 @@ class ImportRefResolver { case CARBON_KIND(SemIR::IntLiteral inst): { return TryResolveTypedInst(inst); } + case CARBON_KIND(SemIR::Namespace inst): { + CARBON_FATAL() << "Namespaces shouldn't need resolution this way: " + << inst; + } case CARBON_KIND(SemIR::PointerType inst): { return TryResolveTypedInst(inst); } @@ -1546,8 +1566,11 @@ static auto GetInstForLoad(Context& context, 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; - import_ir_insts.push_back({.ir_id = context.GetImportIRId(*cursor_ir), - .inst_id = import_ir_inst.inst_id}); + import_ir_insts.push_back( + {.ir_id = AddImportIR(context, {.node_id = Parse::NodeId::Invalid, + .sem_ir = cursor_ir, + .is_export = false}), + .inst_id = import_ir_inst.inst_id}); } } diff --git a/toolchain/check/testdata/alias/no_prelude/import_access.carbon b/toolchain/check/testdata/alias/no_prelude/import_access.carbon index d8f0998156de4..8b10f16f0ddf9 100644 --- a/toolchain/check/testdata/alias/no_prelude/import_access.carbon +++ b/toolchain/check/testdata/alias/no_prelude/import_access.carbon @@ -23,14 +23,10 @@ private alias A = C; // Test files // ============================================================================ -// --- fail_todo_def.impl.carbon +// --- def.impl.carbon impl package Test library "def"; -// CHECK:STDERR: fail_todo_def.impl.carbon:[[@LINE+4]]:11: ERROR: Name `A` not found. -// CHECK:STDERR: var inst: A = {}; -// CHECK:STDERR: ^ -// CHECK:STDERR: var inst: A = {}; // --- fail_local_def.carbon @@ -78,27 +74,41 @@ var inst: Test.A = {}; // CHECK:STDOUT: .Self = constants.%C // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_def.impl.carbon +// CHECK:STDOUT: --- def.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: %struct: %C = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .C = %import_ref +// CHECK:STDOUT: .C = %import_ref.1 +// CHECK:STDOUT: .A [private] = %import_ref.2 // CHECK:STDOUT: .inst = %inst // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref = import_ref ir0, inst+1, unloaded -// CHECK:STDOUT: %A.ref: = name_ref A, [template = ] -// CHECK:STDOUT: %inst.var: ref = var inst -// CHECK:STDOUT: %inst: ref = bind_name inst, %inst.var +// CHECK:STDOUT: %import_ref.1 = import_ref ir0, inst+1, unloaded +// CHECK:STDOUT: %import_ref.2: type = import_ref ir0, inst+5, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.3 = import_ref ir0, inst+2, unloaded +// CHECK:STDOUT: %A.ref: type = name_ref A, %import_ref.2 [template = constants.%C] +// CHECK:STDOUT: %inst.var: ref %C = var inst +// CHECK:STDOUT: %inst: ref %C = bind_name inst, %inst.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.3 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc8: %.1 = struct_literal () -// CHECK:STDOUT: assign file.%inst.var, +// CHECK:STDOUT: %.loc4_16.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc4_16.2: init %C = class_init (), file.%inst.var [template = constants.%struct] +// CHECK:STDOUT: %.loc4_17: init %C = converted %.loc4_16.1, %.loc4_16.2 [template = constants.%struct] +// CHECK:STDOUT: assign file.%inst.var, %.loc4_17 // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/no_prelude/import_access.carbon b/toolchain/check/testdata/class/no_prelude/import_access.carbon index 857988dd0c743..c3f0224460439 100644 --- a/toolchain/check/testdata/class/no_prelude/import_access.carbon +++ b/toolchain/check/testdata/class/no_prelude/import_access.carbon @@ -36,14 +36,10 @@ private class Forward; // Test files // ============================================================================ -// --- fail_todo_def.impl.carbon +// --- def.impl.carbon impl package Test library "def"; -// CHECK:STDERR: fail_todo_def.impl.carbon:[[@LINE+4]]:8: ERROR: Name `Def` not found. -// CHECK:STDERR: var c: Def = {}; -// CHECK:STDERR: ^~~ -// CHECK:STDERR: var c: Def = {}; // --- fail_local_def.carbon @@ -70,14 +66,10 @@ import Test library "def"; // CHECK:STDERR: var c: Test.Def = {}; -// --- fail_todo_forward_with_def.impl.carbon +// --- forward_with_def.impl.carbon impl package Test library "forward_with_def"; -// CHECK:STDERR: fail_todo_forward_with_def.impl.carbon:[[@LINE+4]]:8: ERROR: Name `ForwardWithDef` not found. -// CHECK:STDERR: var c: ForwardWithDef = {}; -// CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: var c: ForwardWithDef = {}; // --- fail_local_forward_with_def.carbon @@ -104,14 +96,10 @@ import Test library "forward_with_def"; // CHECK:STDERR: var c: Test.ForwardWithDef = {}; -// --- fail_todo_forward.impl.carbon +// --- forward.impl.carbon impl package Test library "forward"; -// CHECK:STDERR: fail_todo_forward.impl.carbon:[[@LINE+4]]:9: ERROR: Name `Forward` not found. -// CHECK:STDERR: fn F(c: Forward*) {} -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: fn F(c: Forward*) {} class Forward {} @@ -201,25 +189,39 @@ private class Redecl {} // CHECK:STDOUT: // CHECK:STDOUT: class @Forward; // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_def.impl.carbon +// CHECK:STDOUT: --- def.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { +// CHECK:STDOUT: %Def: type = class_type @Def [template] // CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: %struct: %Def = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Def [private] = %import_ref.1 // CHECK:STDOUT: .c = %c // CHECK:STDOUT: } -// CHECK:STDOUT: %Def.ref: = name_ref Def, [template = ] -// CHECK:STDOUT: %c.var: ref = var c -// CHECK:STDOUT: %c: ref = bind_name c, %c.var +// CHECK:STDOUT: %import_ref.1: type = import_ref ir0, inst+1, loaded [template = constants.%Def] +// CHECK:STDOUT: %import_ref.2 = import_ref ir0, inst+2, unloaded +// CHECK:STDOUT: %Def.ref: type = name_ref Def, %import_ref.1 [template = constants.%Def] +// CHECK:STDOUT: %c.var: ref %Def = var c +// CHECK:STDOUT: %c: ref %Def = bind_name c, %c.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Def { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc8: %.1 = struct_literal () -// CHECK:STDOUT: assign file.%c.var, +// CHECK:STDOUT: %.loc4_15.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc4_15.2: init %Def = class_init (), file.%c.var [template = constants.%struct] +// CHECK:STDOUT: %.loc4_16: init %Def = converted %.loc4_15.1, %.loc4_15.2 [template = constants.%struct] +// CHECK:STDOUT: assign file.%c.var, %.loc4_16 // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: @@ -270,25 +272,39 @@ private class Redecl {} // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_forward_with_def.impl.carbon +// CHECK:STDOUT: --- forward_with_def.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { +// CHECK:STDOUT: %ForwardWithDef: type = class_type @ForwardWithDef [template] // CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: %struct: %ForwardWithDef = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .ForwardWithDef [private] = %import_ref.1 // CHECK:STDOUT: .c = %c // CHECK:STDOUT: } -// CHECK:STDOUT: %ForwardWithDef.ref: = name_ref ForwardWithDef, [template = ] -// CHECK:STDOUT: %c.var: ref = var c -// CHECK:STDOUT: %c: ref = bind_name c, %c.var +// CHECK:STDOUT: %import_ref.1: type = import_ref ir0, inst+1, loaded [template = constants.%ForwardWithDef] +// CHECK:STDOUT: %import_ref.2 = import_ref ir0, inst+2, unloaded +// CHECK:STDOUT: %ForwardWithDef.ref: type = name_ref ForwardWithDef, %import_ref.1 [template = constants.%ForwardWithDef] +// CHECK:STDOUT: %c.var: ref %ForwardWithDef = var c +// CHECK:STDOUT: %c: ref %ForwardWithDef = bind_name c, %c.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @ForwardWithDef { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc8: %.1 = struct_literal () -// CHECK:STDOUT: assign file.%c.var, +// CHECK:STDOUT: %.loc4_26.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc4_26.2: init %ForwardWithDef = class_init (), file.%c.var [template = constants.%struct] +// CHECK:STDOUT: %.loc4_27: init %ForwardWithDef = converted %.loc4_26.1, %.loc4_26.2 [template = constants.%struct] +// CHECK:STDOUT: assign file.%c.var, %.loc4_27 // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: @@ -339,26 +355,28 @@ private class Redecl {} // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_forward.impl.carbon +// CHECK:STDOUT: --- forward.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { +// CHECK:STDOUT: %Forward: type = class_type @Forward [template] +// CHECK:STDOUT: %.1: type = ptr_type %Forward [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] -// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] -// CHECK:STDOUT: %Forward: type = class_type @Forward [template] -// CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: %.3: type = struct_type {} [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Forward [private] = %Forward.decl // CHECK:STDOUT: .F = %F.decl -// CHECK:STDOUT: .Forward = %Forward.decl // CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: type = import_ref ir0, inst+1, loaded [template = constants.%Forward] // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { -// CHECK:STDOUT: %Forward.ref: = name_ref Forward, [template = ] -// CHECK:STDOUT: %.loc8: type = ptr_type [template = ] -// CHECK:STDOUT: %c.loc8_6.1: = param c -// CHECK:STDOUT: @F.%c: = bind_name c, %c.loc8_6.1 +// CHECK:STDOUT: %Forward.ref: type = name_ref Forward, %import_ref [template = constants.%Forward] +// CHECK:STDOUT: %.loc4: type = ptr_type %Forward [template = constants.%.1] +// CHECK:STDOUT: %c.loc4_6.1: %.1 = param c +// CHECK:STDOUT: @F.%c: %.1 = bind_name c, %c.loc4_6.1 // CHECK:STDOUT: } // CHECK:STDOUT: %Forward.decl: type = class_decl @Forward [template = constants.%Forward] {} // CHECK:STDOUT: } @@ -368,7 +386,7 @@ private class Redecl {} // CHECK:STDOUT: .Self = constants.%Forward // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F(%c: ) { +// CHECK:STDOUT: fn @F(%c: %.1) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/function/definition/import_access.carbon b/toolchain/check/testdata/function/definition/import_access.carbon index 2178e35a95a40..74bc5abb6d028 100644 --- a/toolchain/check/testdata/function/definition/import_access.carbon +++ b/toolchain/check/testdata/function/definition/import_access.carbon @@ -36,14 +36,10 @@ private fn Forward(); // Test files // ============================================================================ -// --- fail_todo_def.impl.carbon +// --- def.impl.carbon impl package Test library "def"; -// CHECK:STDERR: fail_todo_def.impl.carbon:[[@LINE+4]]:13: ERROR: Name `Def` not found. -// CHECK:STDERR: var f: () = Def(); -// CHECK:STDERR: ^~~ -// CHECK:STDERR: var f: () = Def(); // --- fail_local_def.carbon @@ -70,14 +66,10 @@ import Test library "def"; // CHECK:STDERR: var f: () = Test.Def(); -// --- fail_todo_forward_with_def.impl.carbon +// --- forward_with_def.impl.carbon impl package Test library "forward_with_def"; -// CHECK:STDERR: fail_todo_forward_with_def.impl.carbon:[[@LINE+4]]:13: ERROR: Name `ForwardWithDef` not found. -// CHECK:STDERR: var f: () = ForwardWithDef(); -// CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: var f: () = ForwardWithDef(); // --- fail_local_forward_with_def.carbon @@ -104,14 +96,10 @@ import Test library "forward_with_def"; // CHECK:STDERR: var f: () = Test.ForwardWithDef(); -// --- fail_todo_forward.impl.carbon +// --- forward.impl.carbon impl package Test library "forward"; -// CHECK:STDERR: fail_todo_forward.impl.carbon:[[@LINE+4]]:13: ERROR: Name `Forward` not found. -// CHECK:STDERR: var f: () = Forward(); -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: var f: () = Forward(); fn Forward() {} @@ -211,28 +199,35 @@ private fn Redecl() {} // CHECK:STDOUT: // CHECK:STDOUT: fn @Forward(); // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_def.impl.carbon +// CHECK:STDOUT: --- def.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %Def.type: type = fn_type @Def [template] +// CHECK:STDOUT: %Def: %Def.type = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Def [private] = %import_ref // CHECK:STDOUT: .Core = %Core // CHECK:STDOUT: .f = %f // CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Def.type = import_ref ir0, inst+2, loaded [template = constants.%Def] // CHECK:STDOUT: %Core: = namespace [template] {} -// CHECK:STDOUT: %.loc8_9.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc8_9.2: type = converted %.loc8_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %.loc4_9.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc4_9.2: type = converted %.loc4_9.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %f.var: ref %.1 = var f // CHECK:STDOUT: %f: ref %.1 = bind_name f, %f.var // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: fn @Def(); +// CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %Def.ref: = name_ref Def, [template = ] -// CHECK:STDOUT: assign file.%f.var, +// CHECK:STDOUT: %Def.ref: %Def.type = name_ref Def, file.%import_ref [template = constants.%Def] +// CHECK:STDOUT: %Def.call: init %.1 = call %Def.ref() +// CHECK:STDOUT: assign file.%f.var, %Def.call // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: @@ -289,28 +284,35 @@ private fn Redecl() {} // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_forward_with_def.impl.carbon +// CHECK:STDOUT: --- forward_with_def.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %ForwardWithDef.type: type = fn_type @ForwardWithDef [template] +// CHECK:STDOUT: %ForwardWithDef: %ForwardWithDef.type = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .ForwardWithDef [private] = %import_ref // CHECK:STDOUT: .Core = %Core // CHECK:STDOUT: .f = %f // CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %ForwardWithDef.type = import_ref ir0, inst+2, loaded [template = constants.%ForwardWithDef] // CHECK:STDOUT: %Core: = namespace [template] {} -// CHECK:STDOUT: %.loc8_9.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc8_9.2: type = converted %.loc8_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %.loc4_9.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc4_9.2: type = converted %.loc4_9.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %f.var: ref %.1 = var f // CHECK:STDOUT: %f: ref %.1 = bind_name f, %f.var // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: fn @ForwardWithDef(); +// CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %ForwardWithDef.ref: = name_ref ForwardWithDef, [template = ] -// CHECK:STDOUT: assign file.%f.var, +// CHECK:STDOUT: %ForwardWithDef.ref: %ForwardWithDef.type = name_ref ForwardWithDef, file.%import_ref [template = constants.%ForwardWithDef] +// CHECK:STDOUT: %ForwardWithDef.call: init %.1 = call %ForwardWithDef.ref() +// CHECK:STDOUT: assign file.%f.var, %ForwardWithDef.call // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: @@ -367,7 +369,7 @@ private fn Redecl() {} // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_forward.impl.carbon +// CHECK:STDOUT: --- forward.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %.1: type = tuple_type () [template] @@ -377,13 +379,14 @@ private fn Redecl() {} // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Forward [private] = %Forward.decl // CHECK:STDOUT: .Core = %Core // CHECK:STDOUT: .f = %f -// CHECK:STDOUT: .Forward = %Forward.decl // CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Forward.type = import_ref ir0, inst+2, loaded [template = constants.%Forward] // CHECK:STDOUT: %Core: = namespace [template] {} -// CHECK:STDOUT: %.loc8_9.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc8_9.2: type = converted %.loc8_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %.loc4_9.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc4_9.2: type = converted %.loc4_9.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %f.var: ref %.1 = var f // CHECK:STDOUT: %f: ref %.1 = bind_name f, %f.var // CHECK:STDOUT: %Forward.decl: %Forward.type = fn_decl @Forward [template = constants.%Forward] {} @@ -396,8 +399,9 @@ private fn Redecl() {} // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %Forward.ref: = name_ref Forward, [template = ] -// CHECK:STDOUT: assign file.%f.var, +// CHECK:STDOUT: %Forward.ref: %Forward.type = name_ref Forward, file.%import_ref [template = constants.%Forward] +// CHECK:STDOUT: %Forward.call: init %.1 = call %Forward.ref() +// CHECK:STDOUT: assign file.%f.var, %Forward.call // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/import_access.carbon b/toolchain/check/testdata/interface/no_prelude/import_access.carbon index 41032cee4bbdd..bae0992cf8070 100644 --- a/toolchain/check/testdata/interface/no_prelude/import_access.carbon +++ b/toolchain/check/testdata/interface/no_prelude/import_access.carbon @@ -37,14 +37,10 @@ package Test library "forward"; // Test files // ============================================================================ -// --- fail_todo_def.impl.carbon +// --- def.impl.carbon impl package Test library "def"; -// CHECK:STDERR: fail_todo_def.impl.carbon:[[@LINE+4]]:9: ERROR: Name `Def` not found. -// CHECK:STDERR: fn F(i: Def) {} -// CHECK:STDERR: ^~~ -// CHECK:STDERR: fn F(i: Def) {} // --- fail_local_def.carbon @@ -71,14 +67,10 @@ import Test library "def"; // CHECK:STDERR: fn F(i: Test.Def) {} -// --- fail_todo_forward_with_def.impl.carbon +// --- forward_with_def.impl.carbon impl package Test library "forward_with_def"; -// CHECK:STDERR: fail_todo_forward_with_def.impl.carbon:[[@LINE+4]]:9: ERROR: Name `ForwardWithDef` not found. -// CHECK:STDERR: fn F(i: ForwardWithDef) {} -// CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: fn F(i: ForwardWithDef) {} // --- fail_local_forward_with_def.carbon @@ -199,26 +191,37 @@ private interface Redecl {} // CHECK:STDOUT: package: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_def.impl.carbon +// CHECK:STDOUT: --- def.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Def [template] +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic] // CHECK:STDOUT: %F.type: type = fn_type @F [template] -// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Def [private] = %import_ref.1 // CHECK:STDOUT: .F = %F.decl // CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: type = import_ref ir0, inst+1, loaded [template = constants.%.1] +// CHECK:STDOUT: %import_ref.2 = import_ref ir0, inst+3, unloaded // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { -// CHECK:STDOUT: %Def.ref: = name_ref Def, [template = ] -// CHECK:STDOUT: %i.loc8_6.1: = param i -// CHECK:STDOUT: @F.%i: = bind_name i, %i.loc8_6.1 +// CHECK:STDOUT: %Def.ref: type = name_ref Def, %import_ref.1 [template = constants.%.1] +// CHECK:STDOUT: %i.loc4_6.1: %.1 = param i +// CHECK:STDOUT: @F.%i: %.1 = bind_name i, %i.loc4_6.1 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F(%i: ) { +// CHECK:STDOUT: interface @Def { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%i: %.1) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -274,26 +277,37 @@ private interface Redecl {} // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_forward_with_def.impl.carbon +// CHECK:STDOUT: --- forward_with_def.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @ForwardWithDef [template] +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic] // CHECK:STDOUT: %F.type: type = fn_type @F [template] -// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .ForwardWithDef [private] = %import_ref.1 // CHECK:STDOUT: .F = %F.decl // CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: type = import_ref ir0, inst+1, loaded [template = constants.%.1] +// CHECK:STDOUT: %import_ref.2 = import_ref ir0, inst+4, unloaded // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { -// CHECK:STDOUT: %ForwardWithDef.ref: = name_ref ForwardWithDef, [template = ] -// CHECK:STDOUT: %i.loc8_6.1: = param i -// CHECK:STDOUT: @F.%i: = bind_name i, %i.loc8_6.1 +// CHECK:STDOUT: %ForwardWithDef.ref: type = name_ref ForwardWithDef, %import_ref.1 [template = constants.%.1] +// CHECK:STDOUT: %i.loc4_6.1: %.1 = param i +// CHECK:STDOUT: @F.%i: %.1 = bind_name i, %i.loc4_6.1 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F(%i: ) { +// CHECK:STDOUT: interface @ForwardWithDef { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%i: %.1) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/let/no_prelude/import_access.carbon b/toolchain/check/testdata/let/no_prelude/import_access.carbon index 3463f3588ffbb..d6fed2b91cf8b 100644 --- a/toolchain/check/testdata/let/no_prelude/import_access.carbon +++ b/toolchain/check/testdata/let/no_prelude/import_access.carbon @@ -22,14 +22,10 @@ private let v: () = (); // Test files // ============================================================================ -// --- fail_todo_def.impl.carbon +// --- def.impl.carbon impl package Test library "def"; -// CHECK:STDERR: fail_todo_def.impl.carbon:[[@LINE+4]]:14: ERROR: Name `v` not found. -// CHECK:STDERR: let v2: () = v; -// CHECK:STDERR: ^ -// CHECK:STDERR: let v2: () = v; // --- fail_local_def.carbon @@ -79,7 +75,7 @@ let v2: () = Test.v; // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_def.impl.carbon +// CHECK:STDOUT: --- def.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %.1: type = tuple_type () [template] @@ -87,16 +83,18 @@ let v2: () = Test.v; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .v [private] = %import_ref // CHECK:STDOUT: .v2 = @__global_init.%v2 // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc8_10.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc8_10.2: type = converted %.loc8_10.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %import_ref: %.1 = import_ref ir0, inst+4, loaded +// CHECK:STDOUT: %.loc4_10.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc4_10.2: type = converted %.loc4_10.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %v.ref: = name_ref v, [template = ] -// CHECK:STDOUT: %v2: %.1 = bind_name v2, +// CHECK:STDOUT: %v.ref: %.1 = name_ref v, file.%import_ref +// CHECK:STDOUT: %v2: %.1 = bind_name v2, %v.ref // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/namespace/imported.carbon b/toolchain/check/testdata/namespace/imported.carbon index a81c8b5a9d1e3..ba0a36ed3f789 100644 --- a/toolchain/check/testdata/namespace/imported.carbon +++ b/toolchain/check/testdata/namespace/imported.carbon @@ -80,14 +80,14 @@ var package_b: () = package.NS.ChildNS.B(); // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.1: = import_ref ir0, inst+2, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.1, [template] { +// CHECK:STDOUT: .A = %import_ref.2 // CHECK:STDOUT: .ChildNS = %ChildNS -// CHECK:STDOUT: .A = %import_ref.3 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.2: = import_ref ir0, inst+3, loaded -// CHECK:STDOUT: %ChildNS: = namespace %import_ref.2, [template] { +// CHECK:STDOUT: %import_ref.2: %A.type = import_ref ir0, inst+4, loaded [template = constants.%A] +// CHECK:STDOUT: %import_ref.3: = import_ref ir0, inst+3, loaded +// CHECK:STDOUT: %ChildNS: = namespace %import_ref.3, [template] { // CHECK:STDOUT: .B = %import_ref.4 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.3: %A.type = import_ref ir0, inst+4, loaded [template = constants.%A] // CHECK:STDOUT: %import_ref.4: %B.type = import_ref ir0, inst+8, loaded [template = constants.%B] // CHECK:STDOUT: %Core: = namespace [template] {} // CHECK:STDOUT: %.loc4_9.1: %.1 = tuple_literal () @@ -115,7 +115,7 @@ var package_b: () = package.NS.ChildNS.B(); // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %NS.ref.loc4: = name_ref NS, file.%NS [template = file.%NS] -// CHECK:STDOUT: %A.ref.loc4: %A.type = name_ref A, file.%import_ref.3 [template = constants.%A] +// CHECK:STDOUT: %A.ref.loc4: %A.type = name_ref A, file.%import_ref.2 [template = constants.%A] // CHECK:STDOUT: %A.call.loc4: init %.1 = call %A.ref.loc4() // CHECK:STDOUT: assign file.%a.var, %A.call.loc4 // CHECK:STDOUT: %NS.ref.loc5: = name_ref NS, file.%NS [template = file.%NS] @@ -125,7 +125,7 @@ var package_b: () = package.NS.ChildNS.B(); // CHECK:STDOUT: assign file.%b.var, %B.call.loc5 // CHECK:STDOUT: %package.ref.loc7: = name_ref package, package [template = package] // CHECK:STDOUT: %NS.ref.loc7: = name_ref NS, file.%NS [template = file.%NS] -// CHECK:STDOUT: %A.ref.loc7: %A.type = name_ref A, file.%import_ref.3 [template = constants.%A] +// CHECK:STDOUT: %A.ref.loc7: %A.type = name_ref A, file.%import_ref.2 [template = constants.%A] // CHECK:STDOUT: %A.call.loc7: init %.1 = call %A.ref.loc7() // CHECK:STDOUT: assign file.%package_a.var, %A.call.loc7 // CHECK:STDOUT: %package.ref.loc8: = name_ref package, package [template = package] diff --git a/toolchain/check/testdata/packages/implicit_imports_prelude.carbon b/toolchain/check/testdata/packages/implicit_imports_prelude.carbon new file mode 100644 index 0000000000000..0c05a3de331c3 --- /dev/null +++ b/toolchain/check/testdata/packages/implicit_imports_prelude.carbon @@ -0,0 +1,90 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This is just checking an implicit import behavior with the prelude present. +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/packages/implicit_imports_prelude.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/packages/implicit_imports_prelude.carbon + +// --- lib.carbon + +library "lib"; + +var a: i32 = 0; + +// --- lib.impl.carbon + +impl library "lib"; + +var b: i32 = a; + +// CHECK:STDOUT: --- lib.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %.2: i32 = int_literal 0 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .a = %a +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref ir3, inst+3, loaded [template = constants.%Int32] +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc4_8.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc4_8.2: type = converted %int.make_type_32, %.loc4_8.1 [template = i32] +// CHECK:STDOUT: %a.var: ref i32 = var a +// CHECK:STDOUT: %a: ref i32 = bind_name a, %a.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc4: i32 = int_literal 0 [template = constants.%.2] +// CHECK:STDOUT: assign file.%a.var, %.loc4 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- lib.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .a = %import_ref.1 +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .b = %b +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: ref i32 = import_ref ir0, inst+12, loaded +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %import_ref.2: %Int32.type = import_ref ir3, inst+3, loaded [template = constants.%Int32] +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc4_8.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc4_8.2: type = converted %int.make_type_32, %.loc4_8.1 [template = i32] +// CHECK:STDOUT: %b.var: ref i32 = var b +// CHECK:STDOUT: %b: ref i32 = bind_name b, %b.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: ref i32 = name_ref a, file.%import_ref.1 +// CHECK:STDOUT: %.loc4: i32 = bind_value %a.ref +// CHECK:STDOUT: assign file.%b.var, %.loc4 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/packages/no_prelude/export_import.carbon b/toolchain/check/testdata/packages/no_prelude/export_import.carbon index 9b4b079cf8f94..7d7e10edf11a9 100644 --- a/toolchain/check/testdata/packages/no_prelude/export_import.carbon +++ b/toolchain/check/testdata/packages/no_prelude/export_import.carbon @@ -345,7 +345,7 @@ var indirect_c: C = {.x = ()}; // CHECK:STDOUT: .C = %import_ref.1 // CHECK:STDOUT: .c = %c // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+1, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir0, inst+1, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+2, unloaded // CHECK:STDOUT: %import_ref.3 = import_ref ir2, inst+7, unloaded // CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C] diff --git a/toolchain/check/testdata/packages/implicit_imports.carbon b/toolchain/check/testdata/packages/no_prelude/implicit_imports_empty.carbon similarity index 67% rename from toolchain/check/testdata/packages/implicit_imports.carbon rename to toolchain/check/testdata/packages/no_prelude/implicit_imports_empty.carbon index 01ce48ab9dd89..3065eafe9a349 100644 --- a/toolchain/check/testdata/packages/implicit_imports.carbon +++ b/toolchain/check/testdata/packages/no_prelude/implicit_imports_empty.carbon @@ -4,9 +4,9 @@ // // AUTOUPDATE // TIP: To test this file alone, run: -// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/packages/implicit_imports.carbon +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/packages/no_prelude/implicit_imports_empty.carbon // TIP: To dump output, run: -// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/packages/implicit_imports.carbon +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/packages/no_prelude/implicit_imports_empty.carbon // --- api_only.carbon @@ -50,90 +50,60 @@ impl library "lib"; // CHECK:STDOUT: --- api_only.carbon // CHECK:STDOUT: // CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: package: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- api_only_lib.carbon // CHECK:STDOUT: // CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: package: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- with_impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: package: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- with_impl.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: package: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- with_impl_extra.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: package: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- with_impl_lib.carbon // CHECK:STDOUT: // CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: package: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- with_impl_lib.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: package: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- main.carbon // CHECK:STDOUT: // CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: package: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- main_lib.carbon // CHECK:STDOUT: // CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: package: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- main_lib.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: package: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/packages/no_prelude/implicit_imports_entities.carbon b/toolchain/check/testdata/packages/no_prelude/implicit_imports_entities.carbon new file mode 100644 index 0000000000000..079e92513b7f6 --- /dev/null +++ b/toolchain/check/testdata/packages/no_prelude/implicit_imports_entities.carbon @@ -0,0 +1,491 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/packages/no_prelude/implicit_imports_entities.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/packages/no_prelude/implicit_imports_entities.carbon + +// ============================================================================ +// Setup files +// ============================================================================ + +// --- c1.carbon + +library "C1"; + +class C1 {} + +// --- c2.carbon + +library "C2"; + +class C2 {} + +// --- ns.carbon + +library "ns"; + +namespace NS; +class NS.C {} + +// --- o1.carbon + +package Other library "O1"; + +class O1 {} + +// --- o2.carbon + +package Other library "O2"; + +class O2 {} + +// ============================================================================ +// Test files +// ============================================================================ + +// --- mix_current_package.carbon + +library "mix_current_package"; + +import library "C1"; + +// --- mix_current_package.impl.carbon + +impl library "mix_current_package"; + +import library "C2"; + +var c1: C1 = {}; +var c2: C2 = {}; + +// --- dup_c1.carbon + +library "dup_c1"; + +import library "C1"; + +// --- dup_c1.impl.carbon + +impl library "dup_c1"; + +import library "C1"; + +var c1: C1 = {}; + +// --- use_ns.carbon + +library "use_ns"; + +import library "ns"; + +// --- use_ns.impl.carbon + +impl library "use_ns"; + +var c: NS.C = {}; + +// --- mix_other.carbon + +library "mix_other"; + +import Other library "O1"; + +// --- mix_other.impl.carbon + +impl library "mix_other"; + +import Other library "O2"; + +var o1: Other.O1 = {}; +var o2: Other.O2 = {}; + +// --- dup_o1.carbon + +library "dup_o1"; + +import Other library "O1"; + +// --- dup_o1.impl.carbon + +impl library "dup_o1"; + +import Other library "O1"; + +var o1: Other.O1 = {}; + +// CHECK:STDOUT: --- c1.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C1: type = class_type @C1 [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C1 = %C1.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C1.decl: type = class_decl @C1 [template = constants.%C1] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C1 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- c2.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C2: type = class_type @C2 [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C2 = %C2.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C2.decl: type = class_decl @C2 [template = constants.%C2] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C2 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- ns.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .NS = %NS +// CHECK:STDOUT: } +// CHECK:STDOUT: %NS: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- o1.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %O1: type = class_type @O1 [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .O1 = %O1.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %O1.decl: type = class_decl @O1 [template = constants.%O1] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @O1 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%O1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- o2.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %O2: type = class_type @O2 [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .O2 = %O2.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %O2.decl: type = class_decl @O2 [template = constants.%O2] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @O2 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%O2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- mix_current_package.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C1 = %import_ref +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref = import_ref ir1, inst+1, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- mix_current_package.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C1: type = class_type @C1 [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: %struct.1: %C1 = struct_value () [template] +// CHECK:STDOUT: %C2: type = class_type @C2 [template] +// CHECK:STDOUT: %struct.2: %C2 = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C1 = %import_ref.1 +// CHECK:STDOUT: .C2 = %import_ref.2 +// CHECK:STDOUT: .c1 = %c1 +// CHECK:STDOUT: .c2 = %c2 +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: type = import_ref ir0, inst+1, loaded [template = constants.%C1] +// CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+1, loaded [template = constants.%C2] +// CHECK:STDOUT: %import_ref.3 = import_ref ir2, inst+2, unloaded +// CHECK:STDOUT: %C1.ref: type = name_ref C1, %import_ref.1 [template = constants.%C1] +// CHECK:STDOUT: %c1.var: ref %C1 = var c1 +// CHECK:STDOUT: %c1: ref %C1 = bind_name c1, %c1.var +// CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+2, unloaded +// CHECK:STDOUT: %C2.ref: type = name_ref C2, %import_ref.2 [template = constants.%C2] +// CHECK:STDOUT: %c2.var: ref %C2 = var c2 +// CHECK:STDOUT: %c2: ref %C2 = bind_name c2, %c2.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C1 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C2 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc6_15.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc6_15.2: init %C1 = class_init (), file.%c1.var [template = constants.%struct.1] +// CHECK:STDOUT: %.loc6_16: init %C1 = converted %.loc6_15.1, %.loc6_15.2 [template = constants.%struct.1] +// CHECK:STDOUT: assign file.%c1.var, %.loc6_16 +// CHECK:STDOUT: %.loc7_15.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc7_15.2: init %C2 = class_init (), file.%c2.var [template = constants.%struct.2] +// CHECK:STDOUT: %.loc7_16: init %C2 = converted %.loc7_15.1, %.loc7_15.2 [template = constants.%struct.2] +// CHECK:STDOUT: assign file.%c2.var, %.loc7_16 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- dup_c1.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C1 = %import_ref +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref = import_ref ir1, inst+1, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- dup_c1.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C1: type = class_type @C1 [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: %struct: %C1 = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C1 = %import_ref.1 +// CHECK:STDOUT: .c1 = %c1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: type = import_ref ir0, inst+1, loaded [template = constants.%C1] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+2, unloaded +// CHECK:STDOUT: %C1.ref: type = name_ref C1, %import_ref.1 [template = constants.%C1] +// CHECK:STDOUT: %c1.var: ref %C1 = var c1 +// CHECK:STDOUT: %c1: ref %C1 = bind_name c1, %c1.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C1 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc6_15.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc6_15.2: init %C1 = class_init (), file.%c1.var [template = constants.%struct] +// CHECK:STDOUT: %.loc6_16: init %C1 = converted %.loc6_15.1, %.loc6_15.2 [template = constants.%struct] +// CHECK:STDOUT: assign file.%c1.var, %.loc6_16 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- use_ns.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .NS = %NS +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: = import_ref ir1, inst+1, loaded +// CHECK:STDOUT: %NS: = namespace %import_ref.1, [template] { +// CHECK:STDOUT: .C = %import_ref.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+2, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- use_ns.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: %struct: %C = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .NS = %NS +// CHECK:STDOUT: .c = %c +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: = import_ref ir0, inst+2, loaded +// CHECK:STDOUT: %NS: = namespace %import_ref.1, [template] { +// CHECK:STDOUT: .C = %import_ref.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.2: type = import_ref ir0, inst+3, loaded [template = constants.%C] +// CHECK:STDOUT: %NS.ref: = name_ref NS, %NS [template = %NS] +// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+3, unloaded +// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.2 [template = constants.%C] +// CHECK:STDOUT: %c.var: ref %C = var c +// CHECK:STDOUT: %c: ref %C = bind_name c, %c.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc4_16.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc4_16.2: init %C = class_init (), file.%c.var [template = constants.%struct] +// CHECK:STDOUT: %.loc4_17: init %C = converted %.loc4_16.1, %.loc4_16.2 [template = constants.%struct] +// CHECK:STDOUT: assign file.%c.var, %.loc4_17 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- mix_other.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: --- mix_other.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %O1: type = class_type @O1 [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: %struct.1: %O1 = struct_value () [template] +// CHECK:STDOUT: %O2: type = class_type @O2 [template] +// CHECK:STDOUT: %struct.2: %O2 = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Other = %Other +// CHECK:STDOUT: .o1 = %o1 +// CHECK:STDOUT: .o2 = %o2 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Other: = namespace [template] {} +// CHECK:STDOUT: %Other.ref.loc6: = name_ref Other, %Other [template = %Other] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+1, loaded [template = constants.%O1] +// CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+2, unloaded +// CHECK:STDOUT: %O1.ref: type = name_ref O1, %import_ref.1 [template = constants.%O1] +// CHECK:STDOUT: %o1.var: ref %O1 = var o1 +// CHECK:STDOUT: %o1: ref %O1 = bind_name o1, %o1.var +// CHECK:STDOUT: %Other.ref.loc7: = name_ref Other, %Other [template = %Other] +// CHECK:STDOUT: %import_ref.3: type = import_ref ir1, inst+1, loaded [template = constants.%O2] +// CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+2, unloaded +// CHECK:STDOUT: %O2.ref: type = name_ref O2, %import_ref.3 [template = constants.%O2] +// CHECK:STDOUT: %o2.var: ref %O2 = var o2 +// CHECK:STDOUT: %o2: ref %O2 = bind_name o2, %o2.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @O1 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @O2 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc6_21.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc6_21.2: init %O1 = class_init (), file.%o1.var [template = constants.%struct.1] +// CHECK:STDOUT: %.loc6_22: init %O1 = converted %.loc6_21.1, %.loc6_21.2 [template = constants.%struct.1] +// CHECK:STDOUT: assign file.%o1.var, %.loc6_22 +// CHECK:STDOUT: %.loc7_21.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc7_21.2: init %O2 = class_init (), file.%o2.var [template = constants.%struct.2] +// CHECK:STDOUT: %.loc7_22: init %O2 = converted %.loc7_21.1, %.loc7_21.2 [template = constants.%struct.2] +// CHECK:STDOUT: assign file.%o2.var, %.loc7_22 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- dup_o1.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: --- dup_o1.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %O1: type = class_type @O1 [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: %struct: %O1 = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Other = %Other +// CHECK:STDOUT: .o1 = %o1 +// 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+1, loaded [template = constants.%O1] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+2, unloaded +// CHECK:STDOUT: %O1.ref: type = name_ref O1, %import_ref.1 [template = constants.%O1] +// CHECK:STDOUT: %o1.var: ref %O1 = var o1 +// CHECK:STDOUT: %o1: ref %O1 = bind_name o1, %o1.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @O1 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc6_21.1: %.1 = struct_literal () +// CHECK:STDOUT: %.loc6_21.2: init %O1 = class_init (), file.%o1.var [template = constants.%struct] +// CHECK:STDOUT: %.loc6_22: init %O1 = converted %.loc6_21.1, %.loc6_21.2 [template = constants.%struct] +// CHECK:STDOUT: assign file.%o1.var, %.loc6_22 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/var/no_prelude/import_access.carbon b/toolchain/check/testdata/var/no_prelude/import_access.carbon index 6565f51a89352..0edfe6a461aaa 100644 --- a/toolchain/check/testdata/var/no_prelude/import_access.carbon +++ b/toolchain/check/testdata/var/no_prelude/import_access.carbon @@ -22,14 +22,10 @@ private var v: () = (); // Test files // ============================================================================ -// --- fail_todo_def.impl.carbon +// --- def.impl.carbon impl package Test library "def"; -// CHECK:STDERR: fail_todo_def.impl.carbon:[[@LINE+4]]:14: ERROR: Name `v` not found. -// CHECK:STDERR: var v2: () = v; -// CHECK:STDERR: ^ -// CHECK:STDERR: var v2: () = v; // --- fail_local_def.carbon @@ -81,26 +77,31 @@ var v2: () = Test.v; // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_def.impl.carbon +// CHECK:STDOUT: --- def.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %tuple: %.1 = tuple_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .v [private] = %import_ref // CHECK:STDOUT: .v2 = %v2 // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc8_10.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc8_10.2: type = converted %.loc8_10.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %import_ref: ref %.1 = import_ref ir0, inst+5, loaded +// CHECK:STDOUT: %.loc4_10.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc4_10.2: type = converted %.loc4_10.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %v2.var: ref %.1 = var v2 // CHECK:STDOUT: %v2: ref %.1 = bind_name v2, %v2.var // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %v.ref: = name_ref v, [template = ] -// CHECK:STDOUT: assign file.%v2.var, +// CHECK:STDOUT: %v.ref: ref %.1 = name_ref v, file.%import_ref +// CHECK:STDOUT: %.loc4_14: init %.1 = tuple_init () to file.%v2.var [template = constants.%tuple] +// CHECK:STDOUT: %.loc4_15: init %.1 = converted %v.ref, %.loc4_14 [template = constants.%tuple] +// CHECK:STDOUT: assign file.%v2.var, %.loc4_15 // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/sem_ir/file.cpp b/toolchain/sem_ir/file.cpp index 835fa57d98ad6..b38b85a2efaa2 100644 --- a/toolchain/sem_ir/file.cpp +++ b/toolchain/sem_ir/file.cpp @@ -526,15 +526,16 @@ auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory { case FieldDecl::Kind: case FunctionDecl::Kind: case ImplDecl::Kind: - case ImportRefUnloaded::Kind: case Namespace::Kind: case Return::Kind: case ReturnExpr::Kind: case StructTypeField::Kind: return ExprCategory::NotExpr; - case CARBON_KIND(ImportRefLoaded inst): { - auto import_ir_inst = ir->import_ir_insts().Get(inst.import_ir_inst_id); + case ImportRefUnloaded::Kind: + case ImportRefLoaded::Kind: { + auto import_ir_inst = ir->import_ir_insts().Get( + untyped_inst.As().import_ir_inst_id); ir = ir->import_irs().Get(import_ir_inst.ir_id).sem_ir; inst_id = import_ir_inst.inst_id; continue;