diff --git a/toolchain/check/generic.cpp b/toolchain/check/generic.cpp index d1048531084a..f38045abe027 100644 --- a/toolchain/check/generic.cpp +++ b/toolchain/check/generic.cpp @@ -44,6 +44,14 @@ static auto AddGenericConstantInstToEvalBlock( } namespace { +// A map from an instruction ID representing a canonical symbolic constant to an +// instruction within an eval block of the generic that computes the specific +// value for that constant. +// +// We arbitrarily use a small size of 256 bytes for the map. +// TODO: Determine a better number based on measurements. +using ConstantsInGenericMap = Map; + // Substitution callbacks to rebuild a generic constant in the eval block for a // generic region. class RebuildGenericConstantInEvalBlockCallbacks final @@ -52,7 +60,7 @@ class RebuildGenericConstantInEvalBlockCallbacks final RebuildGenericConstantInEvalBlockCallbacks( Context& context, SemIR::GenericId generic_id, SemIR::GenericInstIndex::Region region, - Map& constants_in_generic) + ConstantsInGenericMap& constants_in_generic) : context_(context), generic_id_(generic_id), region_(region), @@ -62,6 +70,14 @@ class RebuildGenericConstantInEvalBlockCallbacks final // block, and substitute them for the instructions in the eval block. auto Subst(SemIR::InstId& inst_id) const -> bool override { auto const_id = context_.constant_values().Get(inst_id); + if (!const_id.is_valid()) { + // An unloaded import ref should never contain anything we need to + // substitute into. Don't trigger loading it here. + CARBON_CHECK(context_.insts().Is(inst_id)) + << "Substituting into instruction with invalid constant ID: " + << context_.insts().Get(inst_id); + return true; + } if (!const_id.is_symbolic()) { // This instruction doesn't have a symbolic constant value, so can't // contain any bindings that need to be substituted. @@ -104,6 +120,8 @@ class RebuildGenericConstantInEvalBlockCallbacks final // TODO: Add a function on `Context` to add the instruction without // inserting it into the dependent instructions list or computing a // constant value for it. + // TODO: Provide a location based on the location of the instruction + // that uses the constant. auto inst_id = context_.sem_ir().insts().AddInNoBlock( SemIR::LocIdAndInst::NoLoc(new_inst)); auto const_id = AddGenericConstantInstToEvalBlock( @@ -118,7 +136,7 @@ class RebuildGenericConstantInEvalBlockCallbacks final Context& context_; SemIR::GenericId generic_id_; SemIR::GenericInstIndex::Region region_; - Map& constants_in_generic_; + ConstantsInGenericMap& constants_in_generic_; }; } // namespace @@ -129,8 +147,8 @@ class RebuildGenericConstantInEvalBlockCallbacks final static auto AddGenericTypeToEvalBlock( Context& context, SemIR::GenericId generic_id, SemIR::GenericInstIndex::Region region, - Map& constants_in_generic, - SemIR::TypeId type_id) -> SemIR::TypeId { + ConstantsInGenericMap& constants_in_generic, SemIR::TypeId type_id) + -> SemIR::TypeId { // Substitute into the type's constant instruction and rebuild it in the eval // block. auto type_inst_id = @@ -147,8 +165,8 @@ static auto AddGenericTypeToEvalBlock( static auto AddGenericConstantToEvalBlock( Context& context, SemIR::GenericId generic_id, SemIR::GenericInstIndex::Region region, - Map& constants_in_generic, - SemIR::InstId inst_id) -> SemIR::ConstantId { + ConstantsInGenericMap& constants_in_generic, SemIR::InstId inst_id) + -> SemIR::ConstantId { // Substitute into the constant value and rebuild it in the eval block if // we've not encountered it before. auto const_inst_id = context.constant_values().GetConstantInstId(inst_id); @@ -162,6 +180,24 @@ static auto AddGenericConstantToEvalBlock( return context.constant_values().Get(new_inst_id); } +// Populates a map of constants in a generic from the constants in the +// declaration region, in preparation for building the definition region. +static auto PopulateConstantsFromDeclaration( + Context& context, SemIR::GenericId generic_id, + ConstantsInGenericMap& constants_in_generic) { + // For the definition region, populate constants from the declaration. + auto decl_eval_block = context.inst_blocks().Get( + context.generics().Get(generic_id).decl_block_id); + constants_in_generic.GrowForInsertCount(decl_eval_block.size()); + for (auto inst_id : decl_eval_block) { + auto const_inst_id = context.constant_values().GetConstantInstId(inst_id); + auto result = constants_in_generic.Insert(const_inst_id, inst_id); + CARBON_CHECK(result.is_inserted()) + << "Duplicate constant in generic decl eval block: " + << context.insts().Get(const_inst_id); + } +} + // Builds and returns a block of instructions whose constant values need to be // evaluated in order to resolve a generic to a specific. static auto MakeGenericEvalBlock(Context& context, SemIR::GenericId generic_id, @@ -169,16 +205,11 @@ static auto MakeGenericEvalBlock(Context& context, SemIR::GenericId generic_id, -> SemIR::InstBlockId { context.inst_block_stack().Push(); - Map constants_in_generic; + ConstantsInGenericMap constants_in_generic; // For the definition region, populate constants from the declaration. if (region == SemIR::GenericInstIndex::Region::Definition) { - auto decl_eval_block = context.inst_blocks().Get( - context.generics().Get(generic_id).decl_block_id); - for (auto inst_id : decl_eval_block) { - constants_in_generic.Insert( - context.constant_values().GetConstantInstId(inst_id), inst_id); - } + PopulateConstantsFromDeclaration(context, generic_id, constants_in_generic); } // The work done in this loop might invalidate iterators into the generic @@ -231,6 +262,37 @@ static auto MakeGenericEvalBlock(Context& context, SemIR::GenericId generic_id, return context.inst_block_stack().Pop(); } +// Builds and returns an eval block, given the list of canonical symbolic +// constants that the instructions in the eval block should produce. This is +// used when importing a generic. +auto RebuildGenericEvalBlock(Context& context, SemIR::GenericId generic_id, + SemIR::GenericInstIndex::Region region, + llvm::ArrayRef const_ids) + -> SemIR::InstBlockId { + context.inst_block_stack().Push(); + + ConstantsInGenericMap constants_in_generic; + + // For the definition region, populate constants from the declaration. + if (region == SemIR::GenericInstIndex::Region::Definition) { + PopulateConstantsFromDeclaration(context, generic_id, constants_in_generic); + } + + constants_in_generic.GrowForInsertCount(const_ids.size()); + for (auto [i, inst_id] : llvm::enumerate(const_ids)) { + // Build a constant in the inst block. + AddGenericConstantToEvalBlock(context, generic_id, region, + constants_in_generic, inst_id); + CARBON_CHECK(context.inst_block_stack().PeekCurrentBlockContents().size() == + i + 1) + << "Produced " + << (context.inst_block_stack().PeekCurrentBlockContents().size() - i) + << " instructions when importing " << context.insts().Get(inst_id); + } + + return context.inst_block_stack().Pop(); +} + auto FinishGenericDecl(Context& context, SemIR::InstId decl_id) -> SemIR::GenericId { auto all_bindings = @@ -293,11 +355,6 @@ auto MakeSpecific(Context& context, SemIR::GenericId generic_id, SemIR::InstBlockId args_id) -> SemIR::SpecificId { auto specific_id = context.specifics().GetOrAdd(generic_id, args_id); - // TODO: Remove this once we import generics properly. - if (!generic_id.is_valid()) { - return specific_id; - } - // If this is the first time we've formed this specific, evaluate its decl // block to form information about the specific. if (!context.specifics().Get(specific_id).decl_block_id.is_valid()) { @@ -339,11 +396,7 @@ auto ResolveSpecificDefinition(Context& context, SemIR::SpecificId specific_id) -> bool { auto& specific = context.specifics().Get(specific_id); auto generic_id = specific.generic_id; - - // TODO: Remove this once we import generics properly. - if (!generic_id.is_valid()) { - return true; - } + CARBON_CHECK(generic_id.is_valid()) << "Specific with no generic ID"; if (!specific.definition_block_id.is_valid()) { // Evaluate the eval block for the definition of the generic. diff --git a/toolchain/check/generic.h b/toolchain/check/generic.h index 63424681977a..4008bd1f1746 100644 --- a/toolchain/check/generic.h +++ b/toolchain/check/generic.h @@ -31,6 +31,14 @@ auto FinishGenericRedecl(Context& context, SemIR::InstId decl_id, auto FinishGenericDefinition(Context& context, SemIR::GenericId generic_id) -> void; +// Builds and returns an eval block, given the list of canonical symbolic +// constants that the instructions in the eval block should produce. This is +// used when importing a generic. +auto RebuildGenericEvalBlock(Context& context, SemIR::GenericId generic_id, + SemIR::GenericInstIndex::Region region, + llvm::ArrayRef const_ids) + -> SemIR::InstBlockId; + // Builds a new specific, or finds an existing one if this generic has already // been referenced with these arguments. Performs substitution into the // declaration, but not the definition, of the generic. diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 1334d1433b82..2e07c156bbd3 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -267,6 +267,22 @@ class ImportRefResolver { llvm::SmallVector indirect_insts = {}; }; + // Local information associated with an imported generic. + struct GenericData { + llvm::SmallVector bindings; + // TODO: Add data for the self specific. + llvm::SmallVector decl_block; + llvm::SmallVector definition_block; + }; + + // Local information associated with an imported specific. + struct SpecificData { + SemIR::ConstantId generic_const_id; + llvm::SmallVector args; + llvm::SmallVector decl_block; + llvm::SmallVector definition_block; + }; + // Looks to see if an instruction has been resolved. If a constant is only // found indirectly, sets the constant for any indirect steps that don't // already have the constant. If a constant isn't found, returns the indirect @@ -397,6 +413,18 @@ class ImportRefResolver { return inst_ids; } + // Gets a local instruction block ID corresponding to an imported inst block + // whose contents were already imported, for example by + // GetLocalInstBlockContents. + auto GetLocalInstBlockId(SemIR::InstBlockId import_block_id, + llvm::ArrayRef contents) + -> SemIR::InstBlockId { + if (!import_block_id.is_valid()) { + return SemIR::InstBlockId::Invalid; + } + return context_.inst_blocks().Add(contents); + } + // Gets a local canonical instruction block ID corresponding to an imported // inst block whose contents were already imported, for example by // GetLocalInstBlockContents. @@ -409,43 +437,153 @@ class ImportRefResolver { return context_.inst_blocks().AddCanonical(contents); } - // Gets a local version of an imported generic. - auto GetLocalGeneric(SemIR::GenericId generic_id) -> SemIR::GenericId { + // Gets an incomplete local version of an imported generic. Most fields are + // set in the second pass. + auto MakeIncompleteGeneric(SemIR::InstId decl_id, SemIR::GenericId generic_id) + -> SemIR::GenericId { if (!generic_id.is_valid()) { return SemIR::GenericId::Invalid; } - // TODO: Support importing generics. Note that this comes up in the prelude, - // so for now we fall back to producing `Invalid` and treating imported - // generics as non-generic. - return SemIR::GenericId::Invalid; + return context_.generics().Add( + {.decl_id = decl_id, + .bindings_id = SemIR::InstBlockId::Invalid, + .self_specific_id = SemIR::SpecificId::Invalid}); } - // Gets a local argument list corresponding to the arguments of an imported - // specific. - auto GetLocalSpecificArgs(SemIR::SpecificId specific_id) - -> llvm::SmallVector { - if (!specific_id.is_valid()) { - return {}; + // Gets a local version of the data associated with a generic. + auto GetLocalGenericData(SemIR::GenericId generic_id) -> GenericData { + if (!generic_id.is_valid()) { + return GenericData(); } - return GetLocalInstBlockContents( - import_ir_.specifics().Get(specific_id).args_id); + + const auto& generic = import_ir_.generics().Get(generic_id); + return { + .bindings = GetLocalInstBlockContents(generic.bindings_id), + .decl_block = GetLocalInstBlockContents(generic.decl_block_id), + .definition_block = + GetLocalInstBlockContents(generic.definition_block_id), + }; } - // Gets a local specific whose arguments were already imported by - // GetLocalSpecificArgs. Does not add any new work. - auto GetLocalSpecific(SemIR::SpecificId specific_id, - llvm::ArrayRef args) - -> SemIR::SpecificId { + // Given the local constant values for the elements of the eval block, builds + // and returns the eval block for a region of a generic. + auto GetLocalEvalBlock(const SemIR::Generic& import_generic, + SemIR::GenericId generic_id, + SemIR::GenericInstIndex::Region region, + llvm::ArrayRef inst_ids) + -> SemIR::InstBlockId { + auto import_block_id = import_generic.GetEvalBlock(region); + if (!import_block_id.is_valid()) { + return SemIR::InstBlockId::Invalid; + } + return RebuildGenericEvalBlock(context_, generic_id, region, inst_ids); + } + + // Adds the given local generic data to the given generic. + auto SetGenericData(SemIR::GenericId import_generic_id, + SemIR::GenericId new_generic_id, + const GenericData& generic_data) -> void { + if (!import_generic_id.is_valid()) { + return; + } + + const auto& import_generic = import_ir_.generics().Get(import_generic_id); + auto& new_generic = context_.generics().Get(new_generic_id); + new_generic.bindings_id = GetLocalCanonicalInstBlockId( + import_generic.bindings_id, generic_data.bindings); + // TODO: Import or rebuild the self specific. + new_generic.decl_block_id = GetLocalEvalBlock( + import_generic, new_generic_id, + SemIR::GenericInstIndex::Region::Declaration, generic_data.decl_block); + new_generic.definition_block_id = + GetLocalEvalBlock(import_generic, new_generic_id, + SemIR::GenericInstIndex::Region::Definition, + generic_data.definition_block); + } + + // Gets a local constant value corresponding to an imported generic ID. May + // add work to the work stack and return `Invalid`. + auto GetLocalConstantId(SemIR::GenericId generic_id) -> SemIR::ConstantId { + if (!generic_id.is_valid()) { + return SemIR::ConstantId::Invalid; + } + return GetLocalConstantId( + import_ir_.insts() + .Get(import_ir_.generics().Get(generic_id).decl_id) + .type_id()); + } + + // Gets a local generic ID given the corresponding local constant ID returned + // by GetLocalConstantId for the imported generic. Does not add any new work. + auto GetLocalGenericId(SemIR::ConstantId local_const_id) -> SemIR::GenericId { + if (!local_const_id.is_valid()) { + return SemIR::GenericId::Invalid; + } + auto type = context_.insts().Get( + context_.constant_values().GetInstId(local_const_id)); + CARBON_KIND_SWITCH(type) { + case CARBON_KIND(SemIR::FunctionType fn_type): { + return context_.functions().Get(fn_type.function_id).generic_id; + } + case CARBON_KIND(SemIR::GenericClassType class_type): { + return context_.classes().Get(class_type.class_id).generic_id; + } + case CARBON_KIND(SemIR::GenericInterfaceType interface_type): { + return context_.interfaces() + .Get(interface_type.interface_id) + .generic_id; + } + default: { + CARBON_FATAL() << "Unexpected type for generic declaration: " << type; + } + } + } + + // Gets local information about an imported specific. + auto GetLocalSpecificData(SemIR::SpecificId specific_id) -> SpecificData { if (!specific_id.is_valid()) { + return {.generic_const_id = SemIR::ConstantId::Invalid, .args = {}}; + } + + const auto& specific = import_ir_.specifics().Get(specific_id); + return { + .generic_const_id = GetLocalConstantId(specific.generic_id), + .args = GetLocalInstBlockContents(specific.args_id), + .decl_block = GetLocalInstBlockContents(specific.decl_block_id), + .definition_block = + GetLocalInstBlockContents(specific.definition_block_id), + }; + } + + // Gets a local specific whose data was already imported by + // GetLocalSpecificData. Does not add any new work. + auto GetOrAddLocalSpecific(SemIR::SpecificId import_specific_id, + const SpecificData& data) -> SemIR::SpecificId { + if (!import_specific_id.is_valid()) { return SemIR::SpecificId::Invalid; } - const auto& specific = import_ir_.specifics().Get(specific_id); - // TODO: Import the generic. - auto generic_id = SemIR::GenericId::Invalid; - auto args_id = GetLocalCanonicalInstBlockId(specific.args_id, args); - // TODO: Also import the specific. - return context_.specifics().GetOrAdd(generic_id, args_id); + + // Form a corresponding local specific ID. + const auto& import_specific = + import_ir_.specifics().Get(import_specific_id); + auto generic_id = GetLocalGenericId(data.generic_const_id); + auto args_id = + GetLocalCanonicalInstBlockId(import_specific.args_id, data.args); + + // Populate the specific. Note that we might get data from multiple + // different import IRs, so only import data we don't already have. + auto specific_id = context_.specifics().GetOrAdd(generic_id, args_id); + auto& specific = context_.specifics().Get(specific_id); + if (!specific.decl_block_id.is_valid()) { + specific.decl_block_id = + GetLocalInstBlockId(import_specific.decl_block_id, data.decl_block); + } + if (!specific.definition_block_id.is_valid()) { + specific.definition_block_id = GetLocalInstBlockId( + import_specific.definition_block_id, data.definition_block); + } + return specific_id; } // Returns the ConstantId for each parameter's type. Adds unresolved constants @@ -653,7 +791,7 @@ class ImportRefResolver { return { .name_id = GetLocalNameId(import_base.name_id), .parent_scope_id = SemIR::NameScopeId::Invalid, - .generic_id = GetLocalGeneric(import_base.generic_id), + .generic_id = MakeIncompleteGeneric(decl_id, import_base.generic_id), .first_param_node_id = Parse::NodeId::Invalid, .last_param_node_id = Parse::NodeId::Invalid, .implicit_param_refs_id = import_base.implicit_param_refs_id.is_valid() @@ -854,11 +992,22 @@ class ImportRefResolver { return ResolveResult::Retry(); } + // TODO: Track an interface type, not an interface ID, on + // AssociatedEntityType. + auto interface_inst = context_.insts().Get(interface_inst_id); + SemIR::InterfaceId interface_id = SemIR::InterfaceId::Invalid; + if (interface_inst.Is()) { + interface_id = interface_inst.As().interface_id; + } else { + interface_id = + context_.types() + .GetAs(interface_inst.type_id()) + .interface_id; + } + return ResolveAs( {.type_id = SemIR::TypeId::TypeType, - .interface_id = context_.insts() - .GetAs(interface_inst_id) - .interface_id, + .interface_id = interface_id, .entity_type_id = context_.GetTypeIdForTypeConstant(entity_type_const_id)}); } @@ -1009,6 +1158,7 @@ class ImportRefResolver { GetLocalParamConstantIds(import_class.implicit_param_refs_id); llvm::SmallVector param_const_ids = GetLocalParamConstantIds(import_class.param_refs_id); + auto generic_data = GetLocalGenericData(import_class.generic_id); auto self_const_id = GetLocalConstantId(import_class.self_type_id); auto object_repr_const_id = import_class.object_repr_id.is_valid() @@ -1028,6 +1178,7 @@ class ImportRefResolver { import_class.implicit_param_refs_id, implicit_param_const_ids); new_class.param_refs_id = GetLocalParamRefsId(import_class.param_refs_id, param_const_ids); + SetGenericData(import_class.generic_id, new_class.generic_id, generic_data); new_class.self_type_id = context_.GetTypeIdForTypeConstant(self_const_id); if (import_class.is_defined()) { @@ -1043,7 +1194,7 @@ class ImportRefResolver { CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType); auto class_const_id = GetLocalConstantId(import_ir_.classes().Get(inst.class_id).decl_id); - auto args = GetLocalSpecificArgs(inst.specific_id); + auto specific_data = GetLocalSpecificData(inst.specific_id); if (HasNewWork(initial_work)) { return ResolveResult::Retry(); } @@ -1058,7 +1209,7 @@ class ImportRefResolver { } else { auto generic_class_type = context_.types().GetAs( class_const_inst.type_id()); - auto specific_id = GetLocalSpecific(inst.specific_id, args); + auto specific_id = GetOrAddLocalSpecific(inst.specific_id, specific_data); return ResolveAs( {.type_id = SemIR::TypeId::TypeType, .class_id = generic_class_type.class_id, @@ -1116,6 +1267,7 @@ class ImportRefResolver { GetLocalParamConstantIds(function.implicit_param_refs_id); llvm::SmallVector param_const_ids = GetLocalParamConstantIds(function.param_refs_id); + auto generic_data = GetLocalGenericData(function.generic_id); if (HasNewWork(initial_work)) { return ResolveResult::Retry(); @@ -1130,7 +1282,9 @@ class ImportRefResolver { auto function_decl_id = context_.AddPlaceholderInstInNoBlock( SemIR::LocIdAndInst(import_ir_inst_id, function_decl)); // TODO: Implement import for generics. - auto generic_id = GetLocalGeneric(function.generic_id); + auto generic_id = + MakeIncompleteGeneric(function_decl_id, function.generic_id); + SetGenericData(function.generic_id, generic_id, generic_data); auto new_return_storage = SemIR::InstId::Invalid; if (function.return_storage_id.is_valid()) { @@ -1173,14 +1327,18 @@ class ImportRefResolver { CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType); auto fn_val_id = GetLocalConstantInstId( import_ir_.functions().Get(inst.function_id).decl_id); + auto specific_data = GetLocalSpecificData(inst.specific_id); if (HasNewWork(initial_work)) { return ResolveResult::Retry(); } - auto fn_val = context_.insts().Get(fn_val_id); - CARBON_CHECK(context_.types().Is(fn_val.type_id())); - // TODO: Import the correct specific and build a function type constant - // using it. - return {.const_id = context_.types().GetConstantId(fn_val.type_id())}; + auto fn_type_id = context_.insts().Get(fn_val_id).type_id(); + return ResolveAs( + {.type_id = SemIR::TypeId::TypeType, + .function_id = context_.types() + .GetAs(fn_type_id) + .function_id, + .specific_id = + GetOrAddLocalSpecific(inst.specific_id, specific_data)}); } auto TryResolveTypedInst(SemIR::GenericClassType inst) -> ResolveResult { @@ -1322,6 +1480,7 @@ class ImportRefResolver { GetLocalParamConstantIds(import_interface.implicit_param_refs_id); llvm::SmallVector param_const_ids = GetLocalParamConstantIds(import_interface.param_refs_id); + auto generic_data = GetLocalGenericData(import_interface.generic_id); std::optional self_param_id; if (import_interface.is_defined()) { @@ -1338,6 +1497,8 @@ class ImportRefResolver { import_interface.implicit_param_refs_id, implicit_param_const_ids); new_interface.param_refs_id = GetLocalParamRefsId(import_interface.param_refs_id, param_const_ids); + SetGenericData(import_interface.generic_id, new_interface.generic_id, + generic_data); if (import_interface.is_defined()) { CARBON_CHECK(self_param_id); @@ -1351,7 +1512,7 @@ class ImportRefResolver { CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType); auto interface_const_id = GetLocalConstantId( import_ir_.interfaces().Get(inst.interface_id).decl_id); - auto args = GetLocalSpecificArgs(inst.specific_id); + auto specific_data = GetLocalSpecificData(inst.specific_id); if (HasNewWork(initial_work)) { return ResolveResult::Retry(); } @@ -1368,7 +1529,7 @@ class ImportRefResolver { auto generic_interface_type = context_.types().GetAs( interface_const_inst.type_id()); - auto specific_id = GetLocalSpecific(inst.specific_id, args); + auto specific_id = GetOrAddLocalSpecific(inst.specific_id, specific_data); return ResolveAs( {.type_id = SemIR::TypeId::TypeType, .interface_id = generic_interface_type.interface_id, diff --git a/toolchain/check/testdata/class/generic/import.carbon b/toolchain/check/testdata/class/generic/import.carbon index 7df195a06898..30976b38b9bc 100644 --- a/toolchain/check/testdata/class/generic/import.carbon +++ b/toolchain/check/testdata/class/generic/import.carbon @@ -231,27 +231,35 @@ class Class(U:! type) { // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] -// CHECK:STDOUT: %Class.2: type = class_type @Class, invalid(%T) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, @Class(%T) [symbolic] // CHECK:STDOUT: %.2: type = unbound_element_type %Class.2, %T [symbolic] // CHECK:STDOUT: %.3: type = struct_type {.x: %T} [symbolic] // CHECK:STDOUT: %CompleteClass.type: type = generic_class_type @CompleteClass [template] // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] // CHECK:STDOUT: %.4: type = struct_type {.n: i32} [template] -// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, invalid(%T) [symbolic] +// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic] +// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] +// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] +// CHECK:STDOUT: %F.type.2: type = fn_type @F.1, @CompleteClass(%T) [symbolic] +// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [symbolic] +// CHECK:STDOUT: %.5: type = unbound_element_type %CompleteClass.2, i32 [symbolic] // CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] -// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, invalid(i32) [template] -// CHECK:STDOUT: %F.type: type = fn_type @F [template] -// CHECK:STDOUT: %F: %F.type = struct_value () [template] -// CHECK:STDOUT: %.5: type = ptr_type %.4 [template] -// CHECK:STDOUT: %.6: i32 = int_literal 1 [template] -// CHECK:STDOUT: %struct: %CompleteClass.3 = struct_value (%.6) [template] +// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, @CompleteClass(i32) [template] +// CHECK:STDOUT: %F.type.3: type = fn_type @F.2 [template] +// CHECK:STDOUT: %F.3: %F.type.3 = struct_value () [template] +// CHECK:STDOUT: %.6: type = unbound_element_type %CompleteClass.3, i32 [template] +// CHECK:STDOUT: %F.type.4: type = fn_type @F.1, @CompleteClass(i32) [template] +// CHECK:STDOUT: %F.4: %F.type.4 = struct_value () [template] +// CHECK:STDOUT: %.7: type = ptr_type %.4 [template] +// CHECK:STDOUT: %.8: i32 = int_literal 1 [template] +// CHECK:STDOUT: %struct: %CompleteClass.3 = struct_value (%.8) [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %Class.type = import_ref Main//foo, inst+6, loaded [template = constants.%Class.1] // CHECK:STDOUT: %import_ref.2: %CompleteClass.type = import_ref Main//foo, inst+14, loaded [template = constants.%CompleteClass.1] -// CHECK:STDOUT: %import_ref.3: %F.type = import_ref Main//foo, inst+55, loaded [template = constants.%F] +// CHECK:STDOUT: %import_ref.3: %F.type.3 = import_ref Main//foo, inst+55, loaded [template = constants.%F.3] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.7 // CHECK:STDOUT: import Core//prelude @@ -282,7 +290,7 @@ class Class(U:! type) { // CHECK:STDOUT: %T.loc4_13.1: type = param T // CHECK:STDOUT: %T.loc4_13.2: type = bind_symbolic_name T 0, %T.loc4_13.1 [symbolic = constants.%T] // CHECK:STDOUT: } -// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %F.decl: %F.type.3 = fn_decl @F.2 [template = constants.%F.3] { // CHECK:STDOUT: %CompleteClass.ref: %CompleteClass.type = name_ref CompleteClass, imports.%import_ref.2 [template = constants.%CompleteClass.1] // CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] // CHECK:STDOUT: %.loc8_24.1: type = value_of_initializer %int.make_type_32 [template = i32] @@ -290,42 +298,88 @@ class Class(U:! type) { // CHECK:STDOUT: %.loc8_24.3: init type = call %CompleteClass.ref(%.loc8_24.2) [template = constants.%CompleteClass.3] // CHECK:STDOUT: %.loc8_28.1: type = value_of_initializer %.loc8_24.3 [template = constants.%CompleteClass.3] // CHECK:STDOUT: %.loc8_28.2: type = converted %.loc8_24.3, %.loc8_28.1 [template = constants.%CompleteClass.3] -// CHECK:STDOUT: @F.%return: ref %CompleteClass.3 = var +// CHECK:STDOUT: @F.2.%return: ref %CompleteClass.3 = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @Class { -// CHECK:STDOUT: %T.ref: type = name_ref T, file.%T.loc4_13.2 [symbolic = constants.%T] -// CHECK:STDOUT: %.loc5: %.2 = field_decl x, element0 [template] +// CHECK:STDOUT: generic class @Class(constants.%T: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] // CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%Class.2 -// CHECK:STDOUT: .x = %.loc5 +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] +// CHECK:STDOUT: %.1: type = unbound_element_type @Class.%Class (%Class.2), @Class.%T (%T) [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %T.ref: type = name_ref T, file.%T.loc4_13.2 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %.loc5: @Class.%.1 (%.2) = field_decl x, element0 [template] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Class.2 +// CHECK:STDOUT: .x = %.loc5 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @CompleteClass { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.4 -// CHECK:STDOUT: .n = imports.%import_ref.5 -// CHECK:STDOUT: .F = imports.%import_ref.6 +// CHECK:STDOUT: generic class @CompleteClass(constants.%T: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %CompleteClass: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic = %CompleteClass (constants.%CompleteClass.2)] +// CHECK:STDOUT: %.1: type = unbound_element_type @CompleteClass.%CompleteClass (%CompleteClass.2), i32 [symbolic = %.1 (constants.%.5)] +// CHECK:STDOUT: %F.type: type = fn_type @F.1, @CompleteClass(%T) [symbolic = %F.type (constants.%F.type.2)] +// CHECK:STDOUT: %F: @CompleteClass.%F.type (%F.type.2) = struct_value () [symbolic = %F (constants.%F.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.4 +// CHECK:STDOUT: .n = imports.%import_ref.5 +// CHECK:STDOUT: .F = imports.%import_ref.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.1(constants.%T: type) { +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn() -> i32; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: -// CHECK:STDOUT: fn @F() -> %return: %CompleteClass.3 { +// CHECK:STDOUT: fn @F.2() -> %return: %CompleteClass.3 { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc9_16: i32 = int_literal 1 [template = constants.%.6] +// CHECK:STDOUT: %.loc9_16: i32 = int_literal 1 [template = constants.%.8] // CHECK:STDOUT: %.loc9_17.1: %.4 = struct_literal (%.loc9_16) // CHECK:STDOUT: %.loc9_17.2: ref i32 = class_element_access %return, element0 -// CHECK:STDOUT: %.loc9_17.3: init i32 = initialize_from %.loc9_16 to %.loc9_17.2 [template = constants.%.6] +// CHECK:STDOUT: %.loc9_17.3: init i32 = initialize_from %.loc9_16 to %.loc9_17.2 [template = constants.%.8] // CHECK:STDOUT: %.loc9_17.4: init %CompleteClass.3 = class_init (%.loc9_17.3), %return [template = constants.%struct] // CHECK:STDOUT: %.loc9_18: init %CompleteClass.3 = converted %.loc9_17.1, %.loc9_17.4 [template = constants.%struct] // CHECK:STDOUT: return %.loc9_18 to %return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%T); +// CHECK:STDOUT: specific @Class(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(i32); +// CHECK:STDOUT: specific @Class(@Class.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @CompleteClass(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @CompleteClass(@CompleteClass.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @CompleteClass(i32) { +// CHECK:STDOUT: %T => i32 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %CompleteClass => constants.%CompleteClass.3 +// CHECK:STDOUT: %.1 => constants.%.6 +// CHECK:STDOUT: %F.type => constants.%F.type.4 +// CHECK:STDOUT: %F => constants.%F.4 +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- use_foo.carbon // CHECK:STDOUT: @@ -339,19 +393,25 @@ class Class(U:! type) { // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {.n: i32} [template] // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic] -// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, invalid(%T) [symbolic] -// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, invalid(i32) [template] -// CHECK:STDOUT: %.3: type = ptr_type %.2 [template] +// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic] // CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] // CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] -// CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template] -// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [template] +// CHECK:STDOUT: %F.type.2: type = fn_type @F.1, @CompleteClass(%T) [symbolic] +// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [symbolic] +// CHECK:STDOUT: %.3: type = unbound_element_type %CompleteClass.2, i32 [symbolic] +// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, @CompleteClass(i32) [template] +// CHECK:STDOUT: %.4: type = unbound_element_type %CompleteClass.3, i32 [template] +// CHECK:STDOUT: %F.type.3: type = fn_type @F.1, @CompleteClass(i32) [template] +// CHECK:STDOUT: %F.3: %F.type.3 = struct_value () [template] +// CHECK:STDOUT: %.5: type = ptr_type %.2 [template] +// CHECK:STDOUT: %F.type.4: type = fn_type @F.2 [template] +// CHECK:STDOUT: %F.4: %F.type.4 = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref Main//foo, inst+6, unloaded // CHECK:STDOUT: %import_ref.2: %CompleteClass.type = import_ref Main//foo, inst+14, loaded [template = constants.%CompleteClass.1] -// CHECK:STDOUT: %import_ref.3: %F.type.1 = import_ref Main//foo, inst+55, loaded [template = constants.%F.1] +// CHECK:STDOUT: %import_ref.3: %F.type.4 = import_ref Main//foo, inst+55, loaded [template = constants.%F.4] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.4 // CHECK:STDOUT: import Core//prelude @@ -365,7 +425,7 @@ class Class(U:! type) { // CHECK:STDOUT: %import_ref.4: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] // CHECK:STDOUT: %import_ref.5 = import_ref Main//foo, inst+18, unloaded // CHECK:STDOUT: %import_ref.6 = import_ref Main//foo, inst+28, unloaded -// CHECK:STDOUT: %import_ref.7: %F.type.2 = import_ref Main//foo, inst+35, loaded [template = constants.%F.2] +// CHECK:STDOUT: %import_ref.7: %F.type.2 = import_ref Main//foo, inst+35, loaded [template = constants.%F.1] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -386,11 +446,21 @@ class Class(U:! type) { // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @CompleteClass { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.5 -// CHECK:STDOUT: .n = imports.%import_ref.6 -// CHECK:STDOUT: .F = imports.%import_ref.7 +// CHECK:STDOUT: generic class @CompleteClass(constants.%T: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %CompleteClass: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic = %CompleteClass (constants.%CompleteClass.2)] +// CHECK:STDOUT: %.1: type = unbound_element_type @CompleteClass.%CompleteClass (%CompleteClass.2), i32 [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: %F.type: type = fn_type @F.1, @CompleteClass(%T) [symbolic = %F.type (constants.%F.type.2)] +// CHECK:STDOUT: %F: @CompleteClass.%F.type (%F.type.2) = struct_value () [symbolic = %F (constants.%F.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: .n = imports.%import_ref.6 +// CHECK:STDOUT: .F = imports.%import_ref.7 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; @@ -406,25 +476,43 @@ class Class(U:! type) { // CHECK:STDOUT: %.loc6_27.2: type = converted %.loc6_23.3, %.loc6_27.1 [template = constants.%CompleteClass.3] // CHECK:STDOUT: %v.var: ref %CompleteClass.3 = var v // CHECK:STDOUT: %v: ref %CompleteClass.3 = bind_name v, %v.var -// CHECK:STDOUT: %F.ref.loc6: %F.type.1 = name_ref F, imports.%import_ref.3 [template = constants.%F.1] +// CHECK:STDOUT: %F.ref.loc6: %F.type.4 = name_ref F, imports.%import_ref.3 [template = constants.%F.4] // CHECK:STDOUT: %.loc6_7: ref %CompleteClass.3 = splice_block %v.var {} // CHECK:STDOUT: %F.call.loc6: init %CompleteClass.3 = call %F.ref.loc6() to %.loc6_7 // CHECK:STDOUT: assign %v.var, %F.call.loc6 // CHECK:STDOUT: %v.ref: ref %CompleteClass.3 = name_ref v, %v -// CHECK:STDOUT: %F.ref.loc7: %F.type.2 = name_ref F, imports.%import_ref.7 [template = constants.%F.2] +// CHECK:STDOUT: %F.ref.loc7: %F.type.2 = name_ref F, imports.%import_ref.7 [template = constants.%F.1] // CHECK:STDOUT: %F.call.loc7: init i32 = call %F.ref.loc7() // CHECK:STDOUT: %.loc7_15.1: i32 = value_of_initializer %F.call.loc7 // CHECK:STDOUT: %.loc7_15.2: i32 = converted %F.call.loc7, %.loc7_15.1 // CHECK:STDOUT: return %.loc7_15.2 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.1() -> %CompleteClass.3; +// CHECK:STDOUT: generic fn @F.1(constants.%T: type) { +// CHECK:STDOUT: !definition: // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.2() -> i32; +// CHECK:STDOUT: fn() -> i32; +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%T); +// CHECK:STDOUT: fn @F.2() -> %CompleteClass.3; // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(i32); +// CHECK:STDOUT: specific @CompleteClass(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @CompleteClass(@CompleteClass.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @CompleteClass(i32) { +// CHECK:STDOUT: %T => i32 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %CompleteClass => constants.%CompleteClass.3 +// CHECK:STDOUT: %.1 => constants.%.4 +// CHECK:STDOUT: %F.type => constants.%F.type.3 +// CHECK:STDOUT: %F => constants.%F.3 +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- fail_todo_use_foo.carbon // CHECK:STDOUT: @@ -438,18 +526,25 @@ class Class(U:! type) { // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {.n: i32} [template] // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic] -// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, invalid(%T) [symbolic] -// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, invalid(i32) [template] -// CHECK:STDOUT: %.3: type = ptr_type %.2 [template] -// CHECK:STDOUT: %F.type: type = fn_type @F [template] -// CHECK:STDOUT: %F: %F.type = struct_value () [template] -// CHECK:STDOUT: %.4: type = unbound_element_type %CompleteClass.2, i32 [symbolic] +// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic] +// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] +// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] +// CHECK:STDOUT: %F.type.2: type = fn_type @F.1, @CompleteClass(%T) [symbolic] +// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [symbolic] +// CHECK:STDOUT: %.3: type = unbound_element_type %CompleteClass.2, i32 [symbolic] +// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, @CompleteClass(i32) [template] +// CHECK:STDOUT: %.4: type = unbound_element_type %CompleteClass.3, i32 [template] +// CHECK:STDOUT: %F.type.3: type = fn_type @F.1, @CompleteClass(i32) [template] +// CHECK:STDOUT: %F.3: %F.type.3 = struct_value () [template] +// CHECK:STDOUT: %.5: type = ptr_type %.2 [template] +// CHECK:STDOUT: %F.type.4: type = fn_type @F.2 [template] +// CHECK:STDOUT: %F.4: %F.type.4 = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref Main//foo, inst+6, unloaded // CHECK:STDOUT: %import_ref.2: %CompleteClass.type = import_ref Main//foo, inst+14, loaded [template = constants.%CompleteClass.1] -// CHECK:STDOUT: %import_ref.3: %F.type = import_ref Main//foo, inst+55, loaded [template = constants.%F] +// CHECK:STDOUT: %import_ref.3: %F.type.4 = import_ref Main//foo, inst+55, loaded [template = constants.%F.4] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.4 // CHECK:STDOUT: import Core//prelude @@ -462,7 +557,7 @@ class Class(U:! type) { // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.4: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] // CHECK:STDOUT: %import_ref.5 = import_ref Main//foo, inst+18, unloaded -// CHECK:STDOUT: %import_ref.6: %.4 = import_ref Main//foo, inst+28, loaded [template = %.1] +// CHECK:STDOUT: %import_ref.6: %.3 = import_ref Main//foo, inst+28, loaded [template = %.1] // CHECK:STDOUT: %import_ref.7 = import_ref Main//foo, inst+35, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: @@ -484,11 +579,21 @@ class Class(U:! type) { // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @CompleteClass { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.5 -// CHECK:STDOUT: .n = imports.%import_ref.6 -// CHECK:STDOUT: .F = imports.%import_ref.7 +// CHECK:STDOUT: generic class @CompleteClass(constants.%T: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %CompleteClass: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic = %CompleteClass (constants.%CompleteClass.2)] +// CHECK:STDOUT: %.1: type = unbound_element_type @CompleteClass.%CompleteClass (%CompleteClass.2), i32 [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: %F.type: type = fn_type @F.1, @CompleteClass(%T) [symbolic = %F.type (constants.%F.type.2)] +// CHECK:STDOUT: %F: @CompleteClass.%F.type (%F.type.2) = struct_value () [symbolic = %F (constants.%F.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: .n = imports.%import_ref.6 +// CHECK:STDOUT: .F = imports.%import_ref.7 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; @@ -504,21 +609,47 @@ class Class(U:! type) { // CHECK:STDOUT: %.loc6_27.2: type = converted %.loc6_23.3, %.loc6_27.1 [template = constants.%CompleteClass.3] // CHECK:STDOUT: %v.var: ref %CompleteClass.3 = var v // CHECK:STDOUT: %v: ref %CompleteClass.3 = bind_name v, %v.var -// CHECK:STDOUT: %F.ref: %F.type = name_ref F, imports.%import_ref.3 [template = constants.%F] +// CHECK:STDOUT: %F.ref: %F.type.4 = name_ref F, imports.%import_ref.3 [template = constants.%F.4] // CHECK:STDOUT: %.loc6_7: ref %CompleteClass.3 = splice_block %v.var {} // CHECK:STDOUT: %F.call: init %CompleteClass.3 = call %F.ref() to %.loc6_7 // CHECK:STDOUT: assign %v.var, %F.call // CHECK:STDOUT: %v.ref: ref %CompleteClass.3 = name_ref v, %v -// CHECK:STDOUT: %n.ref: %.4 = name_ref n, imports.%import_ref.6 [template = imports.%.1] +// CHECK:STDOUT: %n.ref: %.3 = name_ref n, imports.%import_ref.6 [template = imports.%.1] // CHECK:STDOUT: %.loc12: i32 = class_element_access , element0 [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F() -> %CompleteClass.3; +// CHECK:STDOUT: generic fn @F.1(constants.%T: type) { +// CHECK:STDOUT: !definition: // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%T); +// CHECK:STDOUT: fn() -> i32; +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(i32); +// CHECK:STDOUT: fn @F.2() -> %CompleteClass.3; +// CHECK:STDOUT: +// CHECK:STDOUT: specific @CompleteClass(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %CompleteClass => constants.%CompleteClass.2 +// CHECK:STDOUT: %.1 => constants.%.3 +// CHECK:STDOUT: %F.type => constants.%F.type.2 +// CHECK:STDOUT: %F => constants.%F.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @CompleteClass(@CompleteClass.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @CompleteClass(i32) { +// CHECK:STDOUT: %T => i32 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %CompleteClass => constants.%CompleteClass.3 +// CHECK:STDOUT: %.1 => constants.%.4 +// CHECK:STDOUT: %F.type => constants.%F.type.3 +// CHECK:STDOUT: %F => constants.%F.3 +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- fail_generic_arg_mismatch.carbon // CHECK:STDOUT: @@ -530,21 +661,32 @@ class Class(U:! type) { // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {.n: i32} [template] // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic] -// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, invalid(%T) [symbolic] +// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic] +// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] +// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] +// CHECK:STDOUT: %F.type.2: type = fn_type @F.1, @CompleteClass(%T) [symbolic] +// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [symbolic] +// CHECK:STDOUT: %.3: type = unbound_element_type %CompleteClass.2, i32 [symbolic] // CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] -// CHECK:STDOUT: %.3: type = ptr_type i32 [template] -// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, invalid(%.3) [template] -// CHECK:STDOUT: %.4: type = ptr_type %.2 [template] -// CHECK:STDOUT: %CompleteClass.4: type = class_type @CompleteClass, invalid(i32) [template] -// CHECK:STDOUT: %F.type: type = fn_type @F [template] -// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type i32 [template] +// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, @CompleteClass(%.4) [template] +// CHECK:STDOUT: %.5: type = unbound_element_type %CompleteClass.3, i32 [template] +// CHECK:STDOUT: %F.type.3: type = fn_type @F.1, @CompleteClass(%.4) [template] +// CHECK:STDOUT: %F.3: %F.type.3 = struct_value () [template] +// CHECK:STDOUT: %.6: type = ptr_type %.2 [template] +// CHECK:STDOUT: %CompleteClass.4: type = class_type @CompleteClass, @CompleteClass(i32) [template] +// CHECK:STDOUT: %F.type.4: type = fn_type @F.2 [template] +// CHECK:STDOUT: %F.4: %F.type.4 = struct_value () [template] +// CHECK:STDOUT: %.7: type = unbound_element_type %CompleteClass.4, i32 [template] +// CHECK:STDOUT: %F.type.5: type = fn_type @F.1, @CompleteClass(i32) [template] +// CHECK:STDOUT: %F.5: %F.type.5 = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref Main//foo, inst+6, unloaded // CHECK:STDOUT: %import_ref.2: %CompleteClass.type = import_ref Main//foo, inst+14, loaded [template = constants.%CompleteClass.1] -// CHECK:STDOUT: %import_ref.3: %F.type = import_ref Main//foo, inst+55, loaded [template = constants.%F] +// CHECK:STDOUT: %import_ref.3: %F.type.4 = import_ref Main//foo, inst+55, loaded [template = constants.%F.4] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.7 // CHECK:STDOUT: import Core//prelude @@ -574,11 +716,21 @@ class Class(U:! type) { // CHECK:STDOUT: %Use.decl: %Use.type = fn_decl @Use [template = constants.%Use] {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @CompleteClass { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.4 -// CHECK:STDOUT: .n = imports.%import_ref.5 -// CHECK:STDOUT: .F = imports.%import_ref.6 +// CHECK:STDOUT: generic class @CompleteClass(constants.%T: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %CompleteClass: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic = %CompleteClass (constants.%CompleteClass.2)] +// CHECK:STDOUT: %.1: type = unbound_element_type @CompleteClass.%CompleteClass (%CompleteClass.2), i32 [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: %F.type: type = fn_type @F.1, @CompleteClass(%T) [symbolic = %F.type (constants.%F.type.2)] +// CHECK:STDOUT: %F: @CompleteClass.%F.type (%F.type.2) = struct_value () [symbolic = %F (constants.%F.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.4 +// CHECK:STDOUT: .n = imports.%import_ref.5 +// CHECK:STDOUT: .F = imports.%import_ref.6 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Use() { @@ -587,28 +739,56 @@ class Class(U:! type) { // CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] // CHECK:STDOUT: %.loc11_27.1: type = value_of_initializer %int.make_type_32 [template = i32] // CHECK:STDOUT: %.loc11_27.2: type = converted %int.make_type_32, %.loc11_27.1 [template = i32] -// CHECK:STDOUT: %.loc11_27.3: type = ptr_type i32 [template = constants.%.3] +// CHECK:STDOUT: %.loc11_27.3: type = ptr_type i32 [template = constants.%.4] // CHECK:STDOUT: %.loc11_23: init type = call %CompleteClass.ref(%.loc11_27.3) [template = constants.%CompleteClass.3] // CHECK:STDOUT: %.loc11_28.1: type = value_of_initializer %.loc11_23 [template = constants.%CompleteClass.3] // CHECK:STDOUT: %.loc11_28.2: type = converted %.loc11_23, %.loc11_28.1 [template = constants.%CompleteClass.3] // CHECK:STDOUT: %v.var: ref %CompleteClass.3 = var v // CHECK:STDOUT: %v: ref %CompleteClass.3 = bind_name v, %v.var -// CHECK:STDOUT: %F.ref: %F.type = name_ref F, imports.%import_ref.3 [template = constants.%F] +// CHECK:STDOUT: %F.ref: %F.type.4 = name_ref F, imports.%import_ref.3 [template = constants.%F.4] // CHECK:STDOUT: %.loc11_33: ref %CompleteClass.4 = temporary_storage // CHECK:STDOUT: %F.call: init %CompleteClass.4 = call %F.ref() to %.loc11_33 // CHECK:STDOUT: assign %v.var, // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.1(constants.%T: type) { +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn() -> i32; +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: -// CHECK:STDOUT: fn @F() -> %CompleteClass.4; +// CHECK:STDOUT: fn @F.2() -> %CompleteClass.4; // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%T); +// CHECK:STDOUT: specific @CompleteClass(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%.3); +// CHECK:STDOUT: specific @CompleteClass(@CompleteClass.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(i32); +// CHECK:STDOUT: specific @CompleteClass(constants.%.4) { +// CHECK:STDOUT: %T => constants.%.4 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %CompleteClass => constants.%CompleteClass.3 +// CHECK:STDOUT: %.1 => constants.%.5 +// CHECK:STDOUT: %F.type => constants.%F.type.3 +// CHECK:STDOUT: %F => constants.%F.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @CompleteClass(i32) { +// CHECK:STDOUT: %T => i32 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %CompleteClass => constants.%CompleteClass.4 +// CHECK:STDOUT: %.1 => constants.%.7 +// CHECK:STDOUT: %F.type => constants.%F.type.5 +// CHECK:STDOUT: %F => constants.%F.5 +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- fail_bad_foo.impl.carbon // CHECK:STDOUT: @@ -618,7 +798,7 @@ class Class(U:! type) { // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic] -// CHECK:STDOUT: %Class.2: type = class_type @Class, invalid(%T) [symbolic] +// CHECK:STDOUT: %Class.2: type = class_type @Class, @Class(%T) [symbolic] // CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] // CHECK:STDOUT: %.2: %.type = struct_value () [template] // CHECK:STDOUT: %.3: type = class_type @.1, @.1(%U) [symbolic] @@ -655,7 +835,11 @@ class Class(U:! type) { // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @Class; +// CHECK:STDOUT: generic class @Class(constants.%T: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: class; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic class @.1(file.%U.loc14_13.2: type) { // CHECK:STDOUT: %U: type = bind_symbolic_name U 0 [symbolic = %U (constants.%U)] @@ -672,7 +856,9 @@ class Class(U:! type) { // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%T); +// CHECK:STDOUT: specific @Class(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @.1(constants.%U) { // CHECK:STDOUT: %U => constants.%U diff --git a/toolchain/check/testdata/class/syntactic_merge_literal.carbon b/toolchain/check/testdata/class/syntactic_merge_literal.carbon index c59ebd7346af..55d4b8cf2b32 100644 --- a/toolchain/check/testdata/class/syntactic_merge_literal.carbon +++ b/toolchain/check/testdata/class/syntactic_merge_literal.carbon @@ -12,21 +12,21 @@ // --- int_match.carbon -class C(a: i32) {} -class D(b: C(1_000)); -class D(b: C(1_000)) {} +class C(a:! i32) {} +class D(b:! C(1_000)); +class D(b:! C(1_000)) {} // --- fail_int_mismatch.carbon -class C(a: i32) {} -class D(b: C(1000)); -// CHECK:STDERR: fail_int_mismatch.carbon:[[@LINE+6]]:14: ERROR: Redeclaration syntax differs here. -// CHECK:STDERR: class D(b: C(1_000)) {} -// CHECK:STDERR: ^~~~~ -// CHECK:STDERR: fail_int_mismatch.carbon:[[@LINE-4]]:14: Comparing with previous declaration here. -// CHECK:STDERR: class D(b: C(1000)); -// CHECK:STDERR: ^~~~ -class D(b: C(1_000)) {} +class C(a:! i32) {} +class D(b:! C(1000)); +// CHECK:STDERR: fail_int_mismatch.carbon:[[@LINE+6]]:15: ERROR: Redeclaration syntax differs here. +// CHECK:STDERR: class D(b:! C(1_000)) {} +// CHECK:STDERR: ^~~~~ +// CHECK:STDERR: fail_int_mismatch.carbon:[[@LINE-4]]:15: Comparing with previous declaration here. +// CHECK:STDERR: class D(b:! C(1000)); +// CHECK:STDERR: ^~~~ +class D(b:! C(1_000)) {} // CHECK:STDOUT: --- int_match.carbon // CHECK:STDOUT: @@ -34,15 +34,17 @@ class D(b: C(1_000)) {} // 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: %a: i32 = bind_symbolic_name a 0 [symbolic] // CHECK:STDOUT: %C.type: type = generic_class_type @C [template] // CHECK:STDOUT: %C.1: %C.type = struct_value () [template] -// CHECK:STDOUT: %C.2: type = class_type @C [template] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%a) [symbolic] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: i32 = int_literal 1000 [template] -// CHECK:STDOUT: %C.3: type = class_type @C, invalid(%.3) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(%.3) [template] +// CHECK:STDOUT: %b: %C.3 = bind_symbolic_name b 0 [symbolic] // CHECK:STDOUT: %D.type: type = generic_class_type @D [template] // CHECK:STDOUT: %D.1: %D.type = struct_value () [template] -// CHECK:STDOUT: %D.2: type = class_type @D [template] +// CHECK:STDOUT: %D.2: type = class_type @D, @D(%b) [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -68,44 +70,66 @@ class D(b: C(1_000)) {} // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.decl: %C.type = class_decl @C [template = constants.%C.1] { // CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc2_12.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc2_12.2: type = converted %int.make_type_32, %.loc2_12.1 [template = i32] +// CHECK:STDOUT: %.loc2_13.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc2_13.2: type = converted %int.make_type_32, %.loc2_13.1 [template = i32] // CHECK:STDOUT: %a.loc2_9.1: i32 = param a -// CHECK:STDOUT: %a.loc2_9.2: i32 = bind_name a, %a.loc2_9.1 +// CHECK:STDOUT: %a.loc2_9.2: i32 = bind_symbolic_name a 0, %a.loc2_9.1 [symbolic = @C.%a (constants.%a)] // CHECK:STDOUT: } // CHECK:STDOUT: %D.decl.loc3: %D.type = class_decl @D [template = constants.%D.1] { // CHECK:STDOUT: %C.ref.loc3: %C.type = name_ref C, %C.decl [template = constants.%C.1] -// CHECK:STDOUT: %.loc3_14: i32 = int_literal 1000 [template = constants.%.3] -// CHECK:STDOUT: %.loc3_13: init type = call %C.ref.loc3(%.loc3_14) [template = constants.%C.3] -// CHECK:STDOUT: %.loc3_19.1: type = value_of_initializer %.loc3_13 [template = constants.%C.3] -// CHECK:STDOUT: %.loc3_19.2: type = converted %.loc3_13, %.loc3_19.1 [template = constants.%C.3] +// CHECK:STDOUT: %.loc3_15: i32 = int_literal 1000 [template = constants.%.3] +// CHECK:STDOUT: %.loc3_14: init type = call %C.ref.loc3(%.loc3_15) [template = constants.%C.3] +// CHECK:STDOUT: %.loc3_20.1: type = value_of_initializer %.loc3_14 [template = constants.%C.3] +// CHECK:STDOUT: %.loc3_20.2: type = converted %.loc3_14, %.loc3_20.1 [template = constants.%C.3] // CHECK:STDOUT: %b.loc3_9.1: %C.3 = param b -// CHECK:STDOUT: %b.loc3_9.2: %C.3 = bind_name b, %b.loc3_9.1 +// CHECK:STDOUT: %b.loc3_9.2: %C.3 = bind_symbolic_name b 0, %b.loc3_9.1 [symbolic = @D.%b (constants.%b)] // CHECK:STDOUT: } // CHECK:STDOUT: %D.decl.loc4: %D.type = class_decl @D [template = constants.%D.1] { // CHECK:STDOUT: %C.ref.loc4: %C.type = name_ref C, %C.decl [template = constants.%C.1] -// CHECK:STDOUT: %.loc4_14: i32 = int_literal 1000 [template = constants.%.3] -// CHECK:STDOUT: %.loc4_13: init type = call %C.ref.loc4(%.loc4_14) [template = constants.%C.3] -// CHECK:STDOUT: %.loc4_19.1: type = value_of_initializer %.loc4_13 [template = constants.%C.3] -// CHECK:STDOUT: %.loc4_19.2: type = converted %.loc4_13, %.loc4_19.1 [template = constants.%C.3] +// CHECK:STDOUT: %.loc4_15: i32 = int_literal 1000 [template = constants.%.3] +// CHECK:STDOUT: %.loc4_14: init type = call %C.ref.loc4(%.loc4_15) [template = constants.%C.3] +// CHECK:STDOUT: %.loc4_20.1: type = value_of_initializer %.loc4_14 [template = constants.%C.3] +// CHECK:STDOUT: %.loc4_20.2: type = converted %.loc4_14, %.loc4_20.1 [template = constants.%C.3] // CHECK:STDOUT: %b.loc4_9.1: %C.3 = param b -// CHECK:STDOUT: %b.loc4_9.2: %C.3 = bind_name b, %b.loc4_9.1 +// CHECK:STDOUT: %b.loc4_9.2: %C.3 = bind_symbolic_name b 0, %b.loc4_9.1 [symbolic = constants.%b] // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%C.2 +// CHECK:STDOUT: generic class @C(file.%a.loc2_9.2: i32) { +// CHECK:STDOUT: %a: i32 = bind_symbolic_name a 0 [symbolic = %a (constants.%a)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C.2 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @D { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%D.2 +// CHECK:STDOUT: generic class @D(file.%b.loc3_9.2: %C.3) { +// CHECK:STDOUT: %b: %C.3 = bind_symbolic_name b 0 [symbolic = %b (constants.%b)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%D.2 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%.3); +// CHECK:STDOUT: specific @C(constants.%a) { +// CHECK:STDOUT: %a => constants.%a +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(constants.%.3) { +// CHECK:STDOUT: %a => constants.%.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @D(constants.%b) { +// CHECK:STDOUT: %b => constants.%b +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- fail_int_mismatch.carbon // CHECK:STDOUT: @@ -113,18 +137,20 @@ class D(b: C(1_000)) {} // 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: %a: i32 = bind_symbolic_name a 0 [symbolic] // CHECK:STDOUT: %C.type: type = generic_class_type @C [template] // CHECK:STDOUT: %C.1: %C.type = struct_value () [template] -// CHECK:STDOUT: %C.2: type = class_type @C [template] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%a) [symbolic] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: i32 = int_literal 1000 [template] -// CHECK:STDOUT: %C.3: type = class_type @C, invalid(%.3) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(%.3) [template] +// CHECK:STDOUT: %b: %C.3 = bind_symbolic_name b 0 [symbolic] // CHECK:STDOUT: %D.type: type = generic_class_type @D [template] // CHECK:STDOUT: %D.1: %D.type = struct_value () [template] -// CHECK:STDOUT: %D.2: type = class_type @D [template] +// CHECK:STDOUT: %D.2: type = class_type @D, @D(%b) [symbolic] // CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] // CHECK:STDOUT: %.4: %.type = struct_value () [template] -// CHECK:STDOUT: %.5: type = class_type @.1 [template] +// CHECK:STDOUT: %.5: type = class_type @.1, @.1(%b) [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -150,44 +176,74 @@ class D(b: C(1_000)) {} // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.decl: %C.type = class_decl @C [template = constants.%C.1] { // CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc2_12.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc2_12.2: type = converted %int.make_type_32, %.loc2_12.1 [template = i32] +// CHECK:STDOUT: %.loc2_13.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc2_13.2: type = converted %int.make_type_32, %.loc2_13.1 [template = i32] // CHECK:STDOUT: %a.loc2_9.1: i32 = param a -// CHECK:STDOUT: %a.loc2_9.2: i32 = bind_name a, %a.loc2_9.1 +// CHECK:STDOUT: %a.loc2_9.2: i32 = bind_symbolic_name a 0, %a.loc2_9.1 [symbolic = @C.%a (constants.%a)] // CHECK:STDOUT: } // CHECK:STDOUT: %D.decl: %D.type = class_decl @D [template = constants.%D.1] { // CHECK:STDOUT: %C.ref.loc3: %C.type = name_ref C, %C.decl [template = constants.%C.1] -// CHECK:STDOUT: %.loc3_14: i32 = int_literal 1000 [template = constants.%.3] -// CHECK:STDOUT: %.loc3_13: init type = call %C.ref.loc3(%.loc3_14) [template = constants.%C.3] -// CHECK:STDOUT: %.loc3_18.1: type = value_of_initializer %.loc3_13 [template = constants.%C.3] -// CHECK:STDOUT: %.loc3_18.2: type = converted %.loc3_13, %.loc3_18.1 [template = constants.%C.3] +// CHECK:STDOUT: %.loc3_15: i32 = int_literal 1000 [template = constants.%.3] +// CHECK:STDOUT: %.loc3_14: init type = call %C.ref.loc3(%.loc3_15) [template = constants.%C.3] +// CHECK:STDOUT: %.loc3_19.1: type = value_of_initializer %.loc3_14 [template = constants.%C.3] +// CHECK:STDOUT: %.loc3_19.2: type = converted %.loc3_14, %.loc3_19.1 [template = constants.%C.3] // CHECK:STDOUT: %b.loc3_9.1: %C.3 = param b -// CHECK:STDOUT: %b.loc3_9.2: %C.3 = bind_name b, %b.loc3_9.1 +// CHECK:STDOUT: %b.loc3_9.2: %C.3 = bind_symbolic_name b 0, %b.loc3_9.1 [symbolic = @D.%b (constants.%b)] // CHECK:STDOUT: } // CHECK:STDOUT: %.decl: %.type = class_decl @.1 [template = constants.%.4] { // CHECK:STDOUT: %C.ref.loc10: %C.type = name_ref C, %C.decl [template = constants.%C.1] -// CHECK:STDOUT: %.loc10_14: i32 = int_literal 1000 [template = constants.%.3] -// CHECK:STDOUT: %.loc10_13: init type = call %C.ref.loc10(%.loc10_14) [template = constants.%C.3] -// CHECK:STDOUT: %.loc10_19.1: type = value_of_initializer %.loc10_13 [template = constants.%C.3] -// CHECK:STDOUT: %.loc10_19.2: type = converted %.loc10_13, %.loc10_19.1 [template = constants.%C.3] +// CHECK:STDOUT: %.loc10_15: i32 = int_literal 1000 [template = constants.%.3] +// CHECK:STDOUT: %.loc10_14: init type = call %C.ref.loc10(%.loc10_15) [template = constants.%C.3] +// CHECK:STDOUT: %.loc10_20.1: type = value_of_initializer %.loc10_14 [template = constants.%C.3] +// CHECK:STDOUT: %.loc10_20.2: type = converted %.loc10_14, %.loc10_20.1 [template = constants.%C.3] // CHECK:STDOUT: %b.loc10_9.1: %C.3 = param b -// CHECK:STDOUT: %b.loc10_9.2: %C.3 = bind_name b, %b.loc10_9.1 +// CHECK:STDOUT: %b.loc10_9.2: %C.3 = bind_symbolic_name b 0, %b.loc10_9.1 [symbolic = @.1.%b (constants.%b)] // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%C.2 +// CHECK:STDOUT: generic class @C(file.%a.loc2_9.2: i32) { +// CHECK:STDOUT: %a: i32 = bind_symbolic_name a 0 [symbolic = %a (constants.%a)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C.2 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @D; +// CHECK:STDOUT: generic class @D(file.%b.loc3_9.2: %C.3) { +// CHECK:STDOUT: %b: %C.3 = bind_symbolic_name b 0 [symbolic = %b (constants.%b)] // CHECK:STDOUT: -// CHECK:STDOUT: class @.1 { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%.5 +// CHECK:STDOUT: class; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @.1(file.%b.loc10_9.2: %C.3) { +// CHECK:STDOUT: %b: %C.3 = bind_symbolic_name b 0 [symbolic = %b (constants.%b)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%.5 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%.3); +// CHECK:STDOUT: specific @C(constants.%a) { +// CHECK:STDOUT: %a => constants.%a +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(constants.%.3) { +// CHECK:STDOUT: %a => constants.%.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @D(constants.%b) { +// CHECK:STDOUT: %b => constants.%b +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @.1(constants.%b) { +// CHECK:STDOUT: %b => constants.%b +// CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/builtin/no_prelude/call_from_operator.carbon b/toolchain/check/testdata/function/builtin/no_prelude/call_from_operator.carbon index 53bfbfd84f45..50011b20ffb2 100644 --- a/toolchain/check/testdata/function/builtin/no_prelude/call_from_operator.carbon +++ b/toolchain/check/testdata/function/builtin/no_prelude/call_from_operator.carbon @@ -191,7 +191,11 @@ var arr: [i32; 1 + 2] = (3, 4, 3 + 4); // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.1[@impl.%self.loc7_9.2: i32](@impl.%other.loc7_21.2: i32) -> i32 = "int.sadd"; // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self](%other: %Self) -> %Self; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> %Self; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/impl/lookup/import.carbon b/toolchain/check/testdata/impl/lookup/import.carbon index de2e241014e9..36919722e9b5 100644 --- a/toolchain/check/testdata/impl/lookup/import.carbon +++ b/toolchain/check/testdata/impl/lookup/import.carbon @@ -197,7 +197,10 @@ fn G(c: Impl.C) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.1(); +// CHECK:STDOUT: generic fn @F.1(constants.%Self: %.2) { +// CHECK:STDOUT: +// CHECK:STDOUT: fn(); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F.2(); // CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/lookup/no_prelude/import.carbon b/toolchain/check/testdata/impl/lookup/no_prelude/import.carbon index d4426f6d087d..e9afabf5dff2 100644 --- a/toolchain/check/testdata/impl/lookup/no_prelude/import.carbon +++ b/toolchain/check/testdata/impl/lookup/no_prelude/import.carbon @@ -172,7 +172,10 @@ fn G(c: Impl.C) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.1(); +// CHECK:STDOUT: generic fn @F.1(constants.%Self: %.2) { +// CHECK:STDOUT: +// CHECK:STDOUT: fn(); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F.2(); // CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/no_prelude/import_self.carbon b/toolchain/check/testdata/impl/no_prelude/import_self.carbon index b0ad6b59ea54..081b1639f01d 100644 --- a/toolchain/check/testdata/impl/no_prelude/import_self.carbon +++ b/toolchain/check/testdata/impl/no_prelude/import_self.carbon @@ -170,7 +170,11 @@ fn F(x: (), y: ()) -> () { // CHECK:STDOUT: return %.loc7_53 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self](%other: %Self) -> %Self; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> %Self; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F(%x: %.1, %y: %.1) -> %.1 { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/index/fail_negative_indexing.carbon b/toolchain/check/testdata/index/fail_negative_indexing.carbon index ea26db0649c4..f80850f9b200 100644 --- a/toolchain/check/testdata/index/fail_negative_indexing.carbon +++ b/toolchain/check/testdata/index/fail_negative_indexing.carbon @@ -88,7 +88,11 @@ var b: i32 = a[-10]; // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op[%self: %Self]() -> %Self; +// CHECK:STDOUT: generic fn @Op(constants.%Self: %.8) { +// CHECK:STDOUT: %Self: %.8 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self]() -> %Self; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/interface/no_prelude/generic_import.carbon b/toolchain/check/testdata/interface/no_prelude/generic_import.carbon index f8dfa7d9cc3f..9fd2cdd0f2ea 100644 --- a/toolchain/check/testdata/interface/no_prelude/generic_import.carbon +++ b/toolchain/check/testdata/interface/no_prelude/generic_import.carbon @@ -99,21 +99,26 @@ impl C as AddWith(C) { // CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: %AddWith: %AddWith.type = struct_value () [template] // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic] -// CHECK:STDOUT: %.3: type = interface_type @AddWith, invalid(%T) [symbolic] +// CHECK:STDOUT: %.3: type = interface_type @AddWith, @AddWith(%T) [symbolic] // CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 1 [symbolic] -// CHECK:STDOUT: %.4: type = interface_type @AddWith, invalid(%C) [template] // CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] // CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] -// CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template] -// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [template] -// CHECK:STDOUT: %.5: = interface_witness (%F.1) [template] +// CHECK:STDOUT: %F.type.2: type = fn_type @F.1, @AddWith(%T) [symbolic] +// CHECK:STDOUT: %.4: type = assoc_entity_type @AddWith, %F.type.2 [symbolic] +// CHECK:STDOUT: %.5: %.4 = assoc_entity element0, imports.%import_ref.2 [symbolic] +// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [symbolic] +// CHECK:STDOUT: %.6: type = interface_type @AddWith, @AddWith(%C) [template] +// CHECK:STDOUT: %F.type.3: type = fn_type @F.2 [template] +// CHECK:STDOUT: %F.3: %F.type.3 = struct_value () [template] +// CHECK:STDOUT: %.7: = interface_witness (%F.3) [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %AddWith.type = import_ref Main//a, inst+4, loaded [template = constants.%AddWith] -// CHECK:STDOUT: %import_ref.2 = import_ref Main//a, inst+10, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//a, inst+16, unloaded -// CHECK:STDOUT: %import_ref.4: %F.type.2 = import_ref Main//a, inst+12, loaded [template = constants.%F.2] +// CHECK:STDOUT: %import_ref.2 = import_ref Main//a, inst+12, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//a, inst+10, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref Main//a, inst+16, unloaded +// CHECK:STDOUT: %import_ref.5: %F.type.2 = import_ref Main//a, inst+12, loaded [template = constants.%F.1] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -123,26 +128,38 @@ impl C as AddWith(C) { // CHECK:STDOUT: } // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} -// CHECK:STDOUT: %.loc7_20.1: type = value_of_initializer %.loc7_18 [template = constants.%.4] -// CHECK:STDOUT: %.loc7_20.2: type = converted %.loc7_18, %.loc7_20.1 [template = constants.%.4] +// CHECK:STDOUT: %.loc7_20.1: type = value_of_initializer %.loc7_18 [template = constants.%.6] +// CHECK:STDOUT: %.loc7_20.2: type = converted %.loc7_18, %.loc7_20.1 [template = constants.%.6] // CHECK:STDOUT: impl_decl @impl { // CHECK:STDOUT: %C.ref.loc7_6: type = name_ref C, %C.decl [template = constants.%C] // CHECK:STDOUT: %AddWith.ref: %AddWith.type = name_ref AddWith, imports.%import_ref.1 [template = constants.%AddWith] // CHECK:STDOUT: %C.ref.loc7_19: type = name_ref C, %C.decl [template = constants.%C] -// CHECK:STDOUT: %.loc7_18: init type = call %AddWith.ref(%C.ref.loc7_19) [template = constants.%.4] +// CHECK:STDOUT: %.loc7_18: init type = call %AddWith.ref(%C.ref.loc7_19) [template = constants.%.6] // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: interface @AddWith { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.2 -// CHECK:STDOUT: .F = imports.%import_ref.3 -// CHECK:STDOUT: witness = (imports.%import_ref.4) +// CHECK:STDOUT: generic interface @AddWith(constants.%T: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1: type = interface_type @AddWith, @AddWith(%T) [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %F.type: type = fn_type @F.1, @AddWith(%T) [symbolic = %F.type (constants.%F.type.2)] +// CHECK:STDOUT: %F: @AddWith.%F.type (%F.type.2) = struct_value () [symbolic = %F (constants.%F.2)] +// CHECK:STDOUT: %.2: type = assoc_entity_type @AddWith, @AddWith.%F.type (%F.type.2) [symbolic = %.2 (constants.%.4)] +// CHECK:STDOUT: %.3: @AddWith.%.2 (%.4) = assoc_entity element0, imports.%import_ref.2 [symbolic = %.3 (constants.%.5)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.3 +// CHECK:STDOUT: .F = imports.%import_ref.4 +// CHECK:STDOUT: witness = (imports.%import_ref.5) +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl: %C as %.4 { -// CHECK:STDOUT: %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] {} -// CHECK:STDOUT: %.1: = interface_witness (%F.decl) [template = constants.%.5] +// CHECK:STDOUT: impl @impl: %C as %.6 { +// CHECK:STDOUT: %F.decl: %F.type.3 = fn_decl @F.2 [template = constants.%F.3] {} +// CHECK:STDOUT: %.1: = interface_witness (%F.decl) [template = constants.%.7] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .F = %F.decl @@ -154,14 +171,25 @@ impl C as AddWith(C) { // CHECK:STDOUT: .Self = constants.%C // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.1() { +// CHECK:STDOUT: generic fn @F.1(constants.%T: type, constants.%Self: %.3) { +// CHECK:STDOUT: +// CHECK:STDOUT: fn(); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.2() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.2(); +// CHECK:STDOUT: specific @AddWith(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%T); +// CHECK:STDOUT: specific @AddWith(@AddWith.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%C); +// CHECK:STDOUT: specific @AddWith(constants.%C) { +// CHECK:STDOUT: %T => constants.%C +// CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/import.carbon b/toolchain/check/testdata/interface/no_prelude/import.carbon index 33e82e4e3aca..11bc5f8beb28 100644 --- a/toolchain/check/testdata/interface/no_prelude/import.carbon +++ b/toolchain/check/testdata/interface/no_prelude/import.carbon @@ -281,9 +281,15 @@ var f: ForwardDeclared* = &f_ref.f; // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.1(); +// CHECK:STDOUT: generic fn @F.1(constants.%Self.2: %.3) { // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.2(); +// CHECK:STDOUT: fn(); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.2(constants.%Self.3: %.4) { +// CHECK:STDOUT: +// CHECK:STDOUT: fn(); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/builtin/fail_type_mismatch_once.carbon b/toolchain/check/testdata/operators/builtin/fail_type_mismatch_once.carbon index b4c5d2e3ab9a..cfd9f513c320 100644 --- a/toolchain/check/testdata/operators/builtin/fail_type_mismatch_once.carbon +++ b/toolchain/check/testdata/operators/builtin/fail_type_mismatch_once.carbon @@ -90,5 +90,9 @@ fn Main() -> i32 { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op[%self: %Self](%other: %Self) -> %Self; +// CHECK:STDOUT: generic fn @Op(constants.%Self: %.4) { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> %Self; +// CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/builtin/fail_unimplemented_op.carbon b/toolchain/check/testdata/operators/builtin/fail_unimplemented_op.carbon index df5159403f38..4656fa1abacc 100644 --- a/toolchain/check/testdata/operators/builtin/fail_unimplemented_op.carbon +++ b/toolchain/check/testdata/operators/builtin/fail_unimplemented_op.carbon @@ -83,5 +83,9 @@ fn Main() -> i32 { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op[%self: %Self](%other: %Self) -> %Self; +// CHECK:STDOUT: generic fn @Op(constants.%Self: %.4) { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> %Self; +// CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/add.carbon b/toolchain/check/testdata/operators/overloaded/add.carbon index ab84fb10ed2e..4f672f53accd 100644 --- a/toolchain/check/testdata/operators/overloaded/add.carbon +++ b/toolchain/check/testdata/operators/overloaded/add.carbon @@ -192,14 +192,23 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: return %.loc19_14 to @impl.1.%return.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self.1: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc23_14.3: %.7](@impl.2.%other.loc23_24.2: %C) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.4[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: generic fn @Op.4(constants.%Self.2: %.6) { +// CHECK:STDOUT: %Self: %.6 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.4.%Self (%Self.2) [symbolic = %.2 (constants.%.8)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestOp(%a: %C, %b: %C) -> %return: %C { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/bit_and.carbon b/toolchain/check/testdata/operators/overloaded/bit_and.carbon index 9412cc774225..f24cb300430b 100644 --- a/toolchain/check/testdata/operators/overloaded/bit_and.carbon +++ b/toolchain/check/testdata/operators/overloaded/bit_and.carbon @@ -192,14 +192,23 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: return %.loc19_14 to @impl.1.%return.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self.1: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc23_14.3: %.7](@impl.2.%other.loc23_24.2: %C) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.4[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: generic fn @Op.4(constants.%Self.2: %.6) { +// CHECK:STDOUT: %Self: %.6 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.4.%Self (%Self.2) [symbolic = %.2 (constants.%.8)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestOp(%a: %C, %b: %C) -> %return: %C { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/bit_complement.carbon b/toolchain/check/testdata/operators/overloaded/bit_complement.carbon index df7a9f91a4b5..97449423a9b1 100644 --- a/toolchain/check/testdata/operators/overloaded/bit_complement.carbon +++ b/toolchain/check/testdata/operators/overloaded/bit_complement.carbon @@ -120,7 +120,11 @@ fn TestOp(a: C) -> C { // CHECK:STDOUT: return %.loc19_14 to @impl.%return.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self]() -> %Self; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self]() -> %Self; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestOp(%a: %C) -> %return: %C { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/bit_or.carbon b/toolchain/check/testdata/operators/overloaded/bit_or.carbon index 383fad1100ce..b0272dbe820f 100644 --- a/toolchain/check/testdata/operators/overloaded/bit_or.carbon +++ b/toolchain/check/testdata/operators/overloaded/bit_or.carbon @@ -192,14 +192,23 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: return %.loc19_14 to @impl.1.%return.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self.1: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc23_14.3: %.7](@impl.2.%other.loc23_24.2: %C) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.4[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: generic fn @Op.4(constants.%Self.2: %.6) { +// CHECK:STDOUT: %Self: %.6 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.4.%Self (%Self.2) [symbolic = %.2 (constants.%.8)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestOp(%a: %C, %b: %C) -> %return: %C { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/bit_xor.carbon b/toolchain/check/testdata/operators/overloaded/bit_xor.carbon index ae06be9bc1c6..10a5918591ef 100644 --- a/toolchain/check/testdata/operators/overloaded/bit_xor.carbon +++ b/toolchain/check/testdata/operators/overloaded/bit_xor.carbon @@ -192,14 +192,23 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: return %.loc19_14 to @impl.1.%return.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self.1: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc23_14.3: %.7](@impl.2.%other.loc23_24.2: %C) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.4[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: generic fn @Op.4(constants.%Self.2: %.6) { +// CHECK:STDOUT: %Self: %.6 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.4.%Self (%Self.2) [symbolic = %.2 (constants.%.8)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestOp(%a: %C, %b: %C) -> %return: %C { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/dec.carbon b/toolchain/check/testdata/operators/overloaded/dec.carbon index 3d92dd6848d8..ae6fbe9ccbe8 100644 --- a/toolchain/check/testdata/operators/overloaded/dec.carbon +++ b/toolchain/check/testdata/operators/overloaded/dec.carbon @@ -109,7 +109,12 @@ fn TestOp() { // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.1[addr @impl.%self.loc18_14.3: %.3](); // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[addr %self: %.5](); +// CHECK:STDOUT: generic fn @Op.2(constants.%Self: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.2.%Self (%Self) [symbolic = %.2 (constants.%.5)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.5](); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestOp() { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/div.carbon b/toolchain/check/testdata/operators/overloaded/div.carbon index 41c4adddae85..c121c27c4688 100644 --- a/toolchain/check/testdata/operators/overloaded/div.carbon +++ b/toolchain/check/testdata/operators/overloaded/div.carbon @@ -192,14 +192,23 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: return %.loc19_14 to @impl.1.%return.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self.1: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc23_14.3: %.7](@impl.2.%other.loc23_24.2: %C) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.4[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: generic fn @Op.4(constants.%Self.2: %.6) { +// CHECK:STDOUT: %Self: %.6 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.4.%Self (%Self.2) [symbolic = %.2 (constants.%.8)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestOp(%a: %C, %b: %C) -> %return: %C { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/eq.carbon b/toolchain/check/testdata/operators/overloaded/eq.carbon index 8fca3f1762df..288cfc035172 100644 --- a/toolchain/check/testdata/operators/overloaded/eq.carbon +++ b/toolchain/check/testdata/operators/overloaded/eq.carbon @@ -224,9 +224,17 @@ fn TestLhsBad(a: D, b: C) -> bool { // CHECK:STDOUT: // CHECK:STDOUT: fn @NotEqual.1[@impl.%self.loc8_15.2: %C](@impl.%other.loc8_24.2: %C) -> bool; // CHECK:STDOUT: -// CHECK:STDOUT: fn @Equal.2[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: generic fn @Equal.2(constants.%Self: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: -// CHECK:STDOUT: fn @NotEqual.2[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @NotEqual.2(constants.%Self: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestEqual(%a: %C, %b: %C) -> bool { // CHECK:STDOUT: !entry: @@ -357,7 +365,11 @@ fn TestLhsBad(a: D, b: C) -> bool { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Equal[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: generic fn @Equal(constants.%Self: %.4) { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestNotEqual(%a: %D, %b: %D) -> bool { // CHECK:STDOUT: !entry: @@ -366,7 +378,11 @@ fn TestLhsBad(a: D, b: C) -> bool { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @NotEqual[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: generic fn @NotEqual(constants.%Self: %.4) { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- fail_no_impl_for_args.carbon // CHECK:STDOUT: @@ -521,9 +537,17 @@ fn TestLhsBad(a: D, b: C) -> bool { // CHECK:STDOUT: // CHECK:STDOUT: fn @NotEqual.1[@impl.%self.loc9_15.2: %C](@impl.%other.loc9_24.2: %C) -> bool; // CHECK:STDOUT: -// CHECK:STDOUT: fn @Equal.2[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: generic fn @Equal.2(constants.%Self: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: -// CHECK:STDOUT: fn @NotEqual.2[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @NotEqual.2(constants.%Self: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestRhsBad(%a: %C, %b: %D) -> bool { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/fail_assign_non_ref.carbon b/toolchain/check/testdata/operators/overloaded/fail_assign_non_ref.carbon index 57d2211edf0c..a8634cc25aec 100644 --- a/toolchain/check/testdata/operators/overloaded/fail_assign_non_ref.carbon +++ b/toolchain/check/testdata/operators/overloaded/fail_assign_non_ref.carbon @@ -186,11 +186,21 @@ fn TestAddAssignNonRef(a: C, b: C) { // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.1[addr @impl.1.%self.loc16_14.3: %.3](); // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[addr %self: %.5](); +// CHECK:STDOUT: generic fn @Op.2(constants.%Self.1: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.2.%Self (%Self.1) [symbolic = %.2 (constants.%.5)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.5](); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc19_14.3: %.3](@impl.2.%other.loc19_24.2: %C); // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.4[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: generic fn @Op.4(constants.%Self.2: %.7) { +// CHECK:STDOUT: %Self: %.7 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.4.%Self (%Self.2) [symbolic = %.2 (constants.%.8)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestIncNonRef(%a: %C) { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/fail_no_impl.carbon b/toolchain/check/testdata/operators/overloaded/fail_no_impl.carbon index c72e746f8b40..57bb9d4eae84 100644 --- a/toolchain/check/testdata/operators/overloaded/fail_no_impl.carbon +++ b/toolchain/check/testdata/operators/overloaded/fail_no_impl.carbon @@ -192,7 +192,11 @@ fn TestRef(b: C) { // CHECK:STDOUT: return to %return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.1[%self: %Self.1]() -> %Self.1; +// CHECK:STDOUT: generic fn @Op.1(constants.%Self.1: %.4) { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self.1]() -> %Self.1; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestBinary(%a: %C, %b: %C) -> %return: %C { // CHECK:STDOUT: !entry: @@ -201,7 +205,11 @@ fn TestRef(b: C) { // CHECK:STDOUT: return to %return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self.2](%other: %Self.2) -> %Self.2; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self.2: %.7) { +// CHECK:STDOUT: %Self: %.7 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self.2](%other: %Self.2) -> %Self.2; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestRef(%b: %C) { // CHECK:STDOUT: !entry: @@ -218,7 +226,17 @@ fn TestRef(b: C) { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.3[addr %self: %.11](%other: %Self.3); +// CHECK:STDOUT: generic fn @Op.3(constants.%Self.3: %.10) { +// CHECK:STDOUT: %Self: %.10 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.3)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.3.%Self (%Self.3) [symbolic = %.2 (constants.%.11)] // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.4[addr %self: %.15](); +// CHECK:STDOUT: fn[addr %self: %.11](%other: %Self.3); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @Op.4(constants.%Self.4: %.14) { +// CHECK:STDOUT: %Self: %.14 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.4)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.4.%Self (%Self.4) [symbolic = %.2 (constants.%.15)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.15](); +// CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/fail_no_impl_for_arg.carbon b/toolchain/check/testdata/operators/overloaded/fail_no_impl_for_arg.carbon index 91052af2288d..a2298d865e9e 100644 --- a/toolchain/check/testdata/operators/overloaded/fail_no_impl_for_arg.carbon +++ b/toolchain/check/testdata/operators/overloaded/fail_no_impl_for_arg.carbon @@ -201,11 +201,20 @@ fn TestAssign(b: D) { // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.1[@impl.1.%self.loc17_9.2: %C](@impl.1.%other.loc17_18.2: %C) -> %C; // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self.1: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc20_14.3: %.6](@impl.2.%other.loc20_24.2: %C); // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.4[addr %self: %.7](%other: %Self.2); +// CHECK:STDOUT: generic fn @Op.4(constants.%Self.2: %.5) { +// CHECK:STDOUT: %Self: %.5 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.4.%Self (%Self.2) [symbolic = %.2 (constants.%.7)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.7](%other: %Self.2); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Test(%a: %C, %b: %D) -> %return: %C { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/inc.carbon b/toolchain/check/testdata/operators/overloaded/inc.carbon index 67ff265a7895..1caaf7119230 100644 --- a/toolchain/check/testdata/operators/overloaded/inc.carbon +++ b/toolchain/check/testdata/operators/overloaded/inc.carbon @@ -109,7 +109,12 @@ fn TestOp() { // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.1[addr @impl.%self.loc18_14.3: %.3](); // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[addr %self: %.5](); +// CHECK:STDOUT: generic fn @Op.2(constants.%Self: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.2.%Self (%Self) [symbolic = %.2 (constants.%.5)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.5](); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestOp() { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/left_shift.carbon b/toolchain/check/testdata/operators/overloaded/left_shift.carbon index 41a3a268d2b2..7fcec7dff794 100644 --- a/toolchain/check/testdata/operators/overloaded/left_shift.carbon +++ b/toolchain/check/testdata/operators/overloaded/left_shift.carbon @@ -192,14 +192,23 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: return %.loc19_14 to @impl.1.%return.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self.1: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc23_14.3: %.7](@impl.2.%other.loc23_24.2: %C) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.4[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: generic fn @Op.4(constants.%Self.2: %.6) { +// CHECK:STDOUT: %Self: %.6 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.4.%Self (%Self.2) [symbolic = %.2 (constants.%.8)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestOp(%a: %C, %b: %C) -> %return: %C { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/mod.carbon b/toolchain/check/testdata/operators/overloaded/mod.carbon index 56d611c839f6..b399cbc84435 100644 --- a/toolchain/check/testdata/operators/overloaded/mod.carbon +++ b/toolchain/check/testdata/operators/overloaded/mod.carbon @@ -192,14 +192,23 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: return %.loc19_14 to @impl.1.%return.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self.1: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc23_14.3: %.7](@impl.2.%other.loc23_24.2: %C) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.4[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: generic fn @Op.4(constants.%Self.2: %.6) { +// CHECK:STDOUT: %Self: %.6 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.4.%Self (%Self.2) [symbolic = %.2 (constants.%.8)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestOp(%a: %C, %b: %C) -> %return: %C { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/mul.carbon b/toolchain/check/testdata/operators/overloaded/mul.carbon index 422348232bf5..0cf4d35d18ab 100644 --- a/toolchain/check/testdata/operators/overloaded/mul.carbon +++ b/toolchain/check/testdata/operators/overloaded/mul.carbon @@ -192,14 +192,23 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: return %.loc19_14 to @impl.1.%return.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self.1: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc23_14.3: %.7](@impl.2.%other.loc23_24.2: %C) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.4[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: generic fn @Op.4(constants.%Self.2: %.6) { +// CHECK:STDOUT: %Self: %.6 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.4.%Self (%Self.2) [symbolic = %.2 (constants.%.8)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestOp(%a: %C, %b: %C) -> %return: %C { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/negate.carbon b/toolchain/check/testdata/operators/overloaded/negate.carbon index 3a2e0f8dc5e3..846bf2a1ad18 100644 --- a/toolchain/check/testdata/operators/overloaded/negate.carbon +++ b/toolchain/check/testdata/operators/overloaded/negate.carbon @@ -120,7 +120,11 @@ fn TestOp(a: C) -> C { // CHECK:STDOUT: return %.loc19_14 to @impl.%return.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self]() -> %Self; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self]() -> %Self; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestOp(%a: %C) -> %return: %C { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/ordered.carbon b/toolchain/check/testdata/operators/overloaded/ordered.carbon index c48daa37cc73..af1d4a6ae839 100644 --- a/toolchain/check/testdata/operators/overloaded/ordered.carbon +++ b/toolchain/check/testdata/operators/overloaded/ordered.carbon @@ -299,13 +299,29 @@ fn TestGreaterEqual(a: D, b: D) -> bool { // CHECK:STDOUT: // CHECK:STDOUT: fn @GreaterOrEquivalent.1[@impl.%self.loc10_26.2: %C](@impl.%other.loc10_35.2: %C) -> bool; // CHECK:STDOUT: -// CHECK:STDOUT: fn @Less.2[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: generic fn @Less.2(constants.%Self: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: -// CHECK:STDOUT: fn @LessOrEquivalent.2[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Greater.2[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: generic fn @LessOrEquivalent.2(constants.%Self: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: -// CHECK:STDOUT: fn @GreaterOrEquivalent.2[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @Greater.2(constants.%Self: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @GreaterOrEquivalent.2(constants.%Self: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestLess(%a: %C, %b: %C) -> bool { // CHECK:STDOUT: !entry: @@ -506,7 +522,11 @@ fn TestGreaterEqual(a: D, b: D) -> bool { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Less[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: generic fn @Less(constants.%Self: %.4) { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestLessEqual(%a: %D, %b: %D) -> bool { // CHECK:STDOUT: !entry: @@ -515,7 +535,11 @@ fn TestGreaterEqual(a: D, b: D) -> bool { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @LessOrEquivalent[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: generic fn @LessOrEquivalent(constants.%Self: %.4) { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestGreater(%a: %D, %b: %D) -> bool { // CHECK:STDOUT: !entry: @@ -524,7 +548,11 @@ fn TestGreaterEqual(a: D, b: D) -> bool { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Greater[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: generic fn @Greater(constants.%Self: %.4) { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestGreaterEqual(%a: %D, %b: %D) -> bool { // CHECK:STDOUT: !entry: @@ -533,5 +561,9 @@ fn TestGreaterEqual(a: D, b: D) -> bool { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @GreaterOrEquivalent[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: generic fn @GreaterOrEquivalent(constants.%Self: %.4) { +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self](%other: %Self) -> bool; +// CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/right_shift.carbon b/toolchain/check/testdata/operators/overloaded/right_shift.carbon index 4eb473d1e18c..5a9d0fab1af9 100644 --- a/toolchain/check/testdata/operators/overloaded/right_shift.carbon +++ b/toolchain/check/testdata/operators/overloaded/right_shift.carbon @@ -192,14 +192,23 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: return %.loc19_14 to @impl.1.%return.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self.1: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc23_14.3: %.7](@impl.2.%other.loc23_24.2: %C) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.4[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: generic fn @Op.4(constants.%Self.2: %.6) { +// CHECK:STDOUT: %Self: %.6 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.4.%Self (%Self.2) [symbolic = %.2 (constants.%.8)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestOp(%a: %C, %b: %C) -> %return: %C { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/operators/overloaded/sub.carbon b/toolchain/check/testdata/operators/overloaded/sub.carbon index bf196ee0c051..428224cd4a20 100644 --- a/toolchain/check/testdata/operators/overloaded/sub.carbon +++ b/toolchain/check/testdata/operators/overloaded/sub.carbon @@ -192,14 +192,23 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: return %.loc19_14 to @impl.1.%return.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.2[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: generic fn @Op.2(constants.%Self.1: %.2) { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: %Self.1](%other: %Self.1) -> %Self.1; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Op.3[addr @impl.2.%self.loc23_14.3: %.7](@impl.2.%other.loc23_24.2: %C) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Op.4[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: generic fn @Op.4(constants.%Self.2: %.6) { +// CHECK:STDOUT: %Self: %.6 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %.2: type = ptr_type @Op.4.%Self (%Self.2) [symbolic = %.2 (constants.%.8)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr %self: %.8](%other: %Self.2); +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @TestOp(%a: %C, %b: %C) -> %return: %C { // CHECK:STDOUT: !entry: diff --git a/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon b/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon index 451c3d3b4660..6e62138da2dd 100644 --- a/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon +++ b/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon @@ -83,10 +83,10 @@ export C2(T:! type); // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %C1.1: %C1.type = struct_value () [template] // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic] -// CHECK:STDOUT: %C1.2: type = class_type @C1, invalid(%T) [symbolic] +// CHECK:STDOUT: %C1.2: type = class_type @C1, @C1(%T) [symbolic] // CHECK:STDOUT: %C2.type: type = generic_class_type @C2 [template] // CHECK:STDOUT: %C2.1: %C2.type = struct_value () [template] -// CHECK:STDOUT: %C2.2: type = class_type @C2, invalid(%T) [symbolic] +// CHECK:STDOUT: %C2.2: type = class_type @C2, @C2(%T) [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -106,9 +106,23 @@ export C2(T:! type); // CHECK:STDOUT: %C2: %C2.type = export C2, imports.%import_ref.2 [template = constants.%C2.1] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C1; +// CHECK:STDOUT: generic class @C1(constants.%T: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] // CHECK:STDOUT: -// CHECK:STDOUT: class @C2; +// CHECK:STDOUT: class; +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%T); +// CHECK:STDOUT: generic class @C2(constants.%T: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: class; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C1(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C2(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/struct/import.carbon b/toolchain/check/testdata/struct/import.carbon index 19ed5422e84e..86ea05b7f85d 100644 --- a/toolchain/check/testdata/struct/import.carbon +++ b/toolchain/check/testdata/struct/import.carbon @@ -225,12 +225,12 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %.10: type = struct_type {} [template] // CHECK:STDOUT: %.11: type = struct_type {.a: i32, .b: i32} [template] // CHECK:STDOUT: %S: %.11 = bind_symbolic_name S 0 [symbolic] -// CHECK:STDOUT: %C.2: type = class_type @C, invalid(%S) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%S) [symbolic] // CHECK:STDOUT: %.12: i32 = int_literal 1 [template] // CHECK:STDOUT: %.13: i32 = int_literal 2 [template] // CHECK:STDOUT: %.14: type = ptr_type %.11 [template] // CHECK:STDOUT: %struct: %.11 = struct_value (%.12, %.13) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, invalid(%struct) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(%struct) [template] // CHECK:STDOUT: %.15: type = ptr_type %.10 [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] @@ -303,9 +303,15 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %c: ref %C.3 = bind_name c, %c.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.6 +// CHECK:STDOUT: generic class @C(constants.%S: %.11) { +// CHECK:STDOUT: %S: %.11 = bind_symbolic_name S 0 [symbolic = %S (constants.%S)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.6 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; @@ -350,9 +356,15 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%S); +// CHECK:STDOUT: specific @C(constants.%S) { +// CHECK:STDOUT: %S => constants.%S +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%struct); +// CHECK:STDOUT: specific @C(constants.%struct) { +// CHECK:STDOUT: %S => constants.%struct +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- fail_bad_type.impl.carbon // CHECK:STDOUT: @@ -363,13 +375,13 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = struct_type {.a: i32, .b: i32} [template] // CHECK:STDOUT: %S: %.3 = bind_symbolic_name S 0 [symbolic] -// CHECK:STDOUT: %C.2: type = class_type @C, invalid(%S) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%S) [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 1 [template] // CHECK:STDOUT: %.5: i32 = int_literal 2 [template] // CHECK:STDOUT: %.6: type = struct_type {.c: i32, .d: i32} [template] // CHECK:STDOUT: %.7: type = ptr_type %.3 [template] // CHECK:STDOUT: %struct: %.3 = struct_value (%.4, %.5) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, invalid(%struct) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(%struct) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: %.8: type = ptr_type %.2 [template] @@ -415,9 +427,15 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %c_bad: ref = bind_name c_bad, %c_bad.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: generic class @C(constants.%S: %.3) { +// CHECK:STDOUT: %S: %.3 = bind_symbolic_name S 0 [symbolic = %S (constants.%S)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() -> %C.3; @@ -431,9 +449,15 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%S); +// CHECK:STDOUT: specific @C(constants.%S) { +// CHECK:STDOUT: %S => constants.%S +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%struct); +// CHECK:STDOUT: specific @C(constants.%struct) { +// CHECK:STDOUT: %S => constants.%struct +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- fail_bad_value.impl.carbon // CHECK:STDOUT: @@ -444,17 +468,17 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = struct_type {.a: i32, .b: i32} [template] // CHECK:STDOUT: %S: %.3 = bind_symbolic_name S 0 [symbolic] -// CHECK:STDOUT: %C.2: type = class_type @C, invalid(%S) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%S) [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 3 [template] // CHECK:STDOUT: %.5: i32 = int_literal 4 [template] // CHECK:STDOUT: %.6: type = ptr_type %.3 [template] // CHECK:STDOUT: %struct.1: %.3 = struct_value (%.4, %.5) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, invalid(%struct.1) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(%struct.1) [template] // CHECK:STDOUT: %.7: type = ptr_type %.2 [template] // CHECK:STDOUT: %.8: i32 = int_literal 2 [template] // CHECK:STDOUT: %.9: i32 = int_literal 1 [template] // CHECK:STDOUT: %struct.2: %.3 = struct_value (%.9, %.8) [template] -// CHECK:STDOUT: %C.4: type = class_type @C, invalid(%struct.2) [template] +// CHECK:STDOUT: %C.4: type = class_type @C, @C(%struct.2) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: } @@ -501,9 +525,15 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %c_bad: ref %C.3 = bind_name c_bad, %c_bad.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: generic class @C(constants.%S: %.3) { +// CHECK:STDOUT: %S: %.3 = bind_symbolic_name S 0 [symbolic = %S (constants.%S)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() -> %C.4; @@ -517,9 +547,19 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%S); +// CHECK:STDOUT: specific @C(constants.%S) { +// CHECK:STDOUT: %S => constants.%S +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%struct.1); +// CHECK:STDOUT: specific @C(constants.%struct.1) { +// CHECK:STDOUT: %S => constants.%struct.1 // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%struct.2); +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(constants.%struct.2) { +// CHECK:STDOUT: %S => constants.%struct.2 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/tuples/import.carbon b/toolchain/check/testdata/tuples/import.carbon index 73190a46f35f..ce160f8c773b 100644 --- a/toolchain/check/testdata/tuples/import.carbon +++ b/toolchain/check/testdata/tuples/import.carbon @@ -249,11 +249,11 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %C.1: %C.type = struct_value () [template] // CHECK:STDOUT: %.14: type = struct_type {} [template] // CHECK:STDOUT: %X: %.8 = bind_symbolic_name X 0 [symbolic] -// CHECK:STDOUT: %C.2: type = class_type @C, invalid(%X) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%X) [symbolic] // CHECK:STDOUT: %.15: i32 = int_literal 1 [template] // CHECK:STDOUT: %.16: i32 = int_literal 2 [template] // CHECK:STDOUT: %tuple: %.8 = tuple_value (%.15, %.16) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, invalid(%tuple) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(%tuple) [template] // CHECK:STDOUT: %.17: type = ptr_type %.14 [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] @@ -334,9 +334,15 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %c: ref %C.3 = bind_name c, %c.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.6 +// CHECK:STDOUT: generic class @C(constants.%X: %.8) { +// CHECK:STDOUT: %X: %.8 = bind_symbolic_name X 0 [symbolic = %X (constants.%X)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.6 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; @@ -389,9 +395,15 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%X); +// CHECK:STDOUT: specific @C(constants.%X) { +// CHECK:STDOUT: %X => constants.%X +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%tuple); +// CHECK:STDOUT: specific @C(constants.%tuple) { +// CHECK:STDOUT: %X => constants.%tuple +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- fail_bad_type.impl.carbon // CHECK:STDOUT: @@ -402,14 +414,14 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = tuple_type (i32, i32) [template] // CHECK:STDOUT: %X: %.3 = bind_symbolic_name X 0 [symbolic] -// CHECK:STDOUT: %C.2: type = class_type @C, invalid(%X) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%X) [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 1 [template] // CHECK:STDOUT: %.5: i32 = int_literal 2 [template] // CHECK:STDOUT: %.6: i32 = int_literal 3 [template] // CHECK:STDOUT: %.7: type = tuple_type (i32, i32, i32) [template] // CHECK:STDOUT: %.8: type = ptr_type %.3 [template] // CHECK:STDOUT: %tuple: %.3 = tuple_value (%.4, %.5) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, invalid(%tuple) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(%tuple) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: %.9: type = ptr_type %.2 [template] @@ -456,9 +468,15 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %c_bad: ref = bind_name c_bad, %c_bad.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: generic class @C(constants.%X: %.3) { +// CHECK:STDOUT: %X: %.3 = bind_symbolic_name X 0 [symbolic = %X (constants.%X)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() -> %C.3; @@ -472,9 +490,15 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%X); +// CHECK:STDOUT: specific @C(constants.%X) { +// CHECK:STDOUT: %X => constants.%X +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%tuple); +// CHECK:STDOUT: specific @C(constants.%tuple) { +// CHECK:STDOUT: %X => constants.%tuple +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- fail_bad_value.impl.carbon // CHECK:STDOUT: @@ -485,17 +509,17 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = tuple_type (i32, i32) [template] // CHECK:STDOUT: %X: %.3 = bind_symbolic_name X 0 [symbolic] -// CHECK:STDOUT: %C.2: type = class_type @C, invalid(%X) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%X) [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 3 [template] // CHECK:STDOUT: %.5: i32 = int_literal 4 [template] // CHECK:STDOUT: %.6: type = ptr_type %.3 [template] // CHECK:STDOUT: %tuple.1: %.3 = tuple_value (%.4, %.5) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, invalid(%tuple.1) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(%tuple.1) [template] // CHECK:STDOUT: %.7: type = ptr_type %.2 [template] // CHECK:STDOUT: %.8: i32 = int_literal 2 [template] // CHECK:STDOUT: %.9: i32 = int_literal 1 [template] // CHECK:STDOUT: %tuple.2: %.3 = tuple_value (%.9, %.8) [template] -// CHECK:STDOUT: %C.4: type = class_type @C, invalid(%tuple.2) [template] +// CHECK:STDOUT: %C.4: type = class_type @C, @C(%tuple.2) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: } @@ -542,9 +566,15 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %c_bad: ref %C.3 = bind_name c_bad, %c_bad.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: generic class @C(constants.%X: %.3) { +// CHECK:STDOUT: %X: %.3 = bind_symbolic_name X 0 [symbolic = %X (constants.%X)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() -> %C.4; @@ -558,9 +588,19 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%X); +// CHECK:STDOUT: specific @C(constants.%X) { +// CHECK:STDOUT: %X => constants.%X +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%tuple.1); +// CHECK:STDOUT: specific @C(constants.%tuple.1) { +// CHECK:STDOUT: %X => constants.%tuple.1 // CHECK:STDOUT: -// CHECK:STDOUT: specific invalid(constants.%tuple.2); +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(constants.%tuple.2) { +// CHECK:STDOUT: %X => constants.%tuple.2 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/sem_ir/generic.cpp b/toolchain/sem_ir/generic.cpp index b04cea6d8cba..5cc71765a793 100644 --- a/toolchain/sem_ir/generic.cpp +++ b/toolchain/sem_ir/generic.cpp @@ -32,6 +32,7 @@ class SpecificStore::KeyContext : public TranslatingKeyContext { auto SpecificStore::GetOrAdd(GenericId generic_id, InstBlockId args_id) -> SpecificId { + CARBON_CHECK(generic_id.is_valid()); return lookup_table_ .Insert( KeyContext::Key{.generic_id = generic_id, .args_id = args_id},