diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp index 3e3644d26c2e..41937af5da60 100644 --- a/toolchain/check/eval.cpp +++ b/toolchain/check/eval.cpp @@ -1744,7 +1744,8 @@ static auto TryEvalTypedInst(EvalContext& eval_context, SemIR::InstId inst_id, // Couldn't perform the action because it's still dependent. return MakeConstantResult(eval_context.context(), inst, Phase::TemplateSymbolic); - } else if constexpr (InstT::Kind.constant_needs_inst_id()) { + } else if constexpr (InstT::Kind.constant_needs_inst_id() != + SemIR::InstConstantNeedsInstIdKind::No) { CARBON_CHECK(inst_id.has_value()); return ConvertEvalResultToConstantId( eval_context.context(), diff --git a/toolchain/check/eval.h b/toolchain/check/eval.h index 1998d2b09062..985b166afcbb 100644 --- a/toolchain/check/eval.h +++ b/toolchain/check/eval.h @@ -8,6 +8,7 @@ #include "toolchain/check/context.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/inst.h" +#include "toolchain/sem_ir/inst_kind.h" namespace Carbon::Check { @@ -38,8 +39,12 @@ inline auto TryEvalInst(Context& context, SemIR::InstId inst_id) // value and the instruction is known to not matter. However, even then care // should be taken: if the produced constant is symbolic, you may still need an // instruction to associate the constant with the enclosing generic. +// +// To evaluate an instruction and add it to SemIR only if necessary, use +// EvalOrAddInst instead. template - requires(!InstT::Kind.constant_needs_inst_id()) + requires(InstT::Kind.constant_needs_inst_id() == + SemIR::InstConstantNeedsInstIdKind::No) auto TryEvalInst(Context& context, InstT inst) -> SemIR::ConstantId { return TryEvalInstUnsafe(context, SemIR::InstId::None, inst); } diff --git a/toolchain/check/eval_inst.h b/toolchain/check/eval_inst.h index 818682c10170..7648bdf68f36 100644 --- a/toolchain/check/eval_inst.h +++ b/toolchain/check/eval_inst.h @@ -140,7 +140,8 @@ template using FunctionTypeForEvalConstantInst = typename FunctionTypeForEvalConstantInstImpl< InstT, ConstantKindHasEvalConstantInst(InstT::Kind.constant_kind()), - InstT::Kind.constant_needs_inst_id()>::Type; + InstT::Kind.constant_needs_inst_id() != + SemIR::InstConstantNeedsInstIdKind::No>::Type; } // namespace Internal diff --git a/toolchain/check/impl_lookup.cpp b/toolchain/check/impl_lookup.cpp index 64000c7d12de..349f9c5f3d46 100644 --- a/toolchain/check/impl_lookup.cpp +++ b/toolchain/check/impl_lookup.cpp @@ -344,8 +344,8 @@ static auto FindWitnessInImpls(Context& context, SemIR::LocId loc_id, SemIR::ConstantId query_self_const_id, SemIR::SpecificInterface interface) -> SemIR::InstId { - auto witness_id = AddInstInNoBlock( - context, loc_id, + auto witness_const_id = EvalOrAddInst( + context, loc_id.ToImplicit(), SemIR::LookupImplWitness{ .type_id = GetSingletonType(context, SemIR::WitnessType::SingletonInstId), @@ -356,7 +356,6 @@ static auto FindWitnessInImpls(Context& context, SemIR::LocId loc_id, }); // We use a NotConstant result from eval to communicate back an impl // lookup failure. See `EvalConstantInst()` for `LookupImplWitness`. - auto witness_const_id = context.constant_values().Get(witness_id); if (!witness_const_id.is_constant()) { return SemIR::InstId::None; } diff --git a/toolchain/check/inst.cpp b/toolchain/check/inst.cpp index 8649fa26fe80..d4f88560e4ad 100644 --- a/toolchain/check/inst.cpp +++ b/toolchain/check/inst.cpp @@ -10,6 +10,7 @@ #include "toolchain/check/generic_region_stack.h" #include "toolchain/sem_ir/constant.h" #include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/inst_kind.h" namespace Carbon::Check { @@ -100,20 +101,91 @@ auto AddPatternInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst) auto GetOrAddInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId { - if (loc_id_and_inst.loc_id.is_implicit() && - !loc_id_and_inst.inst.kind().constant_needs_inst_id()) { - auto const_id = - TryEvalInstUnsafe(context, SemIR::InstId::None, loc_id_and_inst.inst); - if (const_id.has_value()) { - CARBON_VLOG_TO(context.vlog_stream(), "GetOrAddInst: constant: {0}\n", - loc_id_and_inst.inst); - return context.constant_values().GetInstId(const_id); + CARBON_CHECK(!loc_id_and_inst.inst.kind().has_cleanup()); + + auto handle_constant_id = [&](SemIR::ConstantId const_id) -> SemIR::InstId { + CARBON_CHECK(const_id.has_value()); + + // If we didn't produce a constant value for the instruction, we have to add + // the instruction. + if (!const_id.is_constant()) { + return SemIR::InstId::None; + } + + CARBON_VLOG_TO(context.vlog_stream(), "GetOrAddInst: constant: {0}\n", + loc_id_and_inst.inst); + return context.constant_values().GetInstId(const_id); + }; + + // If the instruction is implicit, produce its constant value instead if + // possible. + if (loc_id_and_inst.loc_id.is_implicit()) { + switch (loc_id_and_inst.inst.kind().constant_needs_inst_id()) { + case SemIR::InstConstantNeedsInstIdKind::No: { + // Evaluation doesn't need an InstId. Just do it. + auto const_id = TryEvalInstUnsafe(context, SemIR::InstId::None, + loc_id_and_inst.inst); + if (auto result_inst_id = handle_constant_id(const_id); + result_inst_id.has_value()) { + return result_inst_id; + } + break; + } + + case SemIR::InstConstantNeedsInstIdKind::DuringEvaluation: { + // Evaluation temporarily needs an InstId. Add one for now. + auto inst_id = AddInstInNoBlock(context, loc_id_and_inst); + auto const_id = context.constant_values().Get(inst_id); + if (auto result_inst_id = handle_constant_id(const_id); + result_inst_id.has_value()) { + // TODO: We didn't end up needing the `inst_id` instruction. Consider + // removing it from `insts` if it's still the most recently added + // instruction. + CARBON_CHECK(result_inst_id != inst_id); + return result_inst_id; + } + context.inst_block_stack().AddInstId(inst_id); + return inst_id; + } + + case SemIR::InstConstantNeedsInstIdKind::Permanent: { + // Evaluation needs a permanent InstId. Add the instruction. + break; + } } } + // TODO: For an implicit instruction, this reattempts evaluation. return AddInst(context, loc_id_and_inst); } +auto EvalOrAddInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst) + -> SemIR::ConstantId { + CARBON_CHECK(!loc_id_and_inst.inst.kind().has_cleanup()); + + switch (loc_id_and_inst.inst.kind().constant_needs_inst_id()) { + case SemIR::InstConstantNeedsInstIdKind::No: { + // Evaluation doesn't need an InstId. Just do it. + return TryEvalInstUnsafe(context, SemIR::InstId::None, + loc_id_and_inst.inst); + } + + case SemIR::InstConstantNeedsInstIdKind::DuringEvaluation: { + // Evaluation temporarily needs an InstId. Add one for now. + auto inst_id = AddInstInNoBlock(context, loc_id_and_inst); + // TODO: Consider removing `inst_id` from `insts` if it's still the most + // recently added instruction. + return context.constant_values().Get(inst_id); + } + + case SemIR::InstConstantNeedsInstIdKind::Permanent: { + // Evaluation needs a permanent InstId. Add the instruction. + auto inst_id = AddInst(context, loc_id_and_inst); + return context.constant_values().Get(inst_id); + } + } +} + auto AddPlaceholderInstInNoBlock(Context& context, SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId { diff --git a/toolchain/check/inst.h b/toolchain/check/inst.h index d79e5c22b759..6138ad1054f8 100644 --- a/toolchain/check/inst.h +++ b/toolchain/check/inst.h @@ -64,6 +64,23 @@ auto GetOrAddInst(Context& context, LocT loc, InstT inst) -> SemIR::InstId { return GetOrAddInst(context, SemIR::LocIdAndInst(loc, inst)); } +// Evaluate the given instruction, and returns the corresponding constant value. +// Adds the instruction to the current block if it might be referenced by its +// constant value; otherwise, does not add the instruction to an instruction +// block. +auto EvalOrAddInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst) + -> SemIR::ConstantId; + +// Convenience for EvalOrAddInst with typed nodes. +// +// As a safety check, prevent use with storage insts (see `AddInstWithCleanup`). +template + requires(!InstT::Kind.has_cleanup()) +auto EvalOrAddInst(Context& context, LocT loc, InstT inst) + -> SemIR::ConstantId { + return EvalOrAddInst(context, SemIR::LocIdAndInst(loc, inst)); +} + // Adds an instruction and enqueues it to be added to the eval block of the // enclosing generic, returning the produced ID. The instruction is expected to // be a dependent template instantiation action. diff --git a/toolchain/check/subst.cpp b/toolchain/check/subst.cpp index 86f533e6c6b3..be8f15910cee 100644 --- a/toolchain/check/subst.cpp +++ b/toolchain/check/subst.cpp @@ -405,15 +405,13 @@ class SubstConstantCallbacks final : public SubstInstCallbacks { // Rebuilds an instruction by building a new constant. auto Rebuild(SemIR::InstId old_inst_id, SemIR::Inst new_inst) const -> SemIR::InstId override { - auto result_id = GetOrAddInst( + auto const_id = EvalOrAddInst( *context_, SemIR::LocIdAndInst::UncheckedLoc( context_->insts().GetLocId(old_inst_id).ToImplicit(), new_inst)); - auto const_inst_id = - context_->constant_values().GetConstantInstId(result_id); - CARBON_CHECK(const_inst_id.has_value(), + CARBON_CHECK(const_id.has_value(), "Substitution into constant produced non-constant"); - return const_inst_id; + return context_->constant_values().GetInstId(const_id); } private: diff --git a/toolchain/check/testdata/facet/min_prelude/convert_class_type_to_generic_facet_value.carbon b/toolchain/check/testdata/facet/min_prelude/convert_class_type_to_generic_facet_value.carbon index 3f6a2dbd986c..fc603ef1686e 100644 --- a/toolchain/check/testdata/facet/min_prelude/convert_class_type_to_generic_facet_value.carbon +++ b/toolchain/check/testdata/facet/min_prelude/convert_class_type_to_generic_facet_value.carbon @@ -245,7 +245,6 @@ fn G() { // CHECK:STDOUT: %CallGenericMethod.ref: %CallGenericMethod.type = name_ref CallGenericMethod, file.%CallGenericMethod.decl [concrete = constants.%CallGenericMethod] // CHECK:STDOUT: %GenericParam.ref: type = name_ref GenericParam, file.%GenericParam.decl [concrete = constants.%GenericParam] // CHECK:STDOUT: %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric] -// CHECK:STDOUT: %Generic.type: type = facet_type <@Generic, @Generic(constants.%GenericParam)> [concrete = constants.%Generic.type.769] // CHECK:STDOUT: %Generic.facet: %Generic.type.769 = facet_value constants.%ImplsGeneric, (constants.%impl_witness) [concrete = constants.%Generic.facet] // CHECK:STDOUT: %.loc18: %Generic.type.769 = converted constants.%ImplsGeneric, %Generic.facet [concrete = constants.%Generic.facet] // CHECK:STDOUT: %CallGenericMethod.specific_fn: = specific_function %CallGenericMethod.ref, @CallGenericMethod(constants.%GenericParam, constants.%Generic.facet) [concrete = constants.%CallGenericMethod.specific_fn.934] @@ -279,7 +278,6 @@ fn G() { // CHECK:STDOUT: %PassThroughToGenericMethod.ref: %PassThroughToGenericMethod.type = name_ref PassThroughToGenericMethod, file.%PassThroughToGenericMethod.decl [concrete = constants.%PassThroughToGenericMethod] // CHECK:STDOUT: %GenericParam.ref: type = name_ref GenericParam, file.%GenericParam.decl [concrete = constants.%GenericParam] // CHECK:STDOUT: %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric] -// CHECK:STDOUT: %Generic.type: type = facet_type <@Generic, @Generic(constants.%GenericParam)> [concrete = constants.%Generic.type.769] // CHECK:STDOUT: %Generic.facet: %Generic.type.769 = facet_value constants.%ImplsGeneric, (constants.%impl_witness) [concrete = constants.%Generic.facet] // CHECK:STDOUT: %.loc26: %Generic.type.769 = converted constants.%ImplsGeneric, %Generic.facet [concrete = constants.%Generic.facet] // CHECK:STDOUT: %PassThroughToGenericMethod.specific_fn: = specific_function %PassThroughToGenericMethod.ref, @PassThroughToGenericMethod(constants.%GenericParam, constants.%Generic.facet) [concrete = constants.%PassThroughToGenericMethod.specific_fn] @@ -537,7 +535,6 @@ fn G() { // CHECK:STDOUT: %.loc18_36.3: init %GenericParam = class_init (), %.loc18_36.2 [concrete = constants.%GenericParam.val] // CHECK:STDOUT: %.loc18_36.4: ref %GenericParam = temporary %.loc18_36.2, %.loc18_36.3 // CHECK:STDOUT: %.loc18_38.1: ref %GenericParam = converted %.loc18_36.1, %.loc18_36.4 -// CHECK:STDOUT: %Generic.type: type = facet_type <@Generic, @Generic(constants.%GenericParam)> [concrete = constants.%Generic.type.769] // CHECK:STDOUT: %Generic.facet: %Generic.type.769 = facet_value constants.%ImplsGeneric, (constants.%impl_witness) [concrete = constants.%Generic.facet] // CHECK:STDOUT: %.loc18_53: %Generic.type.769 = converted constants.%ImplsGeneric, %Generic.facet [concrete = constants.%Generic.facet] // CHECK:STDOUT: %CallGenericMethod.specific_fn: = specific_function %CallGenericMethod.ref, @CallGenericMethod(constants.%GenericParam, constants.%Generic.facet) [concrete = constants.%CallGenericMethod.specific_fn] diff --git a/toolchain/check/testdata/facet/min_prelude/convert_class_value_to_generic_facet_value_value.carbon b/toolchain/check/testdata/facet/min_prelude/convert_class_value_to_generic_facet_value_value.carbon index 51bcb6f7147e..15471cc881fd 100644 --- a/toolchain/check/testdata/facet/min_prelude/convert_class_value_to_generic_facet_value_value.carbon +++ b/toolchain/check/testdata/facet/min_prelude/convert_class_value_to_generic_facet_value_value.carbon @@ -319,7 +319,6 @@ fn B() { // CHECK:STDOUT: %.loc20_42.3: init %GenericParam = class_init (), %.loc20_42.2 [concrete = constants.%GenericParam.val] // CHECK:STDOUT: %.loc20_42.4: ref %GenericParam = temporary %.loc20_42.2, %.loc20_42.3 // CHECK:STDOUT: %.loc20_44.1: ref %GenericParam = converted %.loc20_42.1, %.loc20_42.4 -// CHECK:STDOUT: %Generic.type: type = facet_type <@Generic, @Generic(constants.%GenericParam)> [concrete = constants.%Generic.type.769] // CHECK:STDOUT: %Generic.facet: %Generic.type.769 = facet_value constants.%ImplsGeneric, (constants.%impl_witness) [concrete = constants.%Generic.facet.8bd] // CHECK:STDOUT: %.loc20_59: %Generic.type.769 = converted constants.%ImplsGeneric, %Generic.facet [concrete = constants.%Generic.facet.8bd] // CHECK:STDOUT: %CallGenericMethod.specific_fn: = specific_function %CallGenericMethod.ref, @CallGenericMethod(constants.%GenericParam, constants.%Generic.facet.8bd) [concrete = constants.%CallGenericMethod.specific_fn] diff --git a/toolchain/check/testdata/facet/min_prelude/convert_facet_value_to_narrowed_facet_type.carbon b/toolchain/check/testdata/facet/min_prelude/convert_facet_value_to_narrowed_facet_type.carbon index 02fb0e5cfd4d..0e087b440d16 100644 --- a/toolchain/check/testdata/facet/min_prelude/convert_facet_value_to_narrowed_facet_type.carbon +++ b/toolchain/check/testdata/facet/min_prelude/convert_facet_value_to_narrowed_facet_type.carbon @@ -919,8 +919,8 @@ fn CallsWithTypeExplicit(U:! type) { // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: %require_complete: = require_complete_type @HandleTameAnimal2.%W.as_type.loc11_44.2 (%W.as_type) [symbolic = %require_complete (constants.%require_complete.ba9)] -// CHECK:STDOUT: %W.as_wit.iface0.loc12_14.3: = facet_access_witness %W.loc11_22.2, element0 [symbolic = %W.as_wit.iface0.loc12_14.3 (constants.%W.as_wit.iface0)] -// CHECK:STDOUT: %Animal.facet.loc12_14.3: %Animal.type = facet_value %W.as_type.loc11_44.2, (%W.as_wit.iface0.loc12_14.3) [symbolic = %Animal.facet.loc12_14.3 (constants.%Animal.facet)] +// CHECK:STDOUT: %W.as_wit.iface0: = facet_access_witness %W.loc11_22.2, element0 [symbolic = %W.as_wit.iface0 (constants.%W.as_wit.iface0)] +// CHECK:STDOUT: %Animal.facet.loc12_14.3: %Animal.type = facet_value %W.as_type.loc11_44.2, (%W.as_wit.iface0) [symbolic = %Animal.facet.loc12_14.3 (constants.%Animal.facet)] // CHECK:STDOUT: %Eats.lookup_impl_witness: = lookup_impl_witness %W.loc11_22.2, @Eats [symbolic = %Eats.lookup_impl_witness (constants.%Eats.lookup_impl_witness)] // CHECK:STDOUT: %W.as_wit.iface1.loc12_14.3: = facet_access_witness %W.loc11_22.2, element1 [symbolic = %W.as_wit.iface1.loc12_14.3 (constants.%W.as_wit.iface1)] // CHECK:STDOUT: %facet_value.loc12_14.3: %facet_type.6ff = facet_value %W.as_type.loc11_44.2, (%Eats.lookup_impl_witness, %W.as_wit.iface1.loc12_14.3) [symbolic = %facet_value.loc12_14.3 (constants.%facet_value)] @@ -932,16 +932,14 @@ fn CallsWithTypeExplicit(U:! type) { // CHECK:STDOUT: %w.ref: @HandleTameAnimal2.%W.as_type.loc11_44.2 (%W.as_type) = name_ref w, %w // CHECK:STDOUT: %W.as_type.loc12_14.1: type = facet_access_type constants.%W [symbolic = %W.as_type.loc11_44.2 (constants.%W.as_type)] // CHECK:STDOUT: %.loc12_14.1: type = converted constants.%W, %W.as_type.loc12_14.1 [symbolic = %W.as_type.loc11_44.2 (constants.%W.as_type)] -// CHECK:STDOUT: %W.as_wit.iface0.loc12_14.1: = facet_access_witness constants.%W, element0 [symbolic = %W.as_wit.iface0.loc12_14.3 (constants.%W.as_wit.iface0)] -// CHECK:STDOUT: %Animal.facet.loc12_14.1: %Animal.type = facet_value constants.%W.as_type, (%W.as_wit.iface0.loc12_14.1) [symbolic = %Animal.facet.loc12_14.3 (constants.%Animal.facet)] +// CHECK:STDOUT: %Animal.facet.loc12_14.1: %Animal.type = facet_value constants.%W.as_type, (constants.%W.as_wit.iface0) [symbolic = %Animal.facet.loc12_14.3 (constants.%Animal.facet)] // CHECK:STDOUT: %.loc12_14.2: %Animal.type = converted %.loc12_14.1, %Animal.facet.loc12_14.1 [symbolic = %Animal.facet.loc12_14.3 (constants.%Animal.facet)] // CHECK:STDOUT: %W.as_wit.iface1.loc12_14.1: = facet_access_witness constants.%W, element1 [symbolic = %W.as_wit.iface1.loc12_14.3 (constants.%W.as_wit.iface1)] // CHECK:STDOUT: %facet_value.loc12_14.1: %facet_type.6ff = facet_value constants.%W.as_type, (constants.%Eats.lookup_impl_witness, %W.as_wit.iface1.loc12_14.1) [symbolic = %facet_value.loc12_14.3 (constants.%facet_value)] // CHECK:STDOUT: %.loc12_14.3: %facet_type.6ff = converted constants.%W.as_type, %facet_value.loc12_14.1 [symbolic = %facet_value.loc12_14.3 (constants.%facet_value)] // CHECK:STDOUT: %W.as_type.loc12_14.2: type = facet_access_type constants.%W [symbolic = %W.as_type.loc11_44.2 (constants.%W.as_type)] // CHECK:STDOUT: %.loc12_14.4: type = converted constants.%W, %W.as_type.loc12_14.2 [symbolic = %W.as_type.loc11_44.2 (constants.%W.as_type)] -// CHECK:STDOUT: %W.as_wit.iface0.loc12_14.2: = facet_access_witness constants.%W, element0 [symbolic = %W.as_wit.iface0.loc12_14.3 (constants.%W.as_wit.iface0)] -// CHECK:STDOUT: %Animal.facet.loc12_14.2: %Animal.type = facet_value constants.%W.as_type, (%W.as_wit.iface0.loc12_14.2) [symbolic = %Animal.facet.loc12_14.3 (constants.%Animal.facet)] +// CHECK:STDOUT: %Animal.facet.loc12_14.2: %Animal.type = facet_value constants.%W.as_type, (constants.%W.as_wit.iface0) [symbolic = %Animal.facet.loc12_14.3 (constants.%Animal.facet)] // CHECK:STDOUT: %.loc12_14.5: %Animal.type = converted %.loc12_14.4, %Animal.facet.loc12_14.2 [symbolic = %Animal.facet.loc12_14.3 (constants.%Animal.facet)] // CHECK:STDOUT: %W.as_wit.iface1.loc12_14.2: = facet_access_witness constants.%W, element1 [symbolic = %W.as_wit.iface1.loc12_14.3 (constants.%W.as_wit.iface1)] // CHECK:STDOUT: %facet_value.loc12_14.2: %facet_type.6ff = facet_value constants.%W.as_type, (constants.%Eats.lookup_impl_witness, %W.as_wit.iface1.loc12_14.2) [symbolic = %facet_value.loc12_14.3 (constants.%facet_value)] diff --git a/toolchain/check/testdata/facet/min_prelude/convert_facet_value_value_to_generic_facet_value_value.carbon b/toolchain/check/testdata/facet/min_prelude/convert_facet_value_value_to_generic_facet_value_value.carbon index 442b9c06429e..7baf21825bda 100644 --- a/toolchain/check/testdata/facet/min_prelude/convert_facet_value_value_to_generic_facet_value_value.carbon +++ b/toolchain/check/testdata/facet/min_prelude/convert_facet_value_value_to_generic_facet_value_value.carbon @@ -335,9 +335,9 @@ fn F() { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %require_complete.loc31_45: = require_complete_type @HandleAnimal.%T.as_type.loc31_47.2 (%T.as_type.2ad) [symbolic = %require_complete.loc31_45 (constants.%require_complete.234)] // CHECK:STDOUT: %require_complete.loc31_54: = require_complete_type @HandleAnimal.%Food.as_type.loc31_56.2 (%Food.as_type.fae) [symbolic = %require_complete.loc31_54 (constants.%require_complete.444)] -// CHECK:STDOUT: %Eats.type.2: type = facet_type <@Eats, @Eats(%Food.as_type.loc31_56.2)> [symbolic = %Eats.type.2 (constants.%Eats.type.f54c3d.2)] // CHECK:STDOUT: %Eats.lookup_impl_witness: = lookup_impl_witness %T.loc31_17.2, @Eats, @Eats(%Food.as_type.loc31_56.2) [symbolic = %Eats.lookup_impl_witness (constants.%Eats.lookup_impl_witness)] -// CHECK:STDOUT: %Eats.facet.loc31_76.2: @HandleAnimal.%Eats.type.2 (%Eats.type.f54c3d.2) = facet_value %T.as_type.loc31_47.2, (%Eats.lookup_impl_witness) [symbolic = %Eats.facet.loc31_76.2 (constants.%Eats.facet.512)] +// CHECK:STDOUT: %Eats.type: type = facet_type <@Eats, @Eats(%Food.as_type.loc31_56.2)> [symbolic = %Eats.type (constants.%Eats.type.f54c3d.2)] +// CHECK:STDOUT: %Eats.facet.loc31_76.2: @HandleAnimal.%Eats.type (%Eats.type.f54c3d.2) = facet_value %T.as_type.loc31_47.2, (%Eats.lookup_impl_witness) [symbolic = %Eats.facet.loc31_76.2 (constants.%Eats.facet.512)] // CHECK:STDOUT: %Feed.specific_fn.loc31_64.2: = specific_function constants.%Feed, @Feed(%Food.loc31_29.2, %Eats.facet.loc31_76.2) [symbolic = %Feed.specific_fn.loc31_64.2 (constants.%Feed.specific_fn.ea3)] // CHECK:STDOUT: // CHECK:STDOUT: fn[%T.patt.loc31_17.1: %Animal.type, %Food.patt.loc31_29.1: %Edible.type](%a.param_patt: @HandleAnimal.%T.as_type.loc31_47.2 (%T.as_type.2ad), %food.param_patt: @HandleAnimal.%Food.as_type.loc31_56.2 (%Food.as_type.fae)) { @@ -347,14 +347,12 @@ fn F() { // CHECK:STDOUT: %food.ref: @HandleAnimal.%Food.as_type.loc31_56.2 (%Food.as_type.fae) = name_ref food, %food // CHECK:STDOUT: %.loc31_76.1: %Edible.type = converted constants.%Food.as_type.fae, constants.%Food.5fe [symbolic = %Food.loc31_29.2 (constants.%Food.5fe)] // CHECK:STDOUT: %.loc31_76.2: %Edible.type = converted constants.%Food.as_type.fae, constants.%Food.5fe [symbolic = %Food.loc31_29.2 (constants.%Food.5fe)] -// CHECK:STDOUT: %Food.as_type.1: type = facet_access_type constants.%Food.5fe [symbolic = %Food.as_type.loc31_56.2 (constants.%Food.as_type.fae)] -// CHECK:STDOUT: %Eats.type.1: type = facet_type <@Eats, @Eats(constants.%Food.as_type.fae)> [symbolic = %Eats.type.2 (constants.%Eats.type.f54c3d.2)] // CHECK:STDOUT: %.loc31_76.3: %Edible.type = converted constants.%Food.as_type.fae, constants.%Food.5fe [symbolic = %Food.loc31_29.2 (constants.%Food.5fe)] // CHECK:STDOUT: %T.as_type.loc31_76: type = facet_access_type constants.%T.fd4 [symbolic = %T.as_type.loc31_47.2 (constants.%T.as_type.2ad)] // CHECK:STDOUT: %.loc31_76.4: type = converted constants.%T.fd4, %T.as_type.loc31_76 [symbolic = %T.as_type.loc31_47.2 (constants.%T.as_type.2ad)] // CHECK:STDOUT: %.loc31_76.5: %Animal.type = converted %.loc31_76.4, constants.%T.fd4 [symbolic = %T.loc31_17.2 (constants.%T.fd4)] -// CHECK:STDOUT: %Eats.facet.loc31_76.1: @HandleAnimal.%Eats.type.2 (%Eats.type.f54c3d.2) = facet_value constants.%T.as_type.2ad, (constants.%Eats.lookup_impl_witness) [symbolic = %Eats.facet.loc31_76.2 (constants.%Eats.facet.512)] -// CHECK:STDOUT: %.loc31_76.6: @HandleAnimal.%Eats.type.2 (%Eats.type.f54c3d.2) = converted constants.%T.as_type.2ad, %Eats.facet.loc31_76.1 [symbolic = %Eats.facet.loc31_76.2 (constants.%Eats.facet.512)] +// CHECK:STDOUT: %Eats.facet.loc31_76.1: @HandleAnimal.%Eats.type (%Eats.type.f54c3d.2) = facet_value constants.%T.as_type.2ad, (constants.%Eats.lookup_impl_witness) [symbolic = %Eats.facet.loc31_76.2 (constants.%Eats.facet.512)] +// CHECK:STDOUT: %.loc31_76.6: @HandleAnimal.%Eats.type (%Eats.type.f54c3d.2) = converted constants.%T.as_type.2ad, %Eats.facet.loc31_76.1 [symbolic = %Eats.facet.loc31_76.2 (constants.%Eats.facet.512)] // CHECK:STDOUT: %Feed.specific_fn.loc31_64.1: = specific_function %Feed.ref, @Feed(constants.%Food.5fe, constants.%Eats.facet.512) [symbolic = %Feed.specific_fn.loc31_64.2 (constants.%Feed.specific_fn.ea3)] // CHECK:STDOUT: %Feed.call: init %empty_tuple.type = call %Feed.specific_fn.loc31_64.1(%a.ref, %food.ref) // CHECK:STDOUT: return @@ -497,8 +495,8 @@ fn F() { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %require_complete.loc31_45 => constants.%complete_type.357 // CHECK:STDOUT: %require_complete.loc31_54 => constants.%complete_type.357 -// CHECK:STDOUT: %Eats.type.2 => constants.%Eats.type.1ae // CHECK:STDOUT: %Eats.lookup_impl_witness => constants.%impl_witness.4f1 +// CHECK:STDOUT: %Eats.type => constants.%Eats.type.1ae // CHECK:STDOUT: %Eats.facet.loc31_76.2 => constants.%Eats.facet.fa6 // CHECK:STDOUT: %Feed.specific_fn.loc31_64.2 => constants.%Feed.specific_fn.d82 // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/facet/min_prelude/fail_convert_class_type_to_generic_facet_value.carbon b/toolchain/check/testdata/facet/min_prelude/fail_convert_class_type_to_generic_facet_value.carbon index a12615bce1e1..e1d8d3238bb3 100644 --- a/toolchain/check/testdata/facet/min_prelude/fail_convert_class_type_to_generic_facet_value.carbon +++ b/toolchain/check/testdata/facet/min_prelude/fail_convert_class_type_to_generic_facet_value.carbon @@ -210,7 +210,6 @@ fn G() { // CHECK:STDOUT: %CallGenericMethod.ref: %CallGenericMethod.type = name_ref CallGenericMethod, file.%CallGenericMethod.decl [concrete = constants.%CallGenericMethod] // CHECK:STDOUT: %WrongGenericParam.ref: type = name_ref WrongGenericParam, file.%WrongGenericParam.decl [concrete = constants.%WrongGenericParam] // CHECK:STDOUT: %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric] -// CHECK:STDOUT: %Generic.type: type = facet_type <@Generic, @Generic(constants.%WrongGenericParam)> [concrete = constants.%Generic.type.c3b] // CHECK:STDOUT: %CallGenericMethod.specific_fn: = specific_function %CallGenericMethod.ref, @CallGenericMethod(constants.%WrongGenericParam, ) [concrete = ] // CHECK:STDOUT: %CallGenericMethod.call: init %empty_tuple.type = call %CallGenericMethod.specific_fn() [concrete = ] // CHECK:STDOUT: return diff --git a/toolchain/check/testdata/facet/min_prelude/fail_deduction_uses_runtime_type_conversion.carbon b/toolchain/check/testdata/facet/min_prelude/fail_deduction_uses_runtime_type_conversion.carbon index 430d3200f58f..eb6f2cb394cd 100644 --- a/toolchain/check/testdata/facet/min_prelude/fail_deduction_uses_runtime_type_conversion.carbon +++ b/toolchain/check/testdata/facet/min_prelude/fail_deduction_uses_runtime_type_conversion.carbon @@ -304,7 +304,6 @@ fn G(holds_to: HoldsType((RuntimeConvertTo, ))) { // CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F] // CHECK:STDOUT: %from.ref: %RuntimeConvertFrom = name_ref from, %from [symbolic = constants.%from] // CHECK:STDOUT: %holds_to.ref: %HoldsType.066 = name_ref holds_to, %holds_to -// CHECK:STDOUT: %tuple.elem0: type = tuple_access constants.%tuple, element0 [concrete = constants.%RuntimeConvertTo] // CHECK:STDOUT: %impl.elem0: %.31e = impl_witness_access constants.%impl_witness, element0 [concrete = constants.%Convert.e81] // CHECK:STDOUT: %bound_method: = bound_method constants.%from, %impl.elem0 [symbolic = constants.%Convert.bound] // CHECK:STDOUT: %.loc40_19.1: ref %RuntimeConvertTo = temporary_storage diff --git a/toolchain/check/testdata/function/generic/call_method_on_generic_facet.carbon b/toolchain/check/testdata/function/generic/call_method_on_generic_facet.carbon index a8d1deefc10c..a129ae17db76 100644 --- a/toolchain/check/testdata/function/generic/call_method_on_generic_facet.carbon +++ b/toolchain/check/testdata/function/generic/call_method_on_generic_facet.carbon @@ -273,7 +273,6 @@ fn G() { // CHECK:STDOUT: %CallGenericMethod.ref: %CallGenericMethod.type = name_ref CallGenericMethod, file.%CallGenericMethod.decl [concrete = constants.%CallGenericMethod] // CHECK:STDOUT: %GenericParam.ref: type = name_ref GenericParam, file.%GenericParam.decl [concrete = constants.%GenericParam] // CHECK:STDOUT: %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric] -// CHECK:STDOUT: %Generic.type: type = facet_type <@Generic, @Generic(constants.%GenericParam)> [concrete = constants.%Generic.type.769] // CHECK:STDOUT: %Generic.facet: %Generic.type.769 = facet_value constants.%ImplsGeneric, (constants.%impl_witness.b42) [concrete = constants.%Generic.facet.8bd] // CHECK:STDOUT: %.loc34: %Generic.type.769 = converted constants.%ImplsGeneric, %Generic.facet [concrete = constants.%Generic.facet.8bd] // CHECK:STDOUT: %CallGenericMethod.specific_fn: = specific_function %CallGenericMethod.ref, @CallGenericMethod(constants.%GenericParam, constants.%Generic.facet.8bd) [concrete = constants.%CallGenericMethod.specific_fn] diff --git a/toolchain/check/testdata/impl/use_assoc_const.carbon b/toolchain/check/testdata/impl/use_assoc_const.carbon index 52ecbb968e43..6f62d314ca1d 100644 --- a/toolchain/check/testdata/impl/use_assoc_const.carbon +++ b/toolchain/check/testdata/impl/use_assoc_const.carbon @@ -559,8 +559,6 @@ fn F() { // CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc] // CHECK:STDOUT: %impl.elem0.loc9_46: %.f1a = impl_witness_access constants.%impl_witness.01d, element0 [concrete = constants.%Op.c82] // CHECK:STDOUT: %bound_method.loc9_46.1: = bound_method %u.ref, %impl.elem0.loc9_46 -// CHECK:STDOUT: %i32.1: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] -// CHECK:STDOUT: %i32.2: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] // CHECK:STDOUT: %specific_fn.loc9_46: = specific_function %impl.elem0.loc9_46, @Op.2(constants.%int_32) [concrete = constants.%Op.specific_fn] // CHECK:STDOUT: %bound_method.loc9_46.2: = bound_method %u.ref, %specific_fn.loc9_46 // CHECK:STDOUT: %impl.elem0.loc9_48: %.be7 = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956] @@ -820,8 +818,6 @@ fn F() { // CHECK:STDOUT: %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba] // CHECK:STDOUT: %impl.elem0.loc11_34: %.f1a = impl_witness_access constants.%impl_witness.01d, element0 [concrete = constants.%Op.c82] // CHECK:STDOUT: %bound_method.loc11_34.1: = bound_method %u.ref, %impl.elem0.loc11_34 -// CHECK:STDOUT: %i32.1: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] -// CHECK:STDOUT: %i32.2: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] // CHECK:STDOUT: %specific_fn.loc11_34: = specific_function %impl.elem0.loc11_34, @Op.2(constants.%int_32) [concrete = constants.%Op.specific_fn] // CHECK:STDOUT: %bound_method.loc11_34.2: = bound_method %u.ref, %specific_fn.loc11_34 // CHECK:STDOUT: %impl.elem0.loc11_36: %.be7 = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956] @@ -1232,8 +1228,6 @@ fn F() { // CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] // CHECK:STDOUT: %impl.elem0.loc12_16: %.f1a = impl_witness_access constants.%impl_witness.01d, element0 [concrete = constants.%Op.c82] // CHECK:STDOUT: %bound_method.loc12_16.1: = bound_method %u.ref, %impl.elem0.loc12_16 -// CHECK:STDOUT: %i32.1: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] -// CHECK:STDOUT: %i32.2: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] // CHECK:STDOUT: %specific_fn.loc12_16: = specific_function %impl.elem0.loc12_16, @Op.2(constants.%int_32) [concrete = constants.%Op.specific_fn] // CHECK:STDOUT: %bound_method.loc12_16.2: = bound_method %u.ref, %specific_fn.loc12_16 // CHECK:STDOUT: %impl.elem0.loc12_18: %.be7 = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956] @@ -1255,8 +1249,6 @@ fn F() { // CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc] // CHECK:STDOUT: %impl.elem0.loc15_16: %.f1a = impl_witness_access constants.%impl_witness.01d, element0 [concrete = constants.%Op.c82] // CHECK:STDOUT: %bound_method.loc15_16.1: = bound_method %v.ref, %impl.elem0.loc15_16 -// CHECK:STDOUT: %i32.1: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] -// CHECK:STDOUT: %i32.2: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] // CHECK:STDOUT: %specific_fn.loc15_16: = specific_function %impl.elem0.loc15_16, @Op.2(constants.%int_32) [concrete = constants.%Op.specific_fn] // CHECK:STDOUT: %bound_method.loc15_16.2: = bound_method %v.ref, %specific_fn.loc15_16 // CHECK:STDOUT: %impl.elem0.loc15_18: %.be7 = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956] @@ -1404,10 +1396,6 @@ fn F() { // CHECK:STDOUT: %T.as_wit.iface0.loc25: = facet_access_witness constants.%T, element0 [symbolic = %T.as_wit.iface0.loc24_34.2 (constants.%T.as_wit.iface0)] // CHECK:STDOUT: %impl.elem1.loc25_11.1: @GenericCallF.%.loc25_11.2 (%.4d2) = impl_witness_access %T.as_wit.iface0.loc25, element1 [symbolic = %impl.elem1.loc25_11.2 (constants.%impl.elem1)] // CHECK:STDOUT: %u.ref: @GenericCallF.%impl.elem0.loc24_34.2 (%impl.elem0.d9c3a6.2) = name_ref u, %u -// CHECK:STDOUT: %as_wit.iface0.1: = facet_access_witness constants.%J.facet.085e97.2, element0 [symbolic = %T.as_wit.iface0.loc24_34.2 (constants.%T.as_wit.iface0)] -// CHECK:STDOUT: %impl.elem0.1: type = impl_witness_access constants.%T.as_wit.iface0, element0 [symbolic = %impl.elem0.loc24_34.2 (constants.%impl.elem0.d9c3a6.2)] -// CHECK:STDOUT: %as_wit.iface0.2: = facet_access_witness constants.%J.facet.085e97.2, element0 [symbolic = %T.as_wit.iface0.loc24_34.2 (constants.%T.as_wit.iface0)] -// CHECK:STDOUT: %impl.elem0.2: type = impl_witness_access constants.%T.as_wit.iface0, element0 [symbolic = %impl.elem0.loc24_34.2 (constants.%impl.elem0.d9c3a6.2)] // CHECK:STDOUT: %specific_impl_fn.loc25_11.1: = specific_impl_function %impl.elem1.loc25_11.1, @F.1(constants.%J.facet.085e97.2) [symbolic = %specific_impl_fn.loc25_11.2 (constants.%specific_impl_fn)] // CHECK:STDOUT: %.loc25_15: init @GenericCallF.%impl.elem0.loc24_34.2 (%impl.elem0.d9c3a6.2) = call %specific_impl_fn.loc25_11.1(%u.ref) // CHECK:STDOUT: %.loc25_16.1: @GenericCallF.%impl.elem0.loc24_34.2 (%impl.elem0.d9c3a6.2) = value_of_initializer %.loc25_15 @@ -1683,11 +1671,7 @@ fn F() { // CHECK:STDOUT: %impl.elem1.loc9_11.1: @GenericAddResult.%.loc9_11.2 (%.4d2) = impl_witness_access %T.as_wit.iface0.loc9_11, element1 [symbolic = %impl.elem1.loc9_11.2 (constants.%impl.elem1)] // CHECK:STDOUT: %u.ref.loc9_14: @GenericAddResult.%as_type.loc8_38.2 (%as_type.6b96b1.2) = name_ref u, %u // CHECK:STDOUT: %.loc9_15.1: %Add.type = converted constants.%as_type.6b96b1.2, constants.%impl.elem0.c57618.2 [symbolic = %impl.elem0.loc8_38.2 (constants.%impl.elem0.c57618.2)] -// CHECK:STDOUT: %as_wit.iface0.1: = facet_access_witness constants.%J.facet.085e97.2, element0 [symbolic = %T.as_wit.iface0.loc8_38.2 (constants.%T.as_wit.iface0)] -// CHECK:STDOUT: %impl.elem0.1: %Add.type = impl_witness_access constants.%T.as_wit.iface0, element0 [symbolic = %impl.elem0.loc8_38.2 (constants.%impl.elem0.c57618.2)] // CHECK:STDOUT: %.loc9_15.2: %Add.type = converted constants.%as_type.6b96b1.2, constants.%impl.elem0.c57618.2 [symbolic = %impl.elem0.loc8_38.2 (constants.%impl.elem0.c57618.2)] -// CHECK:STDOUT: %as_wit.iface0.2: = facet_access_witness constants.%J.facet.085e97.2, element0 [symbolic = %T.as_wit.iface0.loc8_38.2 (constants.%T.as_wit.iface0)] -// CHECK:STDOUT: %impl.elem0.2: %Add.type = impl_witness_access constants.%T.as_wit.iface0, element0 [symbolic = %impl.elem0.loc8_38.2 (constants.%impl.elem0.c57618.2)] // CHECK:STDOUT: %specific_impl_fn.loc9_11.1: = specific_impl_function %impl.elem1.loc9_11.1, @F(constants.%J.facet.085e97.2) [symbolic = %specific_impl_fn.loc9_11.2 (constants.%specific_impl_fn.5d8)] // CHECK:STDOUT: %.loc9_15.3: init @GenericAddResult.%as_type.loc8_38.2 (%as_type.6b96b1.2) = call %specific_impl_fn.loc9_11.1(%u.ref.loc9_14) // CHECK:STDOUT: %T.ref.loc9: %J.type = name_ref T, %T.loc8_21.1 [symbolic = %T.loc8_21.2 (constants.%T)] @@ -1698,11 +1682,7 @@ fn F() { // CHECK:STDOUT: %impl.elem1.loc9_20: @GenericAddResult.%.loc9_11.2 (%.4d2) = impl_witness_access %T.as_wit.iface0.loc9_20, element1 [symbolic = %impl.elem1.loc9_11.2 (constants.%impl.elem1)] // CHECK:STDOUT: %u.ref.loc9_23: @GenericAddResult.%as_type.loc8_38.2 (%as_type.6b96b1.2) = name_ref u, %u // CHECK:STDOUT: %.loc9_24.1: %Add.type = converted constants.%as_type.6b96b1.2, constants.%impl.elem0.c57618.2 [symbolic = %impl.elem0.loc8_38.2 (constants.%impl.elem0.c57618.2)] -// CHECK:STDOUT: %as_wit.iface0.3: = facet_access_witness constants.%J.facet.085e97.2, element0 [symbolic = %T.as_wit.iface0.loc8_38.2 (constants.%T.as_wit.iface0)] -// CHECK:STDOUT: %impl.elem0.3: %Add.type = impl_witness_access constants.%T.as_wit.iface0, element0 [symbolic = %impl.elem0.loc8_38.2 (constants.%impl.elem0.c57618.2)] // CHECK:STDOUT: %.loc9_24.2: %Add.type = converted constants.%as_type.6b96b1.2, constants.%impl.elem0.c57618.2 [symbolic = %impl.elem0.loc8_38.2 (constants.%impl.elem0.c57618.2)] -// CHECK:STDOUT: %as_wit.iface0.4: = facet_access_witness constants.%J.facet.085e97.2, element0 [symbolic = %T.as_wit.iface0.loc8_38.2 (constants.%T.as_wit.iface0)] -// CHECK:STDOUT: %impl.elem0.4: %Add.type = impl_witness_access constants.%T.as_wit.iface0, element0 [symbolic = %impl.elem0.loc8_38.2 (constants.%impl.elem0.c57618.2)] // CHECK:STDOUT: %specific_impl_fn.loc9_20: = specific_impl_function %impl.elem1.loc9_20, @F(constants.%J.facet.085e97.2) [symbolic = %specific_impl_fn.loc9_11.2 (constants.%specific_impl_fn.5d8)] // CHECK:STDOUT: %.loc9_24.3: init @GenericAddResult.%as_type.loc8_38.2 (%as_type.6b96b1.2) = call %specific_impl_fn.loc9_20(%u.ref.loc9_23) // CHECK:STDOUT: %as_wit.iface0.loc9_17.1: = facet_access_witness constants.%impl.elem0.c57618.2, element0 [symbolic = %as_wit.iface0.loc9_17.2 (constants.%as_wit.iface0)] @@ -1916,10 +1896,6 @@ fn F() { // CHECK:STDOUT: %impl.elem1.loc9_11.1: @GenericCallInterfaceQualified.%.loc9_11 (%.9ac) = impl_witness_access %T.as_wit.iface0.loc9, element1 [symbolic = %impl.elem1.loc9_11.2 (constants.%impl.elem1)] // CHECK:STDOUT: %bound_method.loc9_11: = bound_method %t.ref, %impl.elem1.loc9_11.1 // CHECK:STDOUT: %u.ref: @GenericCallInterfaceQualified.%impl.elem0.loc8_51.2 (%impl.elem0.d9c3a6.2) = name_ref u, %u -// CHECK:STDOUT: %as_wit.iface0.1: = facet_access_witness constants.%J.facet.085e97.2, element0 [symbolic = %T.as_wit.iface0.loc8_51.2 (constants.%T.as_wit.iface0)] -// CHECK:STDOUT: %impl.elem0.1: type = impl_witness_access constants.%T.as_wit.iface0, element0 [symbolic = %impl.elem0.loc8_51.2 (constants.%impl.elem0.d9c3a6.2)] -// CHECK:STDOUT: %as_wit.iface0.2: = facet_access_witness constants.%J.facet.085e97.2, element0 [symbolic = %T.as_wit.iface0.loc8_51.2 (constants.%T.as_wit.iface0)] -// CHECK:STDOUT: %impl.elem0.2: type = impl_witness_access constants.%T.as_wit.iface0, element0 [symbolic = %impl.elem0.loc8_51.2 (constants.%impl.elem0.d9c3a6.2)] // CHECK:STDOUT: %specific_impl_fn.loc9_11.1: = specific_impl_function %impl.elem1.loc9_11.1, @G(constants.%J.facet.085e97.2) [symbolic = %specific_impl_fn.loc9_11.2 (constants.%specific_impl_fn)] // CHECK:STDOUT: %bound_method.loc9_19: = bound_method %t.ref, %specific_impl_fn.loc9_11.1 // CHECK:STDOUT: %.loc9_19: init @GenericCallInterfaceQualified.%impl.elem0.loc8_51.2 (%impl.elem0.d9c3a6.2) = call %bound_method.loc9_19(%t.ref, %u.ref) @@ -2109,10 +2085,10 @@ fn F() { // CHECK:STDOUT: %J.facet: %J.type = facet_value %T.as_type.loc8_45.2, (%T.as_wit.iface0.loc26_11.2) [symbolic = %J.facet (constants.%J.facet.869)] // CHECK:STDOUT: %.loc26_11.2: type = fn_type_with_self_type constants.%F.type, %J.facet [symbolic = %.loc26_11.2 (constants.%.861)] // CHECK:STDOUT: %impl.elem1.loc26_11.2: @GenericCallFI32.%.loc26_11.2 (%.861) = impl_witness_access %T.as_wit.iface0.loc26_11.2, element1 [symbolic = %impl.elem1.loc26_11.2 (constants.%impl.elem1)] -// CHECK:STDOUT: %impl.elem0.3: type = impl_witness_access %T.as_wit.iface0.loc26_11.2, element0 [symbolic = %impl.elem0.3 (constants.%impl.elem0.37e)] +// CHECK:STDOUT: %impl.elem0.1: type = impl_witness_access %T.as_wit.iface0.loc26_11.2, element0 [symbolic = %impl.elem0.1 (constants.%impl.elem0.37e)] // CHECK:STDOUT: %specific_impl_fn.loc26_11.2: = specific_impl_function %impl.elem1.loc26_11.2, @F(%J.facet) [symbolic = %specific_impl_fn.loc26_11.2 (constants.%specific_impl_fn)] -// CHECK:STDOUT: %require_complete.loc26_15: = require_complete_type @GenericCallFI32.%impl.elem0.3 (%impl.elem0.37e) [symbolic = %require_complete.loc26_15 (constants.%require_complete.8bd)] -// CHECK:STDOUT: %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%impl.elem0.3)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.820)] +// CHECK:STDOUT: %require_complete.loc26_15: = require_complete_type @GenericCallFI32.%impl.elem0.1 (%impl.elem0.37e) [symbolic = %require_complete.loc26_15 (constants.%require_complete.8bd)] +// CHECK:STDOUT: %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%impl.elem0.1)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.820)] // CHECK:STDOUT: %require_complete.loc26_14: = require_complete_type @GenericCallFI32.%ImplicitAs.type (%ImplicitAs.type.820) [symbolic = %require_complete.loc26_14 (constants.%require_complete.1ce)] // CHECK:STDOUT: // CHECK:STDOUT: fn[%T.patt.loc8_20.1: %J_where.type](%t.param_patt: @GenericCallFI32.%T.as_type.loc8_45.2 (%T.as_type)) -> %i32 { @@ -2124,13 +2100,9 @@ fn F() { // CHECK:STDOUT: %T.as_wit.iface0.loc26_11.1: = facet_access_witness constants.%T, element0 [symbolic = %T.as_wit.iface0.loc26_11.2 (constants.%T.as_wit.iface0)] // CHECK:STDOUT: %impl.elem1.loc26_11.1: @GenericCallFI32.%.loc26_11.2 (%.861) = impl_witness_access %T.as_wit.iface0.loc26_11.1, element1 [symbolic = %impl.elem1.loc26_11.2 (constants.%impl.elem1)] // CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2] -// CHECK:STDOUT: %as_wit.iface0.1: = facet_access_witness constants.%J.facet.869, element0 [symbolic = %T.as_wit.iface0.loc26_11.2 (constants.%T.as_wit.iface0)] -// CHECK:STDOUT: %impl.elem0.1: type = impl_witness_access constants.%T.as_wit.iface0, element0 [symbolic = %impl.elem0.3 (constants.%impl.elem0.37e)] -// CHECK:STDOUT: %as_wit.iface0.2: = facet_access_witness constants.%J.facet.869, element0 [symbolic = %T.as_wit.iface0.loc26_11.2 (constants.%T.as_wit.iface0)] -// CHECK:STDOUT: %impl.elem0.2: type = impl_witness_access constants.%T.as_wit.iface0, element0 [symbolic = %impl.elem0.3 (constants.%impl.elem0.37e)] // CHECK:STDOUT: %specific_impl_fn.loc26_11.1: = specific_impl_function %impl.elem1.loc26_11.1, @F(constants.%J.facet.869) [symbolic = %specific_impl_fn.loc26_11.2 (constants.%specific_impl_fn)] -// CHECK:STDOUT: %.loc26_14: @GenericCallFI32.%impl.elem0.3 (%impl.elem0.37e) = converted %int_2, [concrete = ] -// CHECK:STDOUT: %.loc26_15: init @GenericCallFI32.%impl.elem0.3 (%impl.elem0.37e) = call %specific_impl_fn.loc26_11.1() [concrete = ] +// CHECK:STDOUT: %.loc26_14: @GenericCallFI32.%impl.elem0.1 (%impl.elem0.37e) = converted %int_2, [concrete = ] +// CHECK:STDOUT: %.loc26_15: init @GenericCallFI32.%impl.elem0.1 (%impl.elem0.37e) = call %specific_impl_fn.loc26_11.1() [concrete = ] // CHECK:STDOUT: %.loc26_16: %i32 = converted %.loc26_15, [concrete = ] // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/sem_ir/inst_kind.h b/toolchain/sem_ir/inst_kind.h index fb02d48e2f59..65e7ef799256 100644 --- a/toolchain/sem_ir/inst_kind.h +++ b/toolchain/sem_ir/inst_kind.h @@ -86,6 +86,19 @@ enum class InstConstantKind : int8_t { Unique, }; +// Whether constant evaluation of an instruction needs the instruction to have +// been created and allocated an InstId, or only needs the instruction operands. +enum class InstConstantNeedsInstIdKind : int8_t { + // This instruction kind doesn't need an InstId to be evaluated. + No, + // This instruction needs an InstId during evaluation, but doesn't need the + // instruction to persist after evaluation. + DuringEvaluation, + // This instruction needs a permanent instruction ID, for example because that + // instruction ID can appear in the constant result of evaluation. + Permanent, +}; + // Whether an instruction is a terminator or part of the terminator sequence. // The instructions in a block appear in the order NotTerminator, then // TerminatorSequence, then Terminator, which is also the numerical order of @@ -123,7 +136,10 @@ class InstKind : public CARBON_ENUM_BASE(InstKind) { llvm::StringLiteral ir_name; InstIsType is_type = InstIsType::Never; InstConstantKind constant_kind = InstConstantKind::Indirect; - bool constant_needs_inst_id = constant_kind == InstConstantKind::Unique; + InstConstantNeedsInstIdKind constant_needs_inst_id = + constant_kind == InstConstantKind::Unique + ? InstConstantNeedsInstIdKind::Permanent + : InstConstantNeedsInstIdKind::No; TerminatorKind terminator_kind = TerminatorKind::NotTerminator; bool is_lowered = true; bool deduce_through = false; @@ -173,7 +189,7 @@ class InstKind : public CARBON_ENUM_BASE(InstKind) { // location, for example for diagnostics or for newly-created instructions, // and for instructions whose evaluation needs to inspect the original form of // its operands. - auto constant_needs_inst_id() const -> bool { + auto constant_needs_inst_id() const -> InstConstantNeedsInstIdKind { return definition_info(*this).constant_needs_inst_id; } @@ -192,6 +208,12 @@ class InstKind : public CARBON_ENUM_BASE(InstKind) { return definition_info(*this).deduce_through; } + // Returns true if this instruction has scoped cleanup associated, typically a + // destructor. + constexpr auto has_cleanup() const -> bool { + return definition_info(*this).has_cleanup; + } + private: // Returns the DefinitionInfo for the kind. static auto definition_info(InstKind kind) -> const DefinitionInfo&; @@ -232,7 +254,7 @@ class InstKind::Definition : public InstKind { } // Returns whether constant evaluation of this instruction needs an InstId. - constexpr auto constant_needs_inst_id() const -> bool { + constexpr auto constant_needs_inst_id() const -> InstConstantNeedsInstIdKind { return info_.constant_needs_inst_id; } diff --git a/toolchain/sem_ir/typed_insts.h b/toolchain/sem_ir/typed_insts.h index 9402fa0d3d33..94f589afe74e 100644 --- a/toolchain/sem_ir/typed_insts.h +++ b/toolchain/sem_ir/typed_insts.h @@ -188,7 +188,7 @@ struct ArrayType { {.ir_name = "array_type", .is_type = InstIsType::Always, .constant_kind = InstConstantKind::Conditional, - .constant_needs_inst_id = true, + .constant_needs_inst_id = InstConstantNeedsInstIdKind::DuringEvaluation, .deduce_through = true}); TypeId type_id; @@ -773,7 +773,7 @@ struct FloatType { {.ir_name = "float_type", .is_type = InstIsType::Always, .constant_kind = InstConstantKind::Conditional, - .constant_needs_inst_id = true, + .constant_needs_inst_id = InstConstantNeedsInstIdKind::DuringEvaluation, .deduce_through = true}); TypeId type_id; @@ -924,7 +924,8 @@ struct ImplWitnessAccess { {.ir_name = "impl_witness_access", .is_type = InstIsType::Maybe, .constant_kind = InstConstantKind::SymbolicOnly, - .constant_needs_inst_id = true, + .constant_needs_inst_id = + InstConstantNeedsInstIdKind::DuringEvaluation, .is_lowered = false}); TypeId type_id; @@ -1108,7 +1109,7 @@ struct IntType { {.ir_name = "int_type", .is_type = InstIsType::Always, .constant_kind = InstConstantKind::Conditional, - .constant_needs_inst_id = true, + .constant_needs_inst_id = InstConstantNeedsInstIdKind::DuringEvaluation, .deduce_through = true}); TypeId type_id; @@ -1133,7 +1134,8 @@ struct LookupImplWitness { InstKind::LookupImplWitness.Define( {.ir_name = "lookup_impl_witness", .constant_kind = InstConstantKind::SymbolicOnly, - .constant_needs_inst_id = true, + .constant_needs_inst_id = + InstConstantNeedsInstIdKind::DuringEvaluation, .is_lowered = false}); // Always the type of the builtin `WitnessType` singleton instruction. @@ -1337,7 +1339,8 @@ struct RequireCompleteType { InstKind::RequireCompleteType.Define( {.ir_name = "require_complete_type", .constant_kind = InstConstantKind::SymbolicOnly, - .constant_needs_inst_id = true, + .constant_needs_inst_id = + InstConstantNeedsInstIdKind::DuringEvaluation, .is_lowered = false}); // Always the builtin witness type. TypeId type_id; @@ -1477,7 +1480,8 @@ struct SpecificFunction { static constexpr auto Kind = InstKind::SpecificFunction.Define( {.ir_name = "specific_function", .constant_kind = InstConstantKind::Conditional, - .constant_needs_inst_id = true}); + // InstId is added to definitions_required_by_use. + .constant_needs_inst_id = InstConstantNeedsInstIdKind::Permanent}); // Always the builtin SpecificFunctionType. TypeId type_id; @@ -1514,7 +1518,8 @@ struct SpecificImplFunction { InstKind::SpecificImplFunction.Define( {.ir_name = "specific_impl_function", .constant_kind = InstConstantKind::SymbolicOnly, - .constant_needs_inst_id = true}); + // InstId is added to definitions_required_by_use. + .constant_needs_inst_id = InstConstantNeedsInstIdKind::Permanent}); // Always the builtin SpecificFunctionType. TypeId type_id;