From fbc5994750f07ceaf36c0065b1697933e32ee55e Mon Sep 17 00:00:00 2001 From: Geoff Romer Date: Mon, 19 May 2025 15:50:16 -0700 Subject: [PATCH] Support importing `var` parameters (#5400) This restructures the import and merge logic to support parameter patterns in a more scalable way. --------- Co-authored-by: Richard Smith --- toolchain/check/import_ref.cpp | 558 ++++++++---------- toolchain/check/merge.cpp | 160 ++--- .../testdata/builtins/float/make_type.carbon | 2 +- .../class/generic/base_is_generic.carbon | 2 +- .../testdata/class/generic/import.carbon | 2 +- toolchain/check/testdata/class/import.carbon | 4 +- .../check/testdata/class/import_base.carbon | 2 +- .../no_prelude/call_from_operator.carbon | 2 +- .../function/declaration/import.carbon | 2 +- .../testdata/impl/no_prelude/compound.carbon | 4 +- .../impl/no_prelude/import_compound.carbon | 4 +- .../min_prelude/fail_member_lookup.carbon | 2 +- .../testdata/let/fail_missing_value.carbon | 2 +- .../overloaded/no_prelude/index.carbon | 4 +- .../import_convert_function.carbon | 4 +- toolchain/check/testdata/struct/import.carbon | 10 +- toolchain/check/testdata/tuple/import.carbon | 10 +- .../var/min_prelude/var_pattern.carbon | 259 ++++++++ toolchain/sem_ir/function.h | 4 +- toolchain/sem_ir/inst.h | 6 +- 20 files changed, 623 insertions(+), 420 deletions(-) diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 89b229040d7a..7bc30d809359 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -401,9 +401,14 @@ class ImportContext { // - Fill in any remaining information to complete the import of the // instruction. For example, when importing a class declaration, build // the class scope and information about the definition. -// - Return ResolveAs/ResolveAsConstant to finish the resolution process. -// This will cause the Resolve loop to set a constant value if we didn't -// retry at the end of the second phase. +// - Return Done() to finish the resolution process. This will cause the +// Resolve loop to set a constant value if we didn't retry at the end of +// the second phase. +// +// In the common case where the second phase cannot add new work (because the +// inst doesn't represent a declaration of an entity that can be forward +// declared), the second and third phases are usually expressed as a call to +// ResolveAsDeduplicated or ResolveAsUnique. // // 3. If resolve didn't return Retry(), pop the work. Otherwise, it needs to // remain, and may no longer be at the top of the stack; update the state of @@ -516,6 +521,9 @@ class ImportRefResolver : public ImportContext { // Returns the ConstantId for an InstId. Adds unresolved constants to // work_stack_. auto GetLocalConstantValueOrPush(SemIR::InstId inst_id) -> SemIR::ConstantId { + if (!inst_id.has_value()) { + return SemIR::ConstantId::None; + } auto const_id = local_constant_values_for_import_insts().GetAttached(inst_id); if (!const_id.has_value()) { @@ -654,7 +662,7 @@ static auto SetConstantValue(Context& context, SemIR::InstId inst_id, // Adds an imported instruction without setting its constant value. The // instruction should later be updated by either `SetConstantValue` or -// `ReplaceImportedInstAndSetConstantValue`. +// `ReplacePlaceholderImportedInst`. template static auto AddPlaceholderImportedInst(ImportContext& context, SemIR::InstId import_inst_id, InstT inst) @@ -662,33 +670,13 @@ static auto AddPlaceholderImportedInst(ImportContext& context, auto inst_id = context.local_insts().AddInNoBlock(MakeImportedLocIdAndInst( context.local_context(), AddImportIRInst(context, import_inst_id), inst)); CARBON_VLOG_TO(context.local_context().vlog_stream(), - "AddImportedInst: {0}\n", static_cast(inst)); + "AddPlaceholderImportedInst: {0}\n", inst); // Track the instruction in the imports block so that it's included in // formatted SemIR if it's referenced. context.local_context().import_ref_ids().push_back(inst_id); return inst_id; } -// Adds an imported instruction. The constant value of the instruction will be -// computed. -// -// Normally `AddImportedConstant` should be used to create the result of -// resolving a constant, for example by calling `ResolveAs*`. However, we -// sometimes need to create a new instruction, not just obtain a constant value, -// such as when importing a declaration or a pattern. In that case, this -// function should be used to create it. -// -// Do not use `AddInst*`, as it will add symbolic constants to the eval block of -// whatever generic the import happens within. -template -static auto AddImportedInst(ImportContext& context, - SemIR::InstId import_inst_id, InstT inst) - -> SemIR::InstId { - auto inst_id = AddPlaceholderImportedInst(context, import_inst_id, inst); - SetConstantValue(context.local_context(), inst_id, inst); - return inst_id; -} - // Replace an imported instruction that was added by // `AddPlaceholderImportedInst` with a new instruction. Computes, sets, and // returns the new constant value. @@ -745,35 +733,6 @@ static auto GetLocalConstantId(ImportRefResolver& resolver, resolver.import_types().GetConstantId(type_id)); } -// Returns the ConstantId for an InstId that is required to have already been -// imported. -static auto GetLocalConstantIdChecked(ImportContext& context, - SemIR::InstId inst_id) - -> SemIR::ConstantId { - auto result_id = - context.local_constant_values_for_import_insts().GetAttached(inst_id); - CARBON_CHECK(result_id.has_value()); - return result_id; -} - -// Returns the ConstantId for a ConstantId that is required to have already been -// imported. -static auto GetLocalConstantIdChecked(ImportContext& context, - SemIR::ConstantId const_id) - -> SemIR::ConstantId { - return GetLocalConstantIdChecked( - context, GetInstWithConstantValue(context.import_ir(), const_id)); -} - -// Returns the ConstantId for a TypeId that is required to have already been -// imported. -static auto GetLocalConstantIdChecked(ImportContext& context, - SemIR::TypeId type_id) - -> SemIR::ConstantId { - return GetLocalConstantIdChecked( - context, context.import_types().GetConstantId(type_id)); -} - // Translates a NameId from the import IR to a local NameId. static auto GetLocalNameId(ImportContext& context, SemIR::NameId import_name_id) -> SemIR::NameId { @@ -1039,164 +998,6 @@ static auto GetLocalSpecificInterface( } } -// Adds unresolved constants for each parameter's type to the resolver's work -// stack. -static auto LoadLocalPatternConstantIds(ImportRefResolver& resolver, - SemIR::InstBlockId param_patterns_id) - -> void { - if (!param_patterns_id.has_value() || - param_patterns_id == SemIR::InstBlockId::Empty) { - return; - } - - const auto& param_patterns = - resolver.import_inst_blocks().Get(param_patterns_id); - for (auto pattern_id : param_patterns) { - auto pattern_inst = resolver.import_insts().GetWithAttachedType(pattern_id); - GetLocalConstantId(resolver, pattern_inst.type_id()); - if (auto addr = pattern_inst.TryAs()) { - pattern_id = addr->inner_id; - pattern_inst = resolver.import_insts().GetWithAttachedType(pattern_id); - GetLocalConstantId(resolver, pattern_inst.type_id()); - } - // If the parameter is a symbolic binding, build the - // SymbolicBindingPattern constant. - if (pattern_inst.Is()) { - GetLocalConstantId(resolver, pattern_id); - } - } -} - -// Returns a version of param_patterns_id localized to the current IR. -// -// Must only be called after a call to -// LoadLocalPatternConstantIds(param_patterns_id) has completed without adding -// any new work to work_stack_. -// -// TODO: This is inconsistent with the rest of this class, which expects -// the relevant constants to be explicitly passed in. That makes it -// easier to statically detect when an input isn't loaded, but makes it -// harder to support importing more complex inst structures. We should -// take a holistic look at how to balance those concerns. For example, -// could the same function be used to load the constants and use them, with -// a parameter to select between the two? -// -// `self_param_id` is an optional out parameter, populated with the InstId in -// the resulting parameter patterns that represents the Self parameter. -static auto GetLocalParamPatternsId(ImportContext& context, - SemIR::InstBlockId param_patterns_id, - SemIR::InstId* self_param_id = nullptr) - -> SemIR::InstBlockId { - CARBON_CHECK(!self_param_id || !self_param_id->has_value()); - if (!param_patterns_id.has_value() || - param_patterns_id == SemIR::InstBlockId::Empty) { - return param_patterns_id; - } - const auto& param_patterns = - context.import_inst_blocks().Get(param_patterns_id); - llvm::SmallVector new_patterns; - for (auto inst_id : param_patterns) { - // Figure out the pattern structure. This echoes - // Function::GetParamPatternInfoFromPatternId. - auto inst = context.import_insts().GetWithAttachedType(inst_id); - - auto addr_pattern_id = inst_id; - auto addr_inst = inst.TryAs(); - if (addr_inst) { - inst_id = addr_inst->inner_id; - inst = context.import_insts().GetWithAttachedType(inst_id); - } - - auto param_pattern_id = inst_id; - auto param_pattern = inst.TryAs(); - if (param_pattern) { - inst_id = param_pattern->subpattern_id; - inst = context.import_insts().GetWithAttachedType(inst_id); - } - - auto binding_id = inst_id; - auto binding = inst.As(); - - // Rebuild the pattern. - auto entity_name = - context.import_entity_names().Get(binding.entity_name_id); - auto name_id = GetLocalNameId(context, entity_name.name_id); - auto type_id = context.local_context().types().GetTypeIdForTypeConstantId( - GetLocalConstantIdChecked(context, binding.type_id)); - - auto new_param_id = SemIR::InstId::None; - switch (binding.kind) { - case SemIR::BindingPattern::Kind: { - auto entity_name_id = context.local_entity_names().Add( - {.name_id = name_id, .parent_scope_id = SemIR::NameScopeId::None}); - new_param_id = AddImportedInst( - context, binding_id, - {.type_id = type_id, .entity_name_id = entity_name_id}); - break; - } - case SemIR::SymbolicBindingPattern::Kind: { - // We already imported a constant value for this symbolic binding. - // We can reuse most of it, but update the value to point to our - // specific parameter, and preserve the constant value. - auto bind_const_id = GetLocalConstantIdChecked(context, binding_id); - auto new_binding_inst = - context.local_insts().GetAs( - context.local_constant_values().GetInstId(bind_const_id)); - new_param_id = AddImportedInst(context, binding_id, new_binding_inst); - break; - } - default: { - CARBON_FATAL("Unexpected kind: ", binding.kind); - } - } - if (param_pattern) { - new_param_id = AddImportedInst( - context, param_pattern_id, - {.type_id = type_id, - .subpattern_id = new_param_id, - .index = param_pattern->index}); - } - if (addr_inst) { - type_id = context.local_context().types().GetTypeIdForTypeConstantId( - GetLocalConstantIdChecked(context, addr_inst->type_id)); - new_param_id = AddImportedInst( - context, addr_pattern_id, - {.type_id = type_id, .inner_id = new_param_id}); - } - if (self_param_id && - context.import_entity_names().Get(binding.entity_name_id).name_id == - SemIR::NameId::SelfValue) { - *self_param_id = new_param_id; - } - new_patterns.push_back(new_param_id); - } - return context.local_inst_blocks().Add(new_patterns); -} - -// Returns a version of import_return_slot_pattern_id localized to the current -// IR. -static auto GetLocalReturnSlotPatternId( - ImportContext& context, SemIR::InstId import_return_slot_pattern_id, - SemIR::ConstantId return_type_const_id) -> SemIR::InstId { - if (!import_return_slot_pattern_id.has_value()) { - return SemIR::InstId::None; - } - - auto param_pattern = context.import_insts().GetAs( - import_return_slot_pattern_id); - auto type_id = context.local_context().types().GetTypeIdForTypeConstantId( - return_type_const_id); - - auto new_return_slot_pattern_id = AddImportedInst( - context, param_pattern.subpattern_id, - {.type_id = type_id, .type_inst_id = SemIR::TypeInstId::None}); - return AddImportedInst( - context, import_return_slot_pattern_id, - {.type_id = type_id, - .subpattern_id = new_return_slot_pattern_id, - .index = param_pattern.index}); -} - // Translates a NameScopeId from the import IR to a local NameScopeId. Adds // unresolved constants to the resolver's work stack. static auto GetLocalNameScopeId(ImportRefResolver& resolver, @@ -1395,26 +1196,55 @@ static auto RetryOrDone(ImportRefResolver& resolver, SemIR::ConstantId const_id) return ResolveResult::Done(const_id); } -// Produces a resolve result for the given instruction that describes a constant -// value. This should only be used for instructions that describe constants, and -// not for instructions that represent declarations. For a declaration, we need -// an associated location, so AddImportedInst should be used instead. Requires -// that there is no new work. -static auto ResolveAsUntyped(ImportContext& context, SemIR::Inst inst) +// Adds `inst` to the local context as a deduplicated constant and returns a +// successful `ResolveResult`. Requires that there is no new work. +// +// This implements phases 2 and 3 of resolving the inst (as described above) for +// the common case where those phases are combined. Cases where that isn't +// applicable should instead use `AddPlaceholderImportedInst` and +// `ReplacePlaceholderImportedInst`. +// +// This should not be used for instructions that represent declarations, or +// other instructions with `constant_kind == InstConstantKind::Unique`, because +// they should not be deduplicated. +template +static auto ResolveAsDeduplicated(ImportRefResolver& resolver, InstT inst) -> ResolveResult { + static_assert(InstT::Kind.constant_kind() != SemIR::InstConstantKind::Unique, + "Use ResolveAsUnique"); + CARBON_CHECK(!resolver.HasNewWork()); // AddImportedConstant produces an unattached constant, so its type must // be unattached as well. - inst.SetType( - context.local_context().types().GetUnattachedType(inst.type_id())); - auto result = AddImportedConstant(context.local_context(), inst); - CARBON_CHECK(result.is_constant(), "{0} is not constant", inst); - return ResolveResult::Done(result); + inst.type_id = + resolver.local_context().types().GetUnattachedType(inst.type_id); + auto const_id = AddImportedConstant(resolver.local_context(), inst); + CARBON_CHECK(const_id.is_constant(), "{0} is not constant", inst); + return ResolveResult::Done(const_id); } -// Same as ResolveAsUntyped, but with an explicit type for convenience. +// Adds `inst` to the local context as a unique constant and returns a +// successful `ResolveResult`. `import_inst_id` is the corresponding inst ID in +// the local context. Requires that there is no new work. +// +// This implements phases 2 and 3 of resolving the inst (as described above) for +// the common case where those phases are combined. Cases where that isn't +// applicable should instead use `AddPlaceholderImportedInst` and +// `ReplacePlaceholderImportedInst`. +// +// This should only be used for instructions that represent declarations, or +// other instructions with `constant_kind == InstConstantKind::Unique`, because +// it does not perform deduplication. template -static auto ResolveAs(ImportContext& context, InstT inst) -> ResolveResult { - return ResolveAsUntyped(context, inst); +static auto ResolveAsUnique(ImportRefResolver& resolver, + SemIR::InstId import_inst_id, InstT inst) + -> ResolveResult { + static_assert(InstT::Kind.constant_kind() == SemIR::InstConstantKind::Unique, + "Use ResolveAsDeduplicated"); + CARBON_CHECK(!resolver.HasNewWork()); + auto inst_id = AddPlaceholderImportedInst(resolver, import_inst_id, inst); + auto const_id = SetConstantValue(resolver.local_context(), inst_id, inst); + CARBON_CHECK(const_id.is_constant(), "{0} is not constant", inst); + return ResolveResult::Done(const_id, inst_id); } static auto TryResolveTypedInst(ImportRefResolver& resolver, @@ -1432,10 +1262,43 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, inst.adapted_type_inst_id, adapted_type_const_id)); // Create a corresponding instruction to represent the declaration. - auto inst_id = AddImportedInst( + return ResolveAsUnique( resolver, import_inst_id, {.adapted_type_inst_id = adapted_type_inst_id}); - return ResolveResult::Done(resolver.local_constant_values().Get(inst_id), - inst_id); +} + +static auto TryResolveTypedInst(ImportRefResolver& resolver, + SemIR::AddrPattern inst, + SemIR::InstId import_inst_id) -> ResolveResult { + auto type_const_id = GetLocalConstantId(resolver, inst.type_id); + auto inner_id = GetLocalConstantInstId(resolver, inst.inner_id); + if (resolver.HasNewWork()) { + return ResolveResult::Retry(); + } + + return ResolveAsUnique( + resolver, import_inst_id, + {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId( + type_const_id), + .inner_id = inner_id}); +} + +template + requires SemIR::Internal::HasInstCategory +static auto TryResolveTypedInst(ImportRefResolver& resolver, ParamPatternT inst, + SemIR::InstId import_inst_id) -> ResolveResult { + auto type_const_id = GetLocalConstantId(resolver, inst.type_id); + auto subpattern_id = GetLocalConstantInstId(resolver, inst.subpattern_id); + if (resolver.HasNewWork()) { + return ResolveResult::Retry(); + } + + return ResolveAsUnique( + resolver, import_inst_id, + {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId( + type_const_id), + .subpattern_id = subpattern_id, + .index = inst.index}); } static auto TryResolveTypedInst(ImportRefResolver& resolver, @@ -1448,7 +1311,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = SemIR::TypeType::TypeId, .bound_id = bound_id, .element_type_inst_id = element_type_inst_id}); @@ -1541,7 +1404,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, // Add a lazy reference to the target declaration. auto decl_id = AddImportRef(resolver, inst.decl_id); - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId( type_const_id), @@ -1562,7 +1425,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, auto specific_interface = GetLocalSpecificInterface(resolver, inst.GetSpecificInterface(), data); - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = SemIR::TypeType::TypeId, .interface_id = specific_interface.interface_id, .interface_specific_id = specific_interface.specific_id}); @@ -1584,14 +1447,12 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, inst.base_type_inst_id, base_type_const_id)); // Create a corresponding instruction to represent the declaration. - auto inst_id = AddImportedInst( + return ResolveAsUnique( resolver, import_inst_id, {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId( type_const_id), .base_type_inst_id = base_type_inst_id, .index = inst.index}); - return ResolveResult::Done(resolver.local_constant_values().Get(inst_id), - inst_id); } static auto TryResolveTypedInst(ImportRefResolver& resolver, SemIR::Vtable inst) @@ -1605,7 +1466,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, SemIR::Vtable inst) auto virtual_functions_id = GetLocalCanonicalInstBlockId( resolver, inst.virtual_functions_id, virtual_functions); - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId( type_const_id), @@ -1628,12 +1489,10 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, const auto& import_entity_name = resolver.import_entity_names().Get(inst.entity_name_id); auto name_id = GetLocalNameId(resolver, import_entity_name.name_id); - // TODO: Use the same `EntityName` for the `SymbolicBindingPattern` and the - // `BindSymbolicName`. auto entity_name_id = resolver.local_entity_names().AddSymbolicBindingName( name_id, SemIR::NameScopeId::None, import_entity_name.bind_index(), import_entity_name.is_template); - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId(type_id), @@ -1641,10 +1500,13 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, .value_id = SemIR::InstId::None}); } +template + requires SemIR::Internal::HasInstCategory static auto TryResolveTypedInst(ImportRefResolver& resolver, - SemIR::SymbolicBindingPattern inst) - -> ResolveResult { - auto type_id = GetLocalConstantId(resolver, inst.type_id); + BindingPatternT inst, + SemIR::InstId import_inst_id) -> ResolveResult { + auto type_const_id = GetLocalConstantId(resolver, inst.type_id); if (resolver.HasNewWork()) { return ResolveResult::Retry(); } @@ -1652,15 +1514,15 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, const auto& import_entity_name = resolver.import_entity_names().Get(inst.entity_name_id); auto name_id = GetLocalNameId(resolver, import_entity_name.name_id); - // TODO: Use the same `EntityName` for the `SymbolicBindingPattern` and the - // `BindSymbolicName`. - auto entity_name_id = resolver.local_entity_names().AddSymbolicBindingName( - name_id, SemIR::NameScopeId::None, import_entity_name.bind_index(), - import_entity_name.is_template); - return ResolveAs( - resolver, - {.type_id = - resolver.local_context().types().GetTypeIdForTypeConstantId(type_id), + auto entity_name_id = resolver.local_entity_names().Add( + {.name_id = name_id, + .parent_scope_id = SemIR::NameScopeId::None, + .bind_index_value = import_entity_name.bind_index().index, + .is_template = import_entity_name.is_template}); + return ResolveAsUnique( + resolver, import_inst_id, + {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId( + type_const_id), .entity_name_id = entity_name_id}); } @@ -1676,7 +1538,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = GetSingletonType(resolver.local_context(), SemIR::BoundMethodType::TypeInstId), @@ -1694,7 +1556,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, SemIR::Call inst) return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId(type_id), @@ -1815,9 +1677,10 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, // Load constants for the definition. auto parent_scope_id = GetLocalNameScopeId(resolver, import_class.parent_scope_id); - LoadLocalPatternConstantIds(resolver, - import_class.implicit_param_patterns_id); - LoadLocalPatternConstantIds(resolver, import_class.param_patterns_id); + auto implicit_param_patterns = GetLocalInstBlockContents( + resolver, import_class.implicit_param_patterns_id); + auto param_patterns = + GetLocalInstBlockContents(resolver, import_class.param_patterns_id); auto generic_data = GetLocalGenericData(resolver, import_class.generic_id); auto self_const_id = GetLocalConstantId(resolver, import_class.self_type_id); auto complete_type_witness_const_id = @@ -1841,10 +1704,11 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, : SemIR::InstId::None; new_class.parent_scope_id = parent_scope_id; - new_class.implicit_param_patterns_id = GetLocalParamPatternsId( - resolver, import_class.implicit_param_patterns_id); - new_class.param_patterns_id = - GetLocalParamPatternsId(resolver, import_class.param_patterns_id); + new_class.implicit_param_patterns_id = GetLocalCanonicalInstBlockId( + resolver, import_class.implicit_param_patterns_id, + implicit_param_patterns); + new_class.param_patterns_id = GetLocalCanonicalInstBlockId( + resolver, import_class.param_patterns_id, param_patterns); SetGenericData(resolver, import_class.generic_id, new_class.generic_id, generic_data); new_class.self_type_id = @@ -1888,10 +1752,10 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, class_const_inst.type_id()); auto specific_id = GetOrAddLocalSpecific(resolver, inst.specific_id, specific_data); - return ResolveAs(resolver, - {.type_id = SemIR::TypeType::TypeId, - .class_id = generic_class_type.class_id, - .specific_id = specific_id}); + return ResolveAsDeduplicated( + resolver, {.type_id = SemIR::TypeType::TypeId, + .class_id = generic_class_type.class_id, + .specific_id = specific_id}); } } @@ -1905,7 +1769,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, if (resolver.HasNewWork()) { return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = GetSingletonType(resolver.local_context(), SemIR::WitnessType::TypeInstId), .object_repr_type_inst_id = object_repr_type_inst_id}); @@ -1918,7 +1782,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, if (resolver.HasNewWork()) { return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = SemIR::TypeType::TypeId, .inner_id = inner_id}); } @@ -1935,14 +1799,12 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, if (resolver.HasNewWork()) { return ResolveResult::Retry(); } - auto inst_id = AddImportedInst( + return ResolveAsUnique( resolver, import_inst_id, {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId( const_id), .name_id = GetLocalNameId(resolver, inst.name_id), .index = inst.index}); - return ResolveResult::Done(resolver.local_constant_values().Get(inst_id), - inst_id); } // Make a declaration of a function. This is done as a separate step from @@ -2017,12 +1879,17 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, } auto parent_scope_id = GetLocalNameScopeId(resolver, import_function.parent_scope_id); - LoadLocalPatternConstantIds(resolver, - import_function.implicit_param_patterns_id); - LoadLocalPatternConstantIds(resolver, import_function.param_patterns_id); + auto implicit_param_patterns = GetLocalInstBlockContents( + resolver, import_function.implicit_param_patterns_id); + auto param_patterns = + GetLocalInstBlockContents(resolver, import_function.param_patterns_id); auto generic_data = GetLocalGenericData(resolver, import_function.generic_id); - auto& new_function = resolver.local_functions().Get(function_id); + auto self_param_id = + GetLocalConstantInstId(resolver, import_function.self_param_id); + auto return_slot_pattern_id = + GetLocalConstantInstId(resolver, import_function.return_slot_pattern_id); + auto& new_function = resolver.local_functions().Get(function_id); if (resolver.HasNewWork()) { return ResolveResult::Retry(function_const_id, new_function.first_decl_id()); @@ -2030,14 +1897,13 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, // Add the function declaration. new_function.parent_scope_id = parent_scope_id; - SemIR::InstId self_param_id = SemIR::InstId::None; - new_function.implicit_param_patterns_id = GetLocalParamPatternsId( - resolver, import_function.implicit_param_patterns_id, &self_param_id); + new_function.implicit_param_patterns_id = GetLocalCanonicalInstBlockId( + resolver, import_function.implicit_param_patterns_id, + implicit_param_patterns); new_function.self_param_id = self_param_id; - new_function.param_patterns_id = - GetLocalParamPatternsId(resolver, import_function.param_patterns_id); - new_function.return_slot_pattern_id = GetLocalReturnSlotPatternId( - resolver, import_function.return_slot_pattern_id, return_type_const_id); + new_function.param_patterns_id = GetLocalCanonicalInstBlockId( + resolver, import_function.param_patterns_id, param_patterns); + new_function.return_slot_pattern_id = return_slot_pattern_id; SetGenericData(resolver, import_function.generic_id, new_function.generic_id, generic_data); @@ -2059,7 +1925,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, return ResolveResult::Retry(); } auto fn_type_id = resolver.local_insts().Get(fn_val_id).type_id(); - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = SemIR::TypeType::TypeId, .function_id = resolver.local_types() .GetAs(fn_type_id) @@ -2079,7 +1945,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = SemIR::TypeType::TypeId, .interface_function_type_id = interface_function_type_id, .self_id = self_id}); @@ -2206,7 +2072,8 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, // Load constants for the definition. auto parent_scope_id = GetLocalNameScopeId(resolver, import_impl.parent_scope_id); - LoadLocalPatternConstantIds(resolver, import_impl.implicit_param_patterns_id); + auto implicit_param_patterns = GetLocalInstBlockContents( + resolver, import_impl.implicit_param_patterns_id); auto generic_data = GetLocalGenericData(resolver, import_impl.generic_id); auto self_const_id = GetLocalConstantId( resolver, @@ -2221,8 +2088,9 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, } new_impl.parent_scope_id = parent_scope_id; - new_impl.implicit_param_patterns_id = - GetLocalParamPatternsId(resolver, import_impl.implicit_param_patterns_id); + new_impl.implicit_param_patterns_id = GetLocalCanonicalInstBlockId( + resolver, import_impl.implicit_param_patterns_id, + implicit_param_patterns); SetGenericData(resolver, import_impl.generic_id, new_impl.generic_id, generic_data); @@ -2374,9 +2242,10 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, auto parent_scope_id = GetLocalNameScopeId(resolver, import_interface.parent_scope_id); - LoadLocalPatternConstantIds(resolver, - import_interface.implicit_param_patterns_id); - LoadLocalPatternConstantIds(resolver, import_interface.param_patterns_id); + auto implicit_param_patterns = GetLocalInstBlockContents( + resolver, import_interface.implicit_param_patterns_id); + auto param_patterns = + GetLocalInstBlockContents(resolver, import_interface.param_patterns_id); auto generic_data = GetLocalGenericData(resolver, import_interface.generic_id); @@ -2393,10 +2262,11 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, } new_interface.parent_scope_id = parent_scope_id; - new_interface.implicit_param_patterns_id = GetLocalParamPatternsId( - resolver, import_interface.implicit_param_patterns_id); - new_interface.param_patterns_id = - GetLocalParamPatternsId(resolver, import_interface.param_patterns_id); + new_interface.implicit_param_patterns_id = GetLocalCanonicalInstBlockId( + resolver, import_interface.implicit_param_patterns_id, + implicit_param_patterns); + new_interface.param_patterns_id = GetLocalCanonicalInstBlockId( + resolver, import_interface.param_patterns_id, param_patterns); SetGenericData(resolver, import_interface.generic_id, new_interface.generic_id, generic_data); @@ -2416,7 +2286,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = SemIR::TypeType::TypeId, .facet_value_inst_id = facet_value_inst_id}); } @@ -2471,7 +2341,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, // TODO: Also process the other requirements. SemIR::FacetTypeId facet_type_id = resolver.local_facet_types().Add(std::move(local_facet_type_info)); - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = SemIR::TypeType::TypeId, .facet_type_id = facet_type_id}); } @@ -2485,7 +2355,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId(type_id), @@ -2517,7 +2387,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, GetLocalSpecificInterface(resolver, import_specific_interface, data); auto query_specific_interface_id = resolver.local_specific_interfaces().Add(specific_interface); - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = GetSingletonType(resolver.local_context(), SemIR::WitnessType::TypeInstId), .query_self_inst_id = query_self_inst_id, @@ -2538,7 +2408,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, auto specific_id = GetOrAddLocalSpecific(resolver, inst.specific_id, specific_data); - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = GetSingletonType(resolver.local_context(), SemIR::WitnessType::TypeInstId), .witness_table_id = witness_table_id, @@ -2554,7 +2424,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId(type_id), @@ -2579,11 +2449,9 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, auto elements_id = GetLocalImportRefInstBlock(resolver, inst.elements_id); // Create a corresponding instruction to represent the table. - auto inst_id = AddImportedInst( + return ResolveAsUnique( resolver, import_inst_id, {.elements_id = elements_id, .impl_id = impl_id}); - return ResolveResult::Done(resolver.local_constant_values().Get(inst_id), - inst_id); } static auto TryResolveTypedInst(ImportRefResolver& resolver, @@ -2600,7 +2468,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, : resolver.local_ints().AddSigned( resolver.import_ints().Get(inst.int_id)); - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId(type_id), @@ -2615,10 +2483,10 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, return ResolveResult::Retry(); } - return ResolveAs(resolver, - {.type_id = SemIR::TypeType::TypeId, - .int_kind = inst.int_kind, - .bit_width_id = bit_width_id}); + return ResolveAsDeduplicated( + resolver, {.type_id = SemIR::TypeType::TypeId, + .int_kind = inst.int_kind, + .bit_width_id = bit_width_id}); } static auto TryResolveTypedInst(ImportRefResolver& resolver, @@ -2668,7 +2536,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = SemIR::TypeType::TypeId, .scrutinee_type_inst_id = scrutinee_type_inst_id}); } @@ -2681,7 +2549,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = SemIR::TypeType::TypeId, .pointee_id = pointee_id}); } @@ -2697,12 +2565,27 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = GetSingletonType(resolver.local_context(), SemIR::WitnessType::TypeInstId), .complete_type_inst_id = complete_type_inst_id}); } +static auto TryResolveTypedInst(ImportRefResolver& resolver, + SemIR::ReturnSlotPattern inst, + SemIR::InstId import_inst_id) -> ResolveResult { + auto type_const_id = GetLocalConstantId(resolver, inst.type_id); + if (resolver.HasNewWork()) { + return ResolveResult::Retry(); + } + + return ResolveAsUnique( + resolver, import_inst_id, + {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId( + type_const_id), + .type_inst_id = SemIR::TypeInstId::None}); +} + static auto TryResolveTypedInst(ImportRefResolver& resolver, SemIR::SpecificFunction inst) -> ResolveResult { auto type_const_id = GetLocalConstantId(resolver, inst.type_id); @@ -2716,7 +2599,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, type_const_id); auto specific_id = GetOrAddLocalSpecific(resolver, inst.specific_id, specific_data); - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = type_id, .callee_id = callee_id, .specific_id = specific_id}); } @@ -2734,7 +2617,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, SemIR::SpecificFunctionType::TypeInstId); auto specific_id = GetOrAddLocalSpecific(resolver, inst.specific_id, specific_data); - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = type_id, .callee_id = callee_id, .specific_id = specific_id}); } @@ -2763,7 +2646,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, {.name_id = name_id, .type_inst_id = field_type_inst_id}); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = SemIR::TypeType::TypeId, .fields_id = resolver.local_struct_type_fields().AddCanonical( new_fields)}); @@ -2777,7 +2660,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId(type_id), @@ -2803,7 +2686,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = SemIR::TypeType::TypeId, .type_elements_id = GetLocalCanonicalInstBlockId( resolver, inst.type_elements_id, type_inst_ids)}); @@ -2817,7 +2700,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId(type_id), @@ -2837,12 +2720,28 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, return ResolveResult::Retry(); } - return ResolveAs( + return ResolveAsDeduplicated( resolver, {.type_id = SemIR::TypeType::TypeId, .class_type_inst_id = class_const_inst_id, .element_type_inst_id = elem_const_inst_id}); } +static auto TryResolveTypedInst(ImportRefResolver& resolver, + SemIR::VarPattern inst, + SemIR::InstId import_inst_id) -> ResolveResult { + auto type_const_id = GetLocalConstantId(resolver, inst.type_id); + auto subpattern_id = GetLocalConstantInstId(resolver, inst.subpattern_id); + if (resolver.HasNewWork()) { + return ResolveResult::Retry(); + } + + return ResolveAsUnique( + resolver, import_inst_id, + {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId( + type_const_id), + .subpattern_id = subpattern_id}); +} + // Tries to resolve the InstId, returning a canonical constant when ready, or // `None` if more has been added to the stack. This is the same as // TryResolveInst, except that it may resolve symbolic constants as canonical @@ -2866,6 +2765,9 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver, case CARBON_KIND(SemIR::AdaptDecl inst): { return TryResolveTypedInst(resolver, inst, inst_id); } + case CARBON_KIND(SemIR::AddrPattern inst): { + return TryResolveTypedInst(resolver, inst, inst_id); + } case CARBON_KIND(SemIR::ArrayType inst): { return TryResolveTypedInst(resolver, inst); } @@ -2884,6 +2786,9 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver, case CARBON_KIND(SemIR::BindAlias inst): { return TryResolveTypedInst(resolver, inst); } + case CARBON_KIND(SemIR::BindingPattern inst): { + return TryResolveTypedInst(resolver, inst, inst_id); + } case SemIR::BindName::Kind: { // TODO: Should we be resolving BindNames at all? return ResolveResult::Done(SemIR::ConstantId::NotConstant); @@ -2969,30 +2874,39 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver, case CARBON_KIND(SemIR::Namespace inst): { return TryResolveTypedInst(resolver, inst, inst_id); } + case CARBON_KIND(SemIR::OutParamPattern inst): { + return TryResolveTypedInst(resolver, inst, inst_id); + } case CARBON_KIND(SemIR::PatternType inst): { return TryResolveTypedInst(resolver, inst); } case CARBON_KIND(SemIR::PointerType inst): { return TryResolveTypedInst(resolver, inst); } + case CARBON_KIND(SemIR::RefParamPattern inst): { + return TryResolveTypedInst(resolver, inst, inst_id); + } case CARBON_KIND(SemIR::RequireCompleteType inst): { return TryResolveTypedInst(resolver, inst); } + case CARBON_KIND(SemIR::ReturnSlotPattern inst): { + return TryResolveTypedInst(resolver, inst, inst_id); + } case CARBON_KIND(SemIR::SpecificFunction inst): { return TryResolveTypedInst(resolver, inst); } case CARBON_KIND(SemIR::SpecificImplFunction inst): { return TryResolveTypedInst(resolver, inst); } - case CARBON_KIND(SemIR::SymbolicBindingPattern inst): { - return TryResolveTypedInst(resolver, inst); - } case CARBON_KIND(SemIR::StructType inst): { return TryResolveTypedInst(resolver, inst); } case CARBON_KIND(SemIR::StructValue inst): { return TryResolveTypedInst(resolver, inst); } + case CARBON_KIND(SemIR::SymbolicBindingPattern inst): { + return TryResolveTypedInst(resolver, inst, inst_id); + } case CARBON_KIND(SemIR::TupleType inst): { return TryResolveTypedInst(resolver, inst); } @@ -3002,6 +2916,12 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver, case CARBON_KIND(SemIR::UnboundElementType inst): { return TryResolveTypedInst(resolver, inst); } + case CARBON_KIND(SemIR::ValueParamPattern inst): { + return TryResolveTypedInst(resolver, inst, inst_id); + } + case CARBON_KIND(SemIR::VarPattern inst): { + return TryResolveTypedInst(resolver, inst, inst_id); + } case CARBON_KIND(SemIR::Vtable inst): { return TryResolveTypedInst(resolver, inst); } diff --git a/toolchain/check/merge.cpp b/toolchain/check/merge.cpp index f486bd395a06..cae6b91fd805 100644 --- a/toolchain/check/merge.cpp +++ b/toolchain/check/merge.cpp @@ -203,13 +203,10 @@ static auto EntityHasParamError(Context& context, const DeclParams& info) // to provide a diagnostic. static auto CheckRedeclParam(Context& context, bool is_implicit_param, int32_t param_index, - SemIR::InstId new_param_pattern_id, - SemIR::InstId prev_param_pattern_id, + SemIR::InstId orig_new_param_pattern_id, + SemIR::InstId orig_prev_param_pattern_id, SemIR::SpecificId prev_specific_id, bool diagnose, bool check_syntax, bool check_self) -> bool { - auto orig_new_param_pattern_id = new_param_pattern_id; - auto orig_prev_param_pattern_id = prev_param_pattern_id; - // TODO: Consider differentiating between type and name mistakes. For now, // taking the simpler approach because I also think we may want to refactor // params. @@ -232,78 +229,101 @@ static auto CheckRedeclParam(Context& context, bool is_implicit_param, .Emit(); }; - auto new_param_pattern = context.insts().Get(new_param_pattern_id); - auto prev_param_pattern = context.insts().Get(prev_param_pattern_id); - if (new_param_pattern.kind() != prev_param_pattern.kind()) { - emit_diagnostic(); - return false; - } + struct PatternPair { + SemIR::InstId prev_id; + SemIR::InstId new_id; + }; - if (new_param_pattern.Is()) { - new_param_pattern_id = new_param_pattern.As().inner_id; - new_param_pattern = context.insts().Get(new_param_pattern_id); - prev_param_pattern_id = - prev_param_pattern.As().inner_id; - prev_param_pattern = context.insts().Get(prev_param_pattern_id); + llvm::SmallVector pattern_stack; + + pattern_stack.push_back({.prev_id = orig_prev_param_pattern_id, + .new_id = orig_new_param_pattern_id}); + + do { + auto patterns = pattern_stack.pop_back_val(); + auto new_param_pattern = context.insts().Get(patterns.new_id); + auto prev_param_pattern = context.insts().Get(patterns.prev_id); if (new_param_pattern.kind() != prev_param_pattern.kind()) { emit_diagnostic(); return false; } - } - if (new_param_pattern.Is()) { - new_param_pattern_id = - new_param_pattern.As().subpattern_id; - new_param_pattern = context.insts().Get(new_param_pattern_id); - prev_param_pattern_id = - prev_param_pattern.As().subpattern_id; - prev_param_pattern = context.insts().Get(prev_param_pattern_id); - if (new_param_pattern.kind() != prev_param_pattern.kind()) { - emit_diagnostic(); - return false; + switch (new_param_pattern.kind()) { + case SemIR::AddrPattern::Kind: { + pattern_stack.push_back( + {.prev_id = prev_param_pattern.As().inner_id, + .new_id = new_param_pattern.As().inner_id}); + break; + } + case SemIR::OutParamPattern::Kind: + case SemIR::RefParamPattern::Kind: + case SemIR::ValueParamPattern::Kind: { + pattern_stack.push_back( + {.prev_id = + prev_param_pattern.As().subpattern_id, + .new_id = + new_param_pattern.As().subpattern_id}); + break; + } + case SemIR::VarPattern::Kind: + pattern_stack.push_back( + {.prev_id = + prev_param_pattern.As().subpattern_id, + .new_id = + new_param_pattern.As().subpattern_id}); + break; + case SemIR::BindingPattern::Kind: + case SemIR::SymbolicBindingPattern::Kind: { + auto new_name_id = + context.entity_names() + .Get(new_param_pattern.As() + .entity_name_id) + .name_id; + auto prev_name_id = + context.entity_names() + .Get(prev_param_pattern.As() + .entity_name_id) + .name_id; + + if (!check_self && new_name_id == SemIR::NameId::SelfValue && + prev_name_id == SemIR::NameId::SelfValue) { + break; + } + + auto prev_param_type_id = SemIR::GetTypeOfInstInSpecific( + context.sem_ir(), prev_specific_id, patterns.prev_id); + if (!context.types().AreEqualAcrossDeclarations( + new_param_pattern.type_id(), prev_param_type_id)) { + if (!diagnose) { + return false; + } + CARBON_DIAGNOSTIC( + RedeclParamDiffersType, Error, + "type {3} of {0:implicit |}parameter {1} in " + "redeclaration differs from previous parameter type {2}", + Diagnostics::BoolAsSelect, int32_t, SemIR::TypeId, SemIR::TypeId); + context.emitter() + .Build(orig_new_param_pattern_id, RedeclParamDiffersType, + is_implicit_param, param_index + 1, prev_param_type_id, + new_param_pattern.type_id()) + .Note(orig_prev_param_pattern_id, RedeclParamPrevious, + is_implicit_param) + .Emit(); + return false; + } + + if (check_syntax && new_name_id != prev_name_id) { + emit_diagnostic(); + return false; + } + break; + } + default: { + CARBON_FATAL("Unexpected inst kind in parameter pattern: {0}", + new_param_pattern.kind()); + } } - } - - auto new_name_id = - context.entity_names() - .Get(new_param_pattern.As().entity_name_id) - .name_id; - auto prev_name_id = - context.entity_names() - .Get(prev_param_pattern.As().entity_name_id) - .name_id; - - if (!check_self && new_name_id == SemIR::NameId::SelfValue && - prev_name_id == SemIR::NameId::SelfValue) { - return true; - } - - auto prev_param_type_id = SemIR::GetTypeOfInstInSpecific( - context.sem_ir(), prev_specific_id, prev_param_pattern_id); - if (!context.types().AreEqualAcrossDeclarations(new_param_pattern.type_id(), - prev_param_type_id)) { - if (!diagnose) { - return false; - } - CARBON_DIAGNOSTIC(RedeclParamDiffersType, Error, - "type {3} of {0:implicit |}parameter {1} in " - "redeclaration differs from previous parameter type {2}", - Diagnostics::BoolAsSelect, int32_t, SemIR::TypeId, - SemIR::TypeId); - context.emitter() - .Build(orig_new_param_pattern_id, RedeclParamDiffersType, - is_implicit_param, param_index + 1, prev_param_type_id, - new_param_pattern.type_id()) - .Note(orig_prev_param_pattern_id, RedeclParamPrevious, - is_implicit_param) - .Emit(); - return false; - } - - if (check_syntax && new_name_id != prev_name_id) { - emit_diagnostic(); - return false; - } + } while (!pattern_stack.empty()); return true; } diff --git a/toolchain/check/testdata/builtins/float/make_type.carbon b/toolchain/check/testdata/builtins/float/make_type.carbon index 2eb2a4bdc12f..e1442a376dc6 100644 --- a/toolchain/check/testdata/builtins/float/make_type.carbon +++ b/toolchain/check/testdata/builtins/float/make_type.carbon @@ -97,12 +97,12 @@ var dyn: Float(dyn_size); // CHECK:STDOUT: constants { // CHECK:STDOUT: %Float.type: type = fn_type @Float [concrete] // CHECK:STDOUT: %Float: %Float.type = struct_value () [concrete] +// CHECK:STDOUT: %pattern_type.98f: type = pattern_type type [concrete] // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] // CHECK:STDOUT: %Int.type: type = generic_class_type @Int [concrete] // CHECK:STDOUT: %Int.generic: %Int.type = struct_value () [concrete] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] // CHECK:STDOUT: %pattern_type.501: type = pattern_type %i32 [concrete] -// CHECK:STDOUT: %pattern_type.98f: type = pattern_type type [concrete] // CHECK:STDOUT: %int_64.fab: Core.IntLiteral = int_value 64 [concrete] // CHECK:STDOUT: %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete] // CHECK:STDOUT: %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete] diff --git a/toolchain/check/testdata/class/generic/base_is_generic.carbon b/toolchain/check/testdata/class/generic/base_is_generic.carbon index 0e1b09f3e415..f302f62fb33a 100644 --- a/toolchain/check/testdata/class/generic/base_is_generic.carbon +++ b/toolchain/check/testdata/class/generic/base_is_generic.carbon @@ -291,7 +291,7 @@ fn H() { // CHECK:STDOUT: %Main.import_ref.8e0 = import_ref Main//extend_generic_base, inst26 [no loc], unloaded // CHECK:STDOUT: %Main.import_ref.7f7: @Base.%Base.elem (%Base.elem.9af) = import_ref Main//extend_generic_base, loc5_8, loaded [concrete = %.e66] // CHECK:STDOUT: %Main.import_ref.bd0: = import_ref Main//extend_generic_base, loc14_1, loaded [concrete = constants.%complete_type.b07] -// CHECK:STDOUT: %Main.import_ref.f6c = import_ref Main//extend_generic_base, inst77 [no loc], unloaded +// CHECK:STDOUT: %Main.import_ref.f6c = import_ref Main//extend_generic_base, inst76 [no loc], unloaded // CHECK:STDOUT: %Main.import_ref.d24 = import_ref Main//extend_generic_base, loc13_27, unloaded // CHECK:STDOUT: %Main.import_ref.77a301.2: type = import_ref Main//extend_generic_base, loc13_26, loaded [concrete = constants.%Base.7a8] // CHECK:STDOUT: %Core.Int: %Int.type = import_ref Core//prelude/types/int, Int, loaded [concrete = constants.%Int.generic] diff --git a/toolchain/check/testdata/class/generic/import.carbon b/toolchain/check/testdata/class/generic/import.carbon index 5164c0692a83..2f6a9583cbd1 100644 --- a/toolchain/check/testdata/class/generic/import.carbon +++ b/toolchain/check/testdata/class/generic/import.carbon @@ -310,7 +310,7 @@ class Class(U:! type) { // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... // CHECK:STDOUT: } -// CHECK:STDOUT: %Main.import_ref.773: @impl.a8d.%Convert.type (%Convert.type.9a6) = import_ref Main//foo, inst143 [indirect], loaded [symbolic = @impl.a8d.%Convert (constants.%Convert.458)] +// CHECK:STDOUT: %Main.import_ref.773: @impl.a8d.%Convert.type (%Convert.type.9a6) = import_ref Main//foo, inst140 [indirect], loaded [symbolic = @impl.a8d.%Convert (constants.%Convert.458)] // CHECK:STDOUT: %ImplicitAs.impl_witness_table.1ad = impl_witness_table (%Main.import_ref.773), @impl.a8d [concrete] // CHECK:STDOUT: %Main.import_ref.5ab3ec.1: type = import_ref Main//foo, loc4_13, loaded [symbolic = @Class.%T.1 (constants.%T)] // CHECK:STDOUT: %Main.import_ref.5ab3ec.2: type = import_ref Main//foo, loc6_21, loaded [symbolic = @CompleteClass.%T (constants.%T)] diff --git a/toolchain/check/testdata/class/import.carbon b/toolchain/check/testdata/class/import.carbon index bc38eb4e8c94..cbb14d877d1f 100644 --- a/toolchain/check/testdata/class/import.carbon +++ b/toolchain/check/testdata/class/import.carbon @@ -234,11 +234,11 @@ fn Run() { // CHECK:STDOUT: %ImplicitAs.impl_witness_table.e36 = impl_witness_table (%Core.import_ref.a86), @impl.c81 [concrete] // CHECK:STDOUT: %.d33: %Field.elem = field_decl x, element0 [concrete] // CHECK:STDOUT: %Main.import_ref.8f24d3.2: = import_ref Main//a, loc16_1, loaded [concrete = constants.%complete_type.357] -// CHECK:STDOUT: %Main.import_ref.39e731.1 = import_ref Main//a, inst60 [no loc], unloaded +// CHECK:STDOUT: %Main.import_ref.39e731.1 = import_ref Main//a, inst59 [no loc], unloaded // CHECK:STDOUT: %Main.import_ref.760: %F.type = import_ref Main//a, loc14_21, loaded [concrete = constants.%F] // CHECK:STDOUT: %Main.import_ref.26e: %G.type = import_ref Main//a, loc15_27, loaded [concrete = constants.%G] // CHECK:STDOUT: %Main.import_ref.8f24d3.3: = import_ref Main//a, loc16_1, loaded [concrete = constants.%complete_type.357] -// CHECK:STDOUT: %Main.import_ref.39e731.2 = import_ref Main//a, inst60 [no loc], unloaded +// CHECK:STDOUT: %Main.import_ref.39e731.2 = import_ref Main//a, inst59 [no loc], unloaded // CHECK:STDOUT: %Main.import_ref.42a = import_ref Main//a, loc14_21, unloaded // CHECK:STDOUT: %Main.import_ref.67a = import_ref Main//a, loc15_27, unloaded // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/class/import_base.carbon b/toolchain/check/testdata/class/import_base.carbon index 155f4cbaabb7..7d0ec2b80175 100644 --- a/toolchain/check/testdata/class/import_base.carbon +++ b/toolchain/check/testdata/class/import_base.carbon @@ -195,7 +195,7 @@ fn Run() { // CHECK:STDOUT: %Main.import_ref.e67: %Base.elem = import_ref Main//a, loc8_8, loaded [concrete = %.720] // CHECK:STDOUT: %Main.import_ref.2e4 = import_ref Main//a, loc9_13, unloaded // CHECK:STDOUT: %Main.import_ref.c5f: = import_ref Main//a, loc14_1, loaded [concrete = constants.%complete_type.15c] -// CHECK:STDOUT: %Main.import_ref.9a9 = import_ref Main//a, inst74 [no loc], unloaded +// CHECK:STDOUT: %Main.import_ref.9a9 = import_ref Main//a, inst73 [no loc], unloaded // CHECK:STDOUT: %Main.import_ref.7e5 = import_ref Main//a, loc13_20, unloaded // CHECK:STDOUT: %Main.import_ref.a21640.2: type = import_ref Main//a, loc13_16, loaded [concrete = constants.%Base] // CHECK:STDOUT: %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic] 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 5058df9d56b7..bbdba3bad056 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 @@ -596,9 +596,9 @@ var arr: array(i32, (1 as i32) + (2 as i32)) = (3, 4, (3 as i32) + (4 as i32)); // CHECK:STDOUT: %Self.65a: %As.type.eed = bind_symbolic_name Self, 1 [symbolic] // CHECK:STDOUT: %Convert.type.843: type = fn_type @Convert.1, @As(%T) [symbolic] // CHECK:STDOUT: %Convert.95f: %Convert.type.843 = struct_value () [symbolic] +// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %T [symbolic] // CHECK:STDOUT: %Self.as_type.04d: type = facet_access_type %Self.65a [symbolic] // CHECK:STDOUT: %pattern_type.ca4: type = pattern_type %Self.as_type.04d [symbolic] -// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %T [symbolic] // CHECK:STDOUT: %As.assoc_type.760: type = assoc_entity_type @As, @As(%T) [symbolic] // CHECK:STDOUT: %assoc0.076: %As.assoc_type.760 = assoc_entity element0, imports.%Core.import_ref.708 [symbolic] // CHECK:STDOUT: %As.type.a6d: type = facet_type <@As, @As(%i32.builtin)> [concrete] diff --git a/toolchain/check/testdata/function/declaration/import.carbon b/toolchain/check/testdata/function/declaration/import.carbon index bcbaee57fad6..796b6c27fa40 100644 --- a/toolchain/check/testdata/function/declaration/import.carbon +++ b/toolchain/check/testdata/function/declaration/import.carbon @@ -865,9 +865,9 @@ import library "extern_api"; // CHECK:STDOUT: %pattern_type.501: type = pattern_type %i32 [concrete] // CHECK:STDOUT: %C.type: type = fn_type @C [concrete] // CHECK:STDOUT: %C: %C.type = struct_value () [concrete] -// CHECK:STDOUT: %tuple.type.dd4: type = tuple_type (%i32) [concrete] // CHECK:STDOUT: %struct_type.c: type = struct_type {.c: %i32} [concrete] // CHECK:STDOUT: %pattern_type.f5f: type = pattern_type %struct_type.c [concrete] +// CHECK:STDOUT: %tuple.type.dd4: type = tuple_type (%i32) [concrete] // CHECK:STDOUT: %D.type: type = fn_type @D [concrete] // CHECK:STDOUT: %D: %D.type = struct_value () [concrete] // CHECK:STDOUT: %E.type: type = fn_type @E [concrete] diff --git a/toolchain/check/testdata/impl/no_prelude/compound.carbon b/toolchain/check/testdata/impl/no_prelude/compound.carbon index a1366e507c30..6e540fc7d80d 100644 --- a/toolchain/check/testdata/impl/no_prelude/compound.carbon +++ b/toolchain/check/testdata/impl/no_prelude/compound.carbon @@ -318,9 +318,9 @@ fn InstanceCallFail() { // CHECK:STDOUT: %Self.519: %ImplicitAs.type.d62 = bind_symbolic_name Self, 1 [symbolic] // CHECK:STDOUT: %Convert.type.275: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic] // CHECK:STDOUT: %Convert.42e: %Convert.type.275 = struct_value () [symbolic] +// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %Dest [symbolic] // CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self.519 [symbolic] // CHECK:STDOUT: %pattern_type.f3e: type = pattern_type %Self.as_type [symbolic] -// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %Dest [symbolic] // CHECK:STDOUT: %ImplicitAs.assoc_type.ca0: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic] // CHECK:STDOUT: %assoc0.9f5: %ImplicitAs.assoc_type.ca0 = assoc_entity element0, imports.%Core.import_ref.1c7 [symbolic] // CHECK:STDOUT: %ImplicitAs.type.c38: type = facet_type <@ImplicitAs, @ImplicitAs(%NonInstance2.type)> [concrete] @@ -500,9 +500,9 @@ fn InstanceCallFail() { // CHECK:STDOUT: %Self.519: %ImplicitAs.type.d62 = bind_symbolic_name Self, 1 [symbolic] // CHECK:STDOUT: %Convert.type.275: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic] // CHECK:STDOUT: %Convert.42e: %Convert.type.275 = struct_value () [symbolic] +// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %Dest [symbolic] // CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self.519 [symbolic] // CHECK:STDOUT: %pattern_type.f3e: type = pattern_type %Self.as_type [symbolic] -// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %Dest [symbolic] // CHECK:STDOUT: %ImplicitAs.assoc_type.ca0: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic] // CHECK:STDOUT: %assoc0.9f5: %ImplicitAs.assoc_type.ca0 = assoc_entity element0, imports.%Core.import_ref.1c7 [symbolic] // CHECK:STDOUT: %ImplicitAs.type.c69: type = facet_type <@ImplicitAs, @ImplicitAs(%NonInstance3.type)> [concrete] diff --git a/toolchain/check/testdata/impl/no_prelude/import_compound.carbon b/toolchain/check/testdata/impl/no_prelude/import_compound.carbon index 7409d837fbe3..6ab1ec48939d 100644 --- a/toolchain/check/testdata/impl/no_prelude/import_compound.carbon +++ b/toolchain/check/testdata/impl/no_prelude/import_compound.carbon @@ -466,9 +466,9 @@ fn InstanceCallImportFail() { // CHECK:STDOUT: %Self.519: %ImplicitAs.type.d62 = bind_symbolic_name Self, 1 [symbolic] // CHECK:STDOUT: %Convert.type.275: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic] // CHECK:STDOUT: %Convert.42e: %Convert.type.275 = struct_value () [symbolic] +// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %Dest [symbolic] // CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self.519 [symbolic] // CHECK:STDOUT: %pattern_type.f3e: type = pattern_type %Self.as_type [symbolic] -// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %Dest [symbolic] // CHECK:STDOUT: %ImplicitAs.assoc_type.ca0: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic] // CHECK:STDOUT: %assoc0.9f5: %ImplicitAs.assoc_type.ca0 = assoc_entity element0, imports.%Core.import_ref.1c7 [symbolic] // CHECK:STDOUT: %ImplicitAs.type.a4a: type = facet_type <@ImplicitAs, @ImplicitAs(%NonInstance.type)> [concrete] @@ -652,9 +652,9 @@ fn InstanceCallImportFail() { // CHECK:STDOUT: %Self.519: %ImplicitAs.type.d62 = bind_symbolic_name Self, 1 [symbolic] // CHECK:STDOUT: %Convert.type.275: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic] // CHECK:STDOUT: %Convert.42e: %Convert.type.275 = struct_value () [symbolic] +// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %Dest [symbolic] // CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self.519 [symbolic] // CHECK:STDOUT: %pattern_type.f3e: type = pattern_type %Self.as_type [symbolic] -// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %Dest [symbolic] // CHECK:STDOUT: %ImplicitAs.assoc_type.ca0: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic] // CHECK:STDOUT: %assoc0.9f5: %ImplicitAs.assoc_type.ca0 = assoc_entity element0, imports.%Core.import_ref.1c7 [symbolic] // CHECK:STDOUT: %ImplicitAs.type.a4a: type = facet_type <@ImplicitAs, @ImplicitAs(%NonInstance.type)> [concrete] diff --git a/toolchain/check/testdata/interface/min_prelude/fail_member_lookup.carbon b/toolchain/check/testdata/interface/min_prelude/fail_member_lookup.carbon index 3516316d5d20..141a601f307a 100644 --- a/toolchain/check/testdata/interface/min_prelude/fail_member_lookup.carbon +++ b/toolchain/check/testdata/interface/min_prelude/fail_member_lookup.carbon @@ -166,9 +166,9 @@ fn G(U:! Different) -> U.(Interface.T); // CHECK:STDOUT: %Self.519: %ImplicitAs.type.d62 = bind_symbolic_name Self, 1 [symbolic] // CHECK:STDOUT: %Convert.type.275: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic] // CHECK:STDOUT: %Convert.42e: %Convert.type.275 = struct_value () [symbolic] +// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %Dest [symbolic] // CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self.519 [symbolic] // CHECK:STDOUT: %pattern_type.f3e: type = pattern_type %Self.as_type [symbolic] -// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %Dest [symbolic] // CHECK:STDOUT: %ImplicitAs.assoc_type.ca0: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic] // CHECK:STDOUT: %assoc0.9f5: %ImplicitAs.assoc_type.ca0 = assoc_entity element0, imports.%Core.import_ref.1c7 [symbolic] // CHECK:STDOUT: %ImplicitAs.type.dc8: type = facet_type <@ImplicitAs, @ImplicitAs(type)> [concrete] diff --git a/toolchain/check/testdata/let/fail_missing_value.carbon b/toolchain/check/testdata/let/fail_missing_value.carbon index c33aafcd2126..fbc6971995b2 100644 --- a/toolchain/check/testdata/let/fail_missing_value.carbon +++ b/toolchain/check/testdata/let/fail_missing_value.carbon @@ -46,7 +46,7 @@ fn F() { // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [concrete] { // CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .n = .inst45.loc15_5 +// CHECK:STDOUT: .n = .inst44.loc15_5 // CHECK:STDOUT: .F = %F.decl // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core diff --git a/toolchain/check/testdata/operators/overloaded/no_prelude/index.carbon b/toolchain/check/testdata/operators/overloaded/no_prelude/index.carbon index b98310e35d28..9f2e88c94470 100644 --- a/toolchain/check/testdata/operators/overloaded/no_prelude/index.carbon +++ b/toolchain/check/testdata/operators/overloaded/no_prelude/index.carbon @@ -267,10 +267,10 @@ fn F() { ()[()]; } // CHECK:STDOUT: %Self.30a: %IndexWith.type.bd2 = bind_symbolic_name Self, 1 [symbolic] // CHECK:STDOUT: %At.type.cf4: type = fn_type @At.1, @IndexWith(%SubscriptType) [symbolic] // CHECK:STDOUT: %At.281: %At.type.cf4 = struct_value () [symbolic] -// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %SubscriptType [symbolic] +// CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] // CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self.30a [symbolic] // CHECK:STDOUT: %pattern_type.e1a: type = pattern_type %Self.as_type [symbolic] -// CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %SubscriptType [symbolic] // CHECK:STDOUT: %IndexWith.assoc_type.290: type = assoc_entity_type @IndexWith, @IndexWith(%SubscriptType) [symbolic] // CHECK:STDOUT: %assoc0.af8: %IndexWith.assoc_type.290 = assoc_entity element0, imports.%Core.import_ref.e99 [symbolic] // CHECK:STDOUT: %IndexWith.type.a51: type = facet_type <@IndexWith, @IndexWith(%empty_tuple.type)> [concrete] diff --git a/toolchain/check/testdata/return/min_prelude/import_convert_function.carbon b/toolchain/check/testdata/return/min_prelude/import_convert_function.carbon index e64511571595..1729c71c1cad 100644 --- a/toolchain/check/testdata/return/min_prelude/import_convert_function.carbon +++ b/toolchain/check/testdata/return/min_prelude/import_convert_function.carbon @@ -296,9 +296,9 @@ fn F0(n: i32) -> P.D { // CHECK:STDOUT: %Self.519: %ImplicitAs.type.d62 = bind_symbolic_name Self, 1 [symbolic] // CHECK:STDOUT: %Convert.type.275: type = fn_type @Convert.1, @ImplicitAs(%T) [symbolic] // CHECK:STDOUT: %Convert.42e: %Convert.type.275 = struct_value () [symbolic] +// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %T [symbolic] // CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self.519 [symbolic] // CHECK:STDOUT: %pattern_type.f3e: type = pattern_type %Self.as_type [symbolic] -// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %T [symbolic] // CHECK:STDOUT: %ImplicitAs.assoc_type.ca0: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%T) [symbolic] // CHECK:STDOUT: %assoc0.9f5: %ImplicitAs.assoc_type.ca0 = assoc_entity element0, imports.%Core.import_ref.1c7 [symbolic] // CHECK:STDOUT: %ImplicitAs.type.61e: type = facet_type <@ImplicitAs, @ImplicitAs(%i32.builtin)> [concrete] @@ -1101,9 +1101,9 @@ fn F0(n: i32) -> P.D { // CHECK:STDOUT: %Self.519: %ImplicitAs.type.d62 = bind_symbolic_name Self, 1 [symbolic] // CHECK:STDOUT: %Convert.type.275: type = fn_type @Convert.1, @ImplicitAs(%T) [symbolic] // CHECK:STDOUT: %Convert.42e: %Convert.type.275 = struct_value () [symbolic] +// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %T [symbolic] // CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self.519 [symbolic] // CHECK:STDOUT: %pattern_type.f3e: type = pattern_type %Self.as_type [symbolic] -// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %T [symbolic] // CHECK:STDOUT: %ImplicitAs.assoc_type.ca0: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%T) [symbolic] // CHECK:STDOUT: %assoc0.9f5: %ImplicitAs.assoc_type.ca0 = assoc_entity element0, imports.%Core.import_ref.1c7 [symbolic] // CHECK:STDOUT: %ImplicitAs.type.61e: type = facet_type <@ImplicitAs, @ImplicitAs(%i32.builtin)> [concrete] diff --git a/toolchain/check/testdata/struct/import.carbon b/toolchain/check/testdata/struct/import.carbon index ac2154df3b8b..ea3dc33559fe 100644 --- a/toolchain/check/testdata/struct/import.carbon +++ b/toolchain/check/testdata/struct/import.carbon @@ -347,12 +347,12 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... // CHECK:STDOUT: } -// CHECK:STDOUT: %Implicit.import_ref.773: @impl.a8d.%Convert.type (%Convert.type.9a6) = import_ref Implicit//default, inst119 [indirect], loaded [symbolic = @impl.a8d.%Convert (constants.%Convert.458)] +// CHECK:STDOUT: %Implicit.import_ref.773: @impl.a8d.%Convert.type (%Convert.type.9a6) = import_ref Implicit//default, inst116 [indirect], loaded [symbolic = @impl.a8d.%Convert (constants.%Convert.458)] // CHECK:STDOUT: %ImplicitAs.impl_witness_table.1ad = impl_witness_table (%Implicit.import_ref.773), @impl.a8d [concrete] // CHECK:STDOUT: %Core.Int: %Int.type = import_ref Core//prelude/types/int, Int, loaded [concrete = constants.%Int.generic] // CHECK:STDOUT: %Implicit.import_ref.c81: %struct_type.a.b.5ca = import_ref Implicit//default, loc8_9, loaded [symbolic = @C.%S (constants.%S)] // CHECK:STDOUT: %Implicit.import_ref.8f2: = import_ref Implicit//default, loc8_34, loaded [concrete = constants.%complete_type.357] -// CHECK:STDOUT: %Implicit.import_ref.b8b = import_ref Implicit//default, inst1423 [no loc], unloaded +// CHECK:STDOUT: %Implicit.import_ref.b8b = import_ref Implicit//default, inst1418 [no loc], unloaded // CHECK:STDOUT: %Core.ImplicitAs: %ImplicitAs.type.595 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -526,7 +526,7 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: } // CHECK:STDOUT: %Implicit.import_ref.c81: %struct_type.a.b = import_ref Implicit//default, loc8_9, loaded [symbolic = @C.%S (constants.%S)] // CHECK:STDOUT: %Implicit.import_ref.8f2: = import_ref Implicit//default, loc8_34, loaded [concrete = constants.%complete_type.357] -// CHECK:STDOUT: %Implicit.import_ref.b8b = import_ref Implicit//default, inst1423 [no loc], unloaded +// CHECK:STDOUT: %Implicit.import_ref.b8b = import_ref Implicit//default, inst1418 [no loc], unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -643,11 +643,11 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... // CHECK:STDOUT: } -// CHECK:STDOUT: %Implicit.import_ref.773: @impl.a8d.%Convert.type (%Convert.type.9a6) = import_ref Implicit//default, inst119 [indirect], loaded [symbolic = @impl.a8d.%Convert (constants.%Convert.458)] +// CHECK:STDOUT: %Implicit.import_ref.773: @impl.a8d.%Convert.type (%Convert.type.9a6) = import_ref Implicit//default, inst116 [indirect], loaded [symbolic = @impl.a8d.%Convert (constants.%Convert.458)] // CHECK:STDOUT: %ImplicitAs.impl_witness_table.1ad = impl_witness_table (%Implicit.import_ref.773), @impl.a8d [concrete] // CHECK:STDOUT: %Implicit.import_ref.c81: %struct_type.a.b.5ca = import_ref Implicit//default, loc8_9, loaded [symbolic = @C.%S (constants.%S)] // CHECK:STDOUT: %Implicit.import_ref.8f2: = import_ref Implicit//default, loc8_34, loaded [concrete = constants.%complete_type.357] -// CHECK:STDOUT: %Implicit.import_ref.b8b = import_ref Implicit//default, inst1423 [no loc], unloaded +// CHECK:STDOUT: %Implicit.import_ref.b8b = import_ref Implicit//default, inst1418 [no loc], unloaded // CHECK:STDOUT: %Core.ImplicitAs: %ImplicitAs.type.595 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic] // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/tuple/import.carbon b/toolchain/check/testdata/tuple/import.carbon index 0bb87c55a0be..5783297338ec 100644 --- a/toolchain/check/testdata/tuple/import.carbon +++ b/toolchain/check/testdata/tuple/import.carbon @@ -377,12 +377,12 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... // CHECK:STDOUT: } -// CHECK:STDOUT: %Implicit.import_ref.773: @impl.a8d.%Convert.type (%Convert.type.9a6) = import_ref Implicit//default, inst121 [indirect], loaded [symbolic = @impl.a8d.%Convert (constants.%Convert.458)] +// CHECK:STDOUT: %Implicit.import_ref.773: @impl.a8d.%Convert.type (%Convert.type.9a6) = import_ref Implicit//default, inst118 [indirect], loaded [symbolic = @impl.a8d.%Convert (constants.%Convert.458)] // CHECK:STDOUT: %ImplicitAs.impl_witness_table.1ad = impl_witness_table (%Implicit.import_ref.773), @impl.a8d [concrete] // CHECK:STDOUT: %Core.Int: %Int.type = import_ref Core//prelude/types/int, Int, loaded [concrete = constants.%Int.generic] // CHECK:STDOUT: %Implicit.import_ref.48d: %tuple.type.c2c = import_ref Implicit//default, loc7_9, loaded [symbolic = @C.%X (constants.%X)] // CHECK:STDOUT: %Implicit.import_ref.8f2: = import_ref Implicit//default, loc7_26, loaded [concrete = constants.%complete_type.357] -// CHECK:STDOUT: %Implicit.import_ref.964 = import_ref Implicit//default, inst1460 [no loc], unloaded +// CHECK:STDOUT: %Implicit.import_ref.964 = import_ref Implicit//default, inst1455 [no loc], unloaded // CHECK:STDOUT: %Core.ImplicitAs: %ImplicitAs.type.595 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -572,7 +572,7 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: } // CHECK:STDOUT: %Implicit.import_ref.48d: %tuple.type.c2c = import_ref Implicit//default, loc7_9, loaded [symbolic = @C.%X (constants.%X)] // CHECK:STDOUT: %Implicit.import_ref.8f2: = import_ref Implicit//default, loc7_26, loaded [concrete = constants.%complete_type.357] -// CHECK:STDOUT: %Implicit.import_ref.964 = import_ref Implicit//default, inst1460 [no loc], unloaded +// CHECK:STDOUT: %Implicit.import_ref.964 = import_ref Implicit//default, inst1455 [no loc], unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -690,11 +690,11 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... // CHECK:STDOUT: } -// CHECK:STDOUT: %Implicit.import_ref.773: @impl.a8d.%Convert.type (%Convert.type.9a6) = import_ref Implicit//default, inst121 [indirect], loaded [symbolic = @impl.a8d.%Convert (constants.%Convert.458)] +// CHECK:STDOUT: %Implicit.import_ref.773: @impl.a8d.%Convert.type (%Convert.type.9a6) = import_ref Implicit//default, inst118 [indirect], loaded [symbolic = @impl.a8d.%Convert (constants.%Convert.458)] // CHECK:STDOUT: %ImplicitAs.impl_witness_table.1ad = impl_witness_table (%Implicit.import_ref.773), @impl.a8d [concrete] // CHECK:STDOUT: %Implicit.import_ref.48d: %tuple.type.c2c = import_ref Implicit//default, loc7_9, loaded [symbolic = @C.%X (constants.%X)] // CHECK:STDOUT: %Implicit.import_ref.8f2: = import_ref Implicit//default, loc7_26, loaded [concrete = constants.%complete_type.357] -// CHECK:STDOUT: %Implicit.import_ref.964 = import_ref Implicit//default, inst1460 [no loc], unloaded +// CHECK:STDOUT: %Implicit.import_ref.964 = import_ref Implicit//default, inst1455 [no loc], unloaded // CHECK:STDOUT: %Core.ImplicitAs: %ImplicitAs.type.595 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic] // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/var/min_prelude/var_pattern.carbon b/toolchain/check/testdata/var/min_prelude/var_pattern.carbon index f301ea330ecb..c7ca1bba24c9 100644 --- a/toolchain/check/testdata/var/min_prelude/var_pattern.carbon +++ b/toolchain/check/testdata/var/min_prelude/var_pattern.carbon @@ -37,6 +37,28 @@ fn G() { F(v, ()); } +// --- public_function.carbon + +package P; + +fn F(x: (), var y: ()); + +// --- public_function.impl.carbon + +impl package P; + +fn F(x: (), var y: ()) {} + +// --- use_public_function.carbon + +library "[[@TEST_NAME]]"; + +import P; + +fn G() { + P.F((), ()); +} + // --- fail_nested.carbon library "[[@TEST_NAME]]"; @@ -94,6 +116,17 @@ class C { fn F[var self: Self](); } +// --- nested_match.carbon + +library "[[@TEST_NAME]]"; + +fn F() -> (); + +fn G() { + // The SemIR should contain only two temporary_storage insts, not three. + let (x: (), var y: (), z: ()) = (F(), F(), F()); +} + // CHECK:STDOUT: --- basic.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -274,6 +307,152 @@ class C { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- public_function.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %pattern_type: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %F.type: type = fn_type @F [concrete] +// CHECK:STDOUT: %F: %F.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [concrete] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { +// CHECK:STDOUT: %x.patt: %pattern_type = binding_pattern x [concrete] +// CHECK:STDOUT: %x.param_patt: %pattern_type = value_param_pattern %x.patt, call_param0 [concrete] +// CHECK:STDOUT: %y.patt: %pattern_type = binding_pattern y [concrete] +// CHECK:STDOUT: %y.param_patt: %pattern_type = ref_param_pattern %y.patt, call_param1 [concrete] +// CHECK:STDOUT: %.loc4_13: %pattern_type = var_pattern %y.param_patt [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %x.param: %empty_tuple.type = value_param call_param0 +// CHECK:STDOUT: %.loc4_10.1: type = splice_block %.loc4_10.3 [concrete = constants.%empty_tuple.type] { +// CHECK:STDOUT: %.loc4_10.2: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc4_10.3: type = converted %.loc4_10.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %x: %empty_tuple.type = bind_name x, %x.param +// CHECK:STDOUT: %y.param: ref %empty_tuple.type = ref_param call_param1 +// CHECK:STDOUT: %.loc4_21.1: type = splice_block %.loc4_21.3 [concrete = constants.%empty_tuple.type] { +// CHECK:STDOUT: %.loc4_21.2: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc4_21.3: type = converted %.loc4_21.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %y: ref %empty_tuple.type = bind_name y, %y.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%x.param: %empty_tuple.type, %y.param: %empty_tuple.type); +// CHECK:STDOUT: +// CHECK:STDOUT: --- public_function.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %pattern_type: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %F.type: type = fn_type @F [concrete] +// CHECK:STDOUT: %F: %F.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [concrete] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: } +// CHECK:STDOUT: %P.import = import P +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { +// CHECK:STDOUT: %x.patt: %pattern_type = binding_pattern x [concrete] +// CHECK:STDOUT: %x.param_patt: %pattern_type = value_param_pattern %x.patt, call_param0 [concrete] +// CHECK:STDOUT: %y.patt: %pattern_type = binding_pattern y [concrete] +// CHECK:STDOUT: %y.param_patt: %pattern_type = ref_param_pattern %y.patt, call_param1 [concrete] +// CHECK:STDOUT: %.loc4_13: %pattern_type = var_pattern %y.param_patt [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %x.param: %empty_tuple.type = value_param call_param0 +// CHECK:STDOUT: %.loc4_10.1: type = splice_block %.loc4_10.3 [concrete = constants.%empty_tuple.type] { +// CHECK:STDOUT: %.loc4_10.2: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc4_10.3: type = converted %.loc4_10.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %x: %empty_tuple.type = bind_name x, %x.param +// CHECK:STDOUT: %y.param: ref %empty_tuple.type = ref_param call_param1 +// CHECK:STDOUT: %.loc4_21.1: type = splice_block %.loc4_21.3 [concrete = constants.%empty_tuple.type] { +// CHECK:STDOUT: %.loc4_21.2: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc4_21.3: type = converted %.loc4_21.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %y: ref %empty_tuple.type = bind_name y, %y.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%x.param: %empty_tuple.type, %y.param: %empty_tuple.type) [from "public_function.carbon"] { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- use_public_function.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %G.type: type = fn_type @G [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %G: %G.type = struct_value () [concrete] +// CHECK:STDOUT: %F.type: type = fn_type @F [concrete] +// CHECK:STDOUT: %F: %F.type = struct_value () [concrete] +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [concrete] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: } +// CHECK:STDOUT: %P: = namespace file.%P.import, [concrete] { +// CHECK:STDOUT: .F = %P.F +// CHECK:STDOUT: import P//default +// CHECK:STDOUT: } +// CHECK:STDOUT: %P.F: %F.type = import_ref P//default, F, loaded [concrete = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .P = imports.%P +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %P.import = import P +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %P.ref: = name_ref P, imports.%P [concrete = imports.%P] +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, imports.%P.F [concrete = constants.%F] +// CHECK:STDOUT: %.loc7_8.1: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc7_12.1: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc7_8.2: %empty_tuple.type = converted %.loc7_8.1, %empty_tuple [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.1: ref %empty_tuple.type = temporary_storage +// CHECK:STDOUT: %.loc7_12.2: init %empty_tuple.type = tuple_init () to %.1 [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.2: init %empty_tuple.type = converted %.loc7_12.1, %.loc7_12.2 [concrete = constants.%empty_tuple] +// CHECK:STDOUT: assign %.1, %.2 +// CHECK:STDOUT: %F.call: init %empty_tuple.type = call %F.ref(%.loc7_8.2, %.1) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F [from "public_function.carbon"]; +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_nested.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -417,3 +596,83 @@ class C { // CHECK:STDOUT: // CHECK:STDOUT: fn @F(%self.param: %C); // CHECK:STDOUT: +// CHECK:STDOUT: --- nested_match.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %F.type: type = fn_type @F [concrete] +// CHECK:STDOUT: %F: %F.type = struct_value () [concrete] +// CHECK:STDOUT: %G.type: type = fn_type @G [concrete] +// CHECK:STDOUT: %G: %G.type = struct_value () [concrete] +// CHECK:STDOUT: %tuple.type: type = tuple_type (%empty_tuple.type, %empty_tuple.type, %empty_tuple.type) [concrete] +// CHECK:STDOUT: %pattern_type.8c1: type = pattern_type %tuple.type [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [concrete] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] { +// CHECK:STDOUT: %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %.loc4_12.1: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc4_12.2: type = converted %.loc4_12.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: %return.param: ref %empty_tuple.type = out_param call_param0 +// CHECK:STDOUT: %return: ref %empty_tuple.type = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() -> %empty_tuple.type; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %x.patt: %pattern_type.cb1 = binding_pattern x [concrete] +// CHECK:STDOUT: %y.patt: %pattern_type.cb1 = binding_pattern y [concrete] +// CHECK:STDOUT: %.loc8_15: %pattern_type.cb1 = var_pattern %y.patt [concrete] +// CHECK:STDOUT: %z.patt: %pattern_type.cb1 = binding_pattern z [concrete] +// CHECK:STDOUT: %.loc8_31: %pattern_type.8c1 = tuple_pattern (%x.patt, %.loc8_15, %z.patt) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %y.var: ref %empty_tuple.type = var y +// CHECK:STDOUT: %F.ref.loc8_36: %F.type = name_ref F, file.%F.decl [concrete = constants.%F] +// CHECK:STDOUT: %F.call.loc8_38: init %empty_tuple.type = call %F.ref.loc8_36() +// CHECK:STDOUT: %F.ref.loc8_41: %F.type = name_ref F, file.%F.decl [concrete = constants.%F] +// CHECK:STDOUT: %F.call.loc8_43: init %empty_tuple.type = call %F.ref.loc8_41() +// CHECK:STDOUT: %F.ref.loc8_46: %F.type = name_ref F, file.%F.decl [concrete = constants.%F] +// CHECK:STDOUT: %F.call.loc8_48: init %empty_tuple.type = call %F.ref.loc8_46() +// CHECK:STDOUT: %.loc8_49: %tuple.type = tuple_literal (%F.call.loc8_38, %F.call.loc8_43, %F.call.loc8_48) +// CHECK:STDOUT: %.loc8_12.1: type = splice_block %.loc8_12.3 [concrete = constants.%empty_tuple.type] { +// CHECK:STDOUT: %.loc8_12.2: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc8_12.3: type = converted %.loc8_12.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_38.1: ref %empty_tuple.type = temporary_storage +// CHECK:STDOUT: %.loc8_38.2: ref %empty_tuple.type = temporary %.loc8_38.1, %F.call.loc8_38 +// CHECK:STDOUT: %x: ref %empty_tuple.type = bind_name x, %.loc8_38.2 +// CHECK:STDOUT: assign %y.var, %F.call.loc8_43 +// CHECK:STDOUT: %.loc8_23.1: type = splice_block %.loc8_23.3 [concrete = constants.%empty_tuple.type] { +// CHECK:STDOUT: %.loc8_23.2: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc8_23.3: type = converted %.loc8_23.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %y: ref %empty_tuple.type = bind_name y, %y.var +// CHECK:STDOUT: %.loc8_30.1: type = splice_block %.loc8_30.3 [concrete = constants.%empty_tuple.type] { +// CHECK:STDOUT: %.loc8_30.2: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc8_30.3: type = converted %.loc8_30.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_48.1: ref %empty_tuple.type = temporary_storage +// CHECK:STDOUT: %.loc8_48.2: ref %empty_tuple.type = temporary %.loc8_48.1, %F.call.loc8_48 +// CHECK:STDOUT: %z: ref %empty_tuple.type = bind_name z, %.loc8_48.2 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/sem_ir/function.h b/toolchain/sem_ir/function.h index 492a2d1ce346..2847a9175b72 100644 --- a/toolchain/sem_ir/function.h +++ b/toolchain/sem_ir/function.h @@ -56,8 +56,8 @@ struct FunctionFields { // is not virtual (ie: (virtual_modifier == None) == (virtual_index == -1)). int32_t virtual_index = -1; - // The implicit self parameter, if any, in implicit_param_patterns_id from - // EntityWithParamsBase. + // The implicit self parameter pattern, if any, in + // implicit_param_patterns_id from EntityWithParamsBase. InstId self_param_id = InstId::None; // The following member is set on the first call to the function, or at the diff --git a/toolchain/sem_ir/inst.h b/toolchain/sem_ir/inst.h index 6addff57501b..c6e7869ca1b5 100644 --- a/toolchain/sem_ir/inst.h +++ b/toolchain/sem_ir/inst.h @@ -79,7 +79,7 @@ struct InstLikeTypeInfo : InstLikeTypeInfoBase { static_assert(HasKindMemberAsField, "Instruction category should have a kind field"); static auto GetKind(InstCat cat) -> InstKind { return cat.kind; } - static auto IsKind(InstKind kind) -> bool { + static constexpr auto IsKind(InstKind kind) -> bool { for (InstKind k : InstCat::Kinds) { if (k == kind) { return true; @@ -100,6 +100,10 @@ struct InstLikeTypeInfo : InstLikeTypeInfoBase { } }; +// HasInstCategory is true if T::Kind is an element of InstCat::Kinds. +template +concept HasInstCategory = InstLikeTypeInfo::IsKind(T::Kind); + // A type is InstLike if InstLikeTypeInfo is defined for it. template concept InstLikeType = requires { sizeof(InstLikeTypeInfo); };