Преглед изворни кода

Use earlier `require` decls inside a named constraint to provide witnesses for `Self` (#6915)

Performing a lookup against `Self` inside the definition of the named
constraint leads to cycles, as described in the document [Self
contradictions in Named
Constraints](https://docs.google.com/document/d/17rn2XmME8o2MM4OJqatSVuMa1iYZ1PAgcNrf0PXR9Q4/edit?tab=t.0).
To prevent those cycles, this change introduces a large refactoring of
impl lookup.

The impl lookup done inside eval is reduced to only performing
monomorphization. That is it:
- Only looks for an provides final witnesses.
- Is not allowed to identify the facet type of the query self.
- Returns either a final witness or None (or an error)

The paths for finding non-final witnesses are now done outside of eval,
directly in the initial `LookupImplWitness()` function. If no final
witness it found through eval, the resulting non-final
`LookupImplWitness` instruction witness is returned. It does not produce
cycles to identify the facet type of query self outside of eval, since
that does not result in repeating the identification when resolving
specifics of the named constraint or require decl.

Move the ArrayStack for Context::require_impls_stack into a new class
which tracks a NamedConstraintId (or InterfaceId) for each frame of
RequireImplsIds, so that in type completion we always can find the
correct frame for a given named constraint which is still being defined,
in order to find the RequireImplsIds in the in-progress definition.
Dana Jansens пре 1 месец
родитељ
комит
d6be20641c
66 измењених фајлова са 1428 додато и 887 уклоњено
  1. 2 0
      toolchain/check/BUILD
  2. 10 9
      toolchain/check/check_unit.cpp
  3. 9 5
      toolchain/check/context.h
  4. 1 1
      toolchain/check/convert.cpp
  5. 14 6
      toolchain/check/custom_witness.cpp
  6. 6 2
      toolchain/check/custom_witness.h
  7. 21 34
      toolchain/check/eval_inst.cpp
  8. 14 1
      toolchain/check/generic.cpp
  9. 3 3
      toolchain/check/handle_interface.cpp
  10. 3 3
      toolchain/check/handle_named_constraint.cpp
  11. 494 298
      toolchain/check/impl_lookup.cpp
  12. 12 62
      toolchain/check/impl_lookup.h
  13. 36 0
      toolchain/check/require_impls_stack.cpp
  14. 44 0
      toolchain/check/require_impls_stack.h
  15. 18 18
      toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon
  16. 2 2
      toolchain/check/testdata/class/generic/basic.carbon
  17. 3 3
      toolchain/check/testdata/class/generic/member_access.carbon
  18. 3 3
      toolchain/check/testdata/class/generic/member_type.carbon
  19. 4 0
      toolchain/check/testdata/deduce/binding_pattern.carbon
  20. 8 8
      toolchain/check/testdata/eval/aggregates.carbon
  21. 2 2
      toolchain/check/testdata/facet/convert_facet_value_to_narrowed_facet_type.carbon
  22. 2 2
      toolchain/check/testdata/facet/convert_facet_value_value_to_blanket_impl.carbon
  23. 11 11
      toolchain/check/testdata/facet/convert_facet_value_value_to_generic_facet_value_value.carbon
  24. 2 0
      toolchain/check/testdata/facet/fail_convert_facet_value_to_missing_impl.carbon
  25. 0 33
      toolchain/check/testdata/facet/fail_incomplete.carbon
  26. 216 0
      toolchain/check/testdata/facet/partially_identified.carbon
  27. 0 66
      toolchain/check/testdata/facet/require_constrains_self.carbon
  28. 17 0
      toolchain/check/testdata/facet/require_invalid.carbon
  29. 29 38
      toolchain/check/testdata/for/actual.carbon
  30. 4 4
      toolchain/check/testdata/function/generic/call.carbon
  31. 4 4
      toolchain/check/testdata/function/generic/deduce.carbon
  32. 2 2
      toolchain/check/testdata/function/generic/indirect_generic_type.carbon
  33. 3 3
      toolchain/check/testdata/function/generic/resolve_used.carbon
  34. 2 2
      toolchain/check/testdata/function/generic/type_param.carbon
  35. 2 2
      toolchain/check/testdata/function/generic/type_param_scope.carbon
  36. 11 7
      toolchain/check/testdata/generic/dot_self_symbolic_type.carbon
  37. 6 0
      toolchain/check/testdata/generic/template/unimplemented.carbon
  38. 2 2
      toolchain/check/testdata/generic/template_dependence.carbon
  39. 5 5
      toolchain/check/testdata/impl/error_recovery.carbon
  40. 4 4
      toolchain/check/testdata/impl/impl_thunk.carbon
  41. 4 4
      toolchain/check/testdata/impl/import_builtin_call.carbon
  42. 37 79
      toolchain/check/testdata/impl/import_generic.carbon
  43. 16 38
      toolchain/check/testdata/impl/import_self_specific.carbon
  44. 1 3
      toolchain/check/testdata/impl/incomplete.carbon
  45. 3 3
      toolchain/check/testdata/impl/lookup/generic.carbon
  46. 5 5
      toolchain/check/testdata/impl/lookup/impl_forall.carbon
  47. 8 6
      toolchain/check/testdata/impl/lookup/specialization_with_symbolic_rewrite.carbon
  48. 44 0
      toolchain/check/testdata/impl/lookup/use_impl_from_definition.carbon
  49. 31 0
      toolchain/check/testdata/impl/name_lookup_in_impl_definition.carbon
  50. 2 2
      toolchain/check/testdata/interface/as_type_of_type.carbon
  51. 8 6
      toolchain/check/testdata/interface/compound_member_access.carbon
  52. 3 3
      toolchain/check/testdata/interface/fail_assoc_const_alias.carbon
  53. 3 0
      toolchain/check/testdata/interface/fail_member_lookup.carbon
  54. 2 2
      toolchain/check/testdata/interface/fail_todo_define_default_fn_out_of_line.carbon
  55. 2 0
      toolchain/check/testdata/interface/generic.carbon
  56. 3 3
      toolchain/check/testdata/interface/generic_method.carbon
  57. 2 2
      toolchain/check/testdata/interface/member_lookup.carbon
  58. 5 5
      toolchain/check/testdata/named_constraint/empty_generic.carbon
  59. 87 26
      toolchain/check/testdata/named_constraint/incomplete.carbon
  60. 85 36
      toolchain/check/type_completion.cpp
  61. 16 1
      toolchain/check/type_completion.h
  62. 0 1
      toolchain/diagnostics/kind.def
  63. 5 5
      toolchain/lower/testdata/impl/import_facet.carbon
  64. 10 1
      toolchain/sem_ir/facet_type_info.cpp
  65. 10 1
      toolchain/sem_ir/facet_type_info.h
  66. 5 10
      toolchain/sem_ir/typed_insts.h

+ 2 - 0
toolchain/check/BUILD

@@ -66,6 +66,7 @@ cc_library(
         "pattern.cpp",
         "pattern_match.cpp",
         "pointer_dereference.cpp",
+        "require_impls_stack.cpp",
         "return.cpp",
         "scope_stack.cpp",
         "subst.cpp",
@@ -134,6 +135,7 @@ cc_library(
         "pending_block.h",
         "pointer_dereference.h",
         "region_stack.h",
+        "require_impls_stack.h",
         "return.h",
         "scope_index.h",
         "scope_stack.h",

+ 10 - 9
toolchain/check/check_unit.cpp

@@ -530,20 +530,21 @@ auto CheckUnit::CheckPoisonedConcreteImplLookupQueries() -> void {
   auto poisoned_queries =
       std::exchange(context_.poisoned_concrete_impl_lookup_queries(), {});
   for (const auto& poison : poisoned_queries) {
-    auto witness_result = EvalLookupSingleImplWitness(
-        context_, poison.loc_id, poison.query, poison.query.query_self_inst_id,
+    auto found_witness_id = EvalLookupSingleFinalWitness(
+        context_, poison.loc_id, poison.query, SemIR::InstId::None,
         EvalImplLookupMode::RecheckPoisonedLookup);
-    CARBON_CHECK(witness_result.has_final_value());
-    auto found_witness_id = witness_result.final_witness();
-    if (found_witness_id == SemIR::ErrorInst::InstId) {
+    CARBON_CHECK(found_witness_id.has_value());
+    if (found_witness_id == SemIR::ErrorInst::ConstantId) {
       // Errors may have been diagnosed with the impl used in the poisoned query
       // in the meantime (such as a missing definition).
       continue;
     }
-    if (found_witness_id != poison.impl_witness) {
-      auto witness_to_impl_id = [&](SemIR::InstId witness_id) {
+    if (found_witness_id != poison.witness_id) {
+      auto witness_to_impl_id = [&](SemIR::ConstantId witness_id) {
+        // TODO: Add and use constant_values().GetAs<SemIR::FacetType>().
+        auto inst_id = context_.constant_values().GetInstId(witness_id);
         auto table_id = context_.insts()
-                            .GetAs<SemIR::ImplWitness>(witness_id)
+                            .GetAs<SemIR::ImplWitness>(inst_id)
                             .witness_table_id;
         return context_.insts()
             .GetAs<SemIR::ImplWitnessTable>(table_id)
@@ -555,7 +556,7 @@ auto CheckUnit::CheckPoisonedConcreteImplLookupQueries() -> void {
       auto bad_impl_id = witness_to_impl_id(found_witness_id);
       const auto& bad_impl = context_.impls().Get(bad_impl_id);
 
-      auto prev_impl_id = witness_to_impl_id(poison.impl_witness);
+      auto prev_impl_id = witness_to_impl_id(poison.witness_id);
       const auto& prev_impl = context_.impls().Get(prev_impl_id);
 
       CARBON_DIAGNOSTIC(

+ 9 - 5
toolchain/check/context.h

@@ -25,6 +25,7 @@
 #include "toolchain/check/node_stack.h"
 #include "toolchain/check/param_and_arg_refs_stack.h"
 #include "toolchain/check/region_stack.h"
+#include "toolchain/check/require_impls_stack.h"
 #include "toolchain/check/scope_stack.h"
 #include "toolchain/diagnostics/emitter.h"
 #include "toolchain/parse/node_ids.h"
@@ -125,7 +126,7 @@ class Context {
     return field_decls_stack_;
   }
 
-  auto require_impls_stack() -> ArrayStack<SemIR::RequireImplsId>& {
+  auto require_impls_stack() -> RequireImplsStack& {
     return require_impls_stack_;
   }
 
@@ -221,6 +222,9 @@ class Context {
     SemIR::ConstantId query_facet_type_const_id;
     // The location of the impl being looked at for the stack entry.
     SemIR::InstId impl_loc = SemIR::InstId::None;
+    // TODO: If we make a proper stack class, we only need one `diagnosed_cycle`
+    // field, which resets to false when the stack becomes empty.
+    bool diagnosed_cycle = false;
   };
   auto impl_lookup_stack() -> llvm::SmallVector<ImplLookupStackEntry>& {
     return impl_lookup_stack_;
@@ -229,7 +233,7 @@ class Context {
   // A map from a (self, interface) pair to a final witness.
   using ImplLookupCacheKey =
       std::pair<SemIR::ConstantId, SemIR::SpecificInterfaceId>;
-  using ImplLookupCacheMap = Map<ImplLookupCacheKey, SemIR::InstId>;
+  using ImplLookupCacheMap = Map<ImplLookupCacheKey, SemIR::ConstantId>;
   auto impl_lookup_cache() -> ImplLookupCacheMap& { return impl_lookup_cache_; }
 
   // An impl lookup query that resulted in a concrete witness from finding an
@@ -240,8 +244,8 @@ class Context {
     SemIR::LocId loc_id;
     // The query for a witness of an impl for an interface.
     SemIR::LookupImplWitness query;
-    // The resulting ImplWitness.
-    SemIR::InstId impl_witness;
+    // The resulting final witness.
+    SemIR::ConstantId witness_id;
   };
   auto poisoned_concrete_impl_lookup_queries()
       -> llvm::SmallVector<PoisonedConcreteImplLookupQuery>& {
@@ -425,7 +429,7 @@ class Context {
 
   // The stack of RequireImpls for in-progress Interface and Constraint
   // definitions.
-  ArrayStack<SemIR::RequireImplsId> require_impls_stack_;
+  RequireImplsStack require_impls_stack_;
 
   // The stack used for qualified declaration name construction.
   DeclNameStack decl_name_stack_;

+ 1 - 1
toolchain/check/convert.cpp

@@ -1512,7 +1512,7 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id,
     // by finding impl witnesses for the target FacetType.
     auto lookup_result = LookupImplWitness(
         context, loc_id, sem_ir.constant_values().Get(type_inst_id),
-        sem_ir.types().GetConstantId(target.type_id));
+        sem_ir.types().GetConstantId(target.type_id), target.diagnose);
     if (lookup_result.has_value()) {
       if (lookup_result.has_error_value()) {
         return SemIR::ErrorInst::InstId;

+ 14 - 6
toolchain/check/custom_witness.cpp

@@ -377,7 +377,7 @@ static auto TypeCanDestroy(Context& context,
 static auto MakeDestroyWitness(
     Context& context, SemIR::LocId loc_id,
     SemIR::ConstantId query_self_const_id,
-    SemIR::SpecificInterfaceId query_specific_interface_id)
+    SemIR::SpecificInterfaceId query_specific_interface_id, bool build_witness)
     -> std::optional<SemIR::InstId> {
   auto query_specific_interface =
       context.specific_interfaces().Get(query_specific_interface_id);
@@ -387,6 +387,10 @@ static auto MakeDestroyWitness(
     return std::nullopt;
   }
 
+  if (!build_witness) {
+    return SemIR::InstId::None;
+  }
+
   if (query_self_const_id.is_symbolic()) {
     return SemIR::InstId::None;
   }
@@ -407,7 +411,7 @@ static auto MakeDestroyWitness(
 static auto MakeIntFitsInWitness(
     Context& context, SemIR::LocId loc_id,
     SemIR::ConstantId query_self_const_id,
-    SemIR::SpecificInterfaceId query_specific_interface_id)
+    SemIR::SpecificInterfaceId query_specific_interface_id, bool build_witness)
     -> std::optional<SemIR::InstId> {
   auto query_specific_interface =
       context.specific_interfaces().Get(query_specific_interface_id);
@@ -470,6 +474,10 @@ static auto MakeIntFitsInWitness(
     return std::nullopt;
   }
 
+  if (!build_witness) {
+    return SemIR::InstId::None;
+  }
+
   return BuildCustomWitness(context, loc_id, query_self_const_id,
                             query_specific_interface_id, {});
 }
@@ -477,15 +485,15 @@ static auto MakeIntFitsInWitness(
 auto LookupCustomWitness(Context& context, SemIR::LocId loc_id,
                          CoreInterface core_interface,
                          SemIR::ConstantId query_self_const_id,
-                         SemIR::SpecificInterfaceId query_specific_interface_id)
-    -> std::optional<SemIR::InstId> {
+                         SemIR::SpecificInterfaceId query_specific_interface_id,
+                         bool build_witness) -> std::optional<SemIR::InstId> {
   switch (core_interface) {
     case CoreInterface::Destroy:
       return MakeDestroyWitness(context, loc_id, query_self_const_id,
-                                query_specific_interface_id);
+                                query_specific_interface_id, build_witness);
     case CoreInterface::IntFitsIn:
       return MakeIntFitsInWitness(context, loc_id, query_self_const_id,
-                                  query_specific_interface_id);
+                                  query_specific_interface_id, build_witness);
     case CoreInterface::Copy:
     case CoreInterface::CppUnsafeDeref:
     case CoreInterface::Default:

+ 6 - 2
toolchain/check/custom_witness.h

@@ -39,11 +39,15 @@ auto GetCoreInterface(Context& context, SemIR::InterfaceId interface_id)
 // Returns a witness for a `CoreInterface` `CustomWitness`. A return value of
 // `None` indicates a non-final witness should be produced, while `std::nullopt`
 // indicates the query is final and no witness can be produced.
+//
+// If `build_witness` is false, this function always returns `None` as the
+// witness, whether it would be final or not. It is used to indicate the
+// presence of such a witness without adding instructions for it.
 auto LookupCustomWitness(Context& context, SemIR::LocId loc_id,
                          CoreInterface core_interface,
                          SemIR::ConstantId query_self_const_id,
-                         SemIR::SpecificInterfaceId query_specific_interface_id)
-    -> std::optional<SemIR::InstId>;
+                         SemIR::SpecificInterfaceId query_specific_interface_id,
+                         bool build_witness) -> std::optional<SemIR::InstId>;
 
 }  // namespace Carbon::Check
 

+ 21 - 34
toolchain/check/eval_inst.cpp

@@ -281,48 +281,35 @@ auto EvalConstantInst(Context& /*context*/, SemIR::FunctionDecl inst)
 
 auto EvalConstantInst(Context& context, SemIR::InstId inst_id,
                       SemIR::LookupImplWitness inst) -> ConstantEvalResult {
+  // If the monomorphized query self is a FacetValue, we may get a witness from
+  // it under limited circumstances. If no final witness is found though, we
+  // don't need to preserve it for future evaluations, so we strip it from the
+  // LookupImplWitness instruction to reduce the number of distinct constant
+  // values.
+  auto self_facet_value_inst_id = SemIR::InstId::None;
+  if (auto facet_value = context.insts().TryGetAs<SemIR::FacetValue>(
+          inst.query_self_inst_id)) {
+    self_facet_value_inst_id =
+        std::exchange(inst.query_self_inst_id, facet_value->type_inst_id);
+  }
+
   // The self value is canonicalized in order to produce a canonical
   // LookupImplWitness instruction, avoiding multiple constant values for
   // `<facet value>` and `<facet value>` as type, which always have the same
   // lookup result.
-  auto self_facet_value_inst_id =
+  inst.query_self_inst_id =
       GetCanonicalFacetOrTypeValue(context, inst.query_self_inst_id);
 
-  // When we look for a witness in the (facet) type of self, we may get a
-  // concrete witness from a `FacetValue` (which is `self_facet_value_inst_id`)
-  // in which case this instruction evaluates to that witness.
-  //
-  // If we only get a symbolic witness result though, then this instruction
-  // evaluates to a `LookupImplWitness`. Since there was no concrete result in
-  // the `FacetValue`, we don't need to preserve it. By looking through the
-  // `FacetValue` at the type value it wraps to generate a more canonical value
-  // for a symbolic `LookupImplWitness`. This makes us produce the same constant
-  // value for symbolic lookups in `FacetValue(T)` and `T`, since they will
-  // always have the same lookup result later, when `T` is replaced in a
-  // specific by something that can provide a concrete witness.
-  if (auto facet_value = context.insts().TryGetAs<SemIR::FacetValue>(
-          self_facet_value_inst_id)) {
-    inst.query_self_inst_id =
-        GetCanonicalFacetOrTypeValue(context, facet_value->type_inst_id);
-  } else {
-    inst.query_self_inst_id = self_facet_value_inst_id;
-  }
-
-  auto result = EvalLookupSingleImplWitness(context, SemIR::LocId(inst_id),
-                                            inst, self_facet_value_inst_id,
-                                            EvalImplLookupMode::Normal);
-  if (!result.has_value()) {
-    // We use NotConstant to communicate back to impl lookup that the lookup
-    // failed. This can not happen for a deferred symbolic lookup in a generic
-    // eval block, since we only add the deferred lookup instruction (being
-    // evaluated here) to the SemIR if the lookup succeeds.
-    return ConstantEvalResult::NotConstant;
+  auto witness_id = EvalLookupSingleFinalWitness(context, SemIR::LocId(inst_id),
+                                                 inst, self_facet_value_inst_id,
+                                                 EvalImplLookupMode::Normal);
+  if (witness_id == SemIR::ErrorInst::ConstantId) {
+    return ConstantEvalResult::Error;
   }
-  if (result.has_final_value()) {
-    return ConstantEvalResult::Existing(
-        context.constant_values().Get(result.final_witness()));
+  if (witness_id.has_value()) {
+    return ConstantEvalResult::Existing(witness_id);
   }
-
+  // Try again when the query is modified by a specific.
   return ConstantEvalResult::NewSamePhase(inst);
 }
 

+ 14 - 1
toolchain/check/generic.cpp

@@ -147,8 +147,21 @@ class RebuildGenericConstantInEvalBlockCallbacks : public SubstInstCallbacks {
 
   auto ReuseUnchanged(SemIR::InstId orig_inst_id) -> SemIR::InstId override {
     auto inst = context().insts().Get(orig_inst_id);
+
+    auto const_id = context().constant_values().Get(orig_inst_id);
+    const auto& symbolic =
+        context().constant_values().GetSymbolicConstant(const_id);
+    // Template actions are inserted into the eval block directly, instead of
+    // adding a new instruction, in `AddTemplateActionToEvalBlock`. This means
+    // any instruction that is symbolic because it contains a template action as
+    // an operand would Rebuild that operand with the same instruction. Then the
+    // dependent instruction would be reused unchanged.
+    bool is_template =
+        symbolic.dependence == SemIR::ConstantDependence::Template;
+
     CARBON_CHECK(
-        (inst.IsOneOf<SemIR::SymbolicBinding, SemIR::SymbolicBindingPattern>()),
+        is_template || (inst.IsOneOf<SemIR::SymbolicBinding,
+                                     SemIR::SymbolicBindingPattern>()),
         "Instruction {0} has symbolic constant value but no symbolic operands",
         inst);
 

+ 3 - 3
toolchain/check/handle_interface.cpp

@@ -184,7 +184,7 @@ auto HandleParseNode(Context& context,
       context.inst_block_stack().PeekOrAdd();
 
   context.inst_block_stack().Push();
-  context.require_impls_stack().PushArray();
+  context.require_impls_stack().Push(interface_id);
   // We use the arg stack to build the witness table type.
   context.args_type_info_stack().Push();
 
@@ -213,8 +213,8 @@ auto HandleParseNode(Context& context, Parse::InterfaceDefinitionId /*node_id*/)
   auto associated_entities_id = context.args_type_info_stack().Pop();
 
   auto require_impls_block_id = context.require_impls_blocks().Add(
-      context.require_impls_stack().PeekArray());
-  context.require_impls_stack().PopArray();
+      context.require_impls_stack().PeekTop());
+  context.require_impls_stack().Pop();
 
   auto& interface_info = context.interfaces().Get(interface_id);
   if (!interface_info.associated_entities_id.has_value()) {

+ 3 - 3
toolchain/check/handle_named_constraint.cpp

@@ -184,7 +184,7 @@ auto HandleParseNode(Context& context,
   constraint_info.body_block_with_self_id =
       context.inst_block_stack().PeekOrAdd();
 
-  context.require_impls_stack().PushArray();
+  context.require_impls_stack().Push(named_constraint_id);
 
   context.node_stack().Push(node_id, named_constraint_id);
   return true;
@@ -199,8 +199,8 @@ auto HandleParseNode(Context& context,
   context.inst_block_stack().Pop();
 
   auto require_impls_block_id = context.require_impls_blocks().Add(
-      context.require_impls_stack().PeekArray());
-  context.require_impls_stack().PopArray();
+      context.require_impls_stack().PeekTop());
+  context.require_impls_stack().Pop();
 
   auto& constraint_info = context.named_constraints().Get(named_constraint_id);
   if (!constraint_info.complete) {

+ 494 - 298
toolchain/check/impl_lookup.cpp

@@ -158,10 +158,9 @@ static auto FindAssociatedImportIRs(
 
 // Returns true if a cycle was found and diagnosed.
 static auto FindAndDiagnoseImplLookupCycle(
-    Context& context,
-    const llvm::SmallVector<Context::ImplLookupStackEntry>& stack,
+    Context& context, llvm::SmallVector<Context::ImplLookupStackEntry>& stack,
     SemIR::LocId loc_id, SemIR::ConstantId query_self_const_id,
-    SemIR::ConstantId query_facet_type_const_id) -> bool {
+    SemIR::ConstantId query_facet_type_const_id, bool diagnose) -> bool {
   // Deduction of the interface parameters can do further impl lookups, and we
   // need to ensure we terminate.
   //
@@ -177,22 +176,26 @@ static auto FindAndDiagnoseImplLookupCycle(
   for (auto [i, entry] : llvm::enumerate(stack)) {
     if (entry.query_self_const_id == query_self_const_id &&
         entry.query_facet_type_const_id == query_facet_type_const_id) {
-      auto facet_type_type_id =
-          context.types().GetTypeIdForTypeConstantId(query_facet_type_const_id);
-      CARBON_DIAGNOSTIC(ImplLookupCycle, Error,
-                        "cycle found in search for impl of {0} for type {1}",
-                        SemIR::TypeId, SemIR::TypeId);
-      auto builder = context.emitter().Build(
-          loc_id, ImplLookupCycle, facet_type_type_id,
-          context.types().GetTypeIdForTypeConstantId(query_self_const_id));
-      for (const auto& active_entry : llvm::drop_begin(stack, i)) {
-        if (active_entry.impl_loc.has_value()) {
-          CARBON_DIAGNOSTIC(ImplLookupCycleNote, Note,
-                            "determining if this impl clause matches", );
-          builder.Note(active_entry.impl_loc, ImplLookupCycleNote);
+      if (diagnose && !stack.back().diagnosed_cycle) {
+        auto facet_type_type_id = context.types().GetTypeIdForTypeConstantId(
+            query_facet_type_const_id);
+        CARBON_DIAGNOSTIC(ImplLookupCycle, Error,
+                          "cycle found in search for impl of {0} for type {1}",
+                          SemIR::TypeId, SemIR::TypeId);
+        auto builder = context.emitter().Build(
+            loc_id, ImplLookupCycle, facet_type_type_id,
+            context.types().GetTypeIdForTypeConstantId(query_self_const_id));
+        for (const auto& active_entry : llvm::drop_begin(stack, i)) {
+          if (active_entry.impl_loc.has_value()) {
+            CARBON_DIAGNOSTIC(ImplLookupCycleNote, Note,
+                              "determining if this impl clause matches", );
+            builder.Note(active_entry.impl_loc, ImplLookupCycleNote);
+          }
         }
+        builder.Emit();
       }
-      builder.Emit();
+
+      stack.back().diagnosed_cycle = true;
       return true;
     }
   }
@@ -209,7 +212,7 @@ struct RequiredImplsFromConstraint {
 static auto GetRequiredImplsFromConstraint(
     Context& context, SemIR::LocId loc_id,
     SemIR::ConstantId query_self_const_id,
-    SemIR::ConstantId query_facet_type_const_id)
+    SemIR::ConstantId query_facet_type_const_id, bool diagnose)
     -> std::optional<RequiredImplsFromConstraint> {
   auto facet_type_inst_id =
       context.constant_values().GetInstId(query_facet_type_const_id);
@@ -225,7 +228,8 @@ static auto GetRequiredImplsFromConstraint(
                           "facet type {0} can not be identified", InstIdAsType);
         builder.Context(loc_id, ImplLookupInUnidentifiedFacetType,
                         facet_type_inst_id);
-      });
+      },
+      diagnose);
   if (!identified_id.has_value()) {
     return std::nullopt;
   }
@@ -235,12 +239,24 @@ static auto GetRequiredImplsFromConstraint(
        .other_requirements = facet_type_info.other_requirements}};
 }
 
-static auto GetWitnessIdForImpl(Context& context, SemIR::LocId loc_id,
-                                bool query_is_concrete,
-                                SemIR::ConstantId query_self_const_id,
-                                const SemIR::SpecificInterface& interface,
-                                const SemIR::Impl& impl)
-    -> EvalImplLookupResult {
+static auto TreatImplAsFinal(Context& context, const SemIR::Impl& impl)
+    -> bool {
+  // Lookups for the impl inside its own definition treat the impl as final.
+  // Nothing can specialize those lookups further, and it resolves any accesses
+  // of associated constants to their concrete values.
+  return IsImplEffectivelyFinal(context, impl) || impl.is_being_defined();
+}
+
+// Given a (possibly generic) `impl`, deduce a specific `impl` from the query
+// self and specific for the interface. Return the witness ID of the `impl` of
+// the resulting specific `impl`, if its specific interface matches the query.
+//
+// Note the witness also has the specific for the `impl` applied to it.
+static auto TryGetSpecificWitnessIdForImpl(
+    Context& context, SemIR::LocId loc_id,
+    SemIR::ConstantId query_self_const_id,
+    const SemIR::SpecificInterface& interface, const SemIR::Impl& impl)
+    -> SemIR::ConstantId {
   // The impl may have generic arguments, in which case we need to deduce them
   // to find what they are given the specific type and interface query. We use
   // that specific to map values in the impl to the deduced values.
@@ -249,7 +265,7 @@ static auto GetWitnessIdForImpl(Context& context, SemIR::LocId loc_id,
     specific_id = DeduceImplArguments(
         context, loc_id, impl, query_self_const_id, interface.specific_id);
     if (!specific_id.has_value()) {
-      return EvalImplLookupResult::MakeNone();
+      return SemIR::ConstantId::None;
     }
   }
 
@@ -265,7 +281,7 @@ static auto GetWitnessIdForImpl(Context& context, SemIR::LocId loc_id,
   auto deduced_self_const_id =
       GetCanonicalFacetOrTypeValue(context, noncanonical_deduced_self_const_id);
   if (query_self_const_id != deduced_self_const_id) {
-    return EvalImplLookupResult::MakeNone();
+    return SemIR::ConstantId::None;
   }
 
   // The impl's constraint is a facet type which it is implementing for the self
@@ -276,7 +292,7 @@ static auto GetWitnessIdForImpl(Context& context, SemIR::LocId loc_id,
       context.constant_values().GetInstId(SemIR::GetConstantValueInSpecific(
           context.sem_ir(), specific_id, impl.constraint_id));
   if (deduced_constraint_id == SemIR::ErrorInst::InstId) {
-    return EvalImplLookupResult::MakeNone();
+    return SemIR::ConstantId::None;
   }
 
   auto deduced_constraint_facet_type_id =
@@ -289,7 +305,7 @@ static auto GetWitnessIdForImpl(Context& context, SemIR::LocId loc_id,
                1);
 
   if (deduced_constraint_facet_type_info.other_requirements) {
-    return EvalImplLookupResult::MakeNone();
+    return SemIR::ConstantId::None;
   }
 
   // The specifics in the queried interface must match the deduced specifics in
@@ -298,15 +314,19 @@ static auto GetWitnessIdForImpl(Context& context, SemIR::LocId loc_id,
       deduced_constraint_facet_type_info.extend_constraints[0].specific_id;
   auto query_interface_specific_id = interface.specific_id;
   if (impl_interface_specific_id != query_interface_specific_id) {
-    return EvalImplLookupResult::MakeNone();
+    return SemIR::ConstantId::None;
   }
 
   LoadImportRef(context, impl.witness_id);
-  if (specific_id.has_value()) {
+  if (!impl.is_being_defined() && specific_id.has_value()) {
     // If the impl definition can be resolved, eval will do it immediately;
     // otherwise, it can be resolved by further specialization. This is used to
     // resolve dependency chains when `MakeFinal` is returned without a concrete
     // definition; particularly final impls with symbolic constants.
+    //
+    // Note we do not do this for lookups _inside_ the definition of the impl,
+    // as that creates a cycle where resolving the definition must resolve the
+    // definition.
     AddInstInNoBlock(
         context, loc_id,
         SemIR::RequireSpecificDefinition{
@@ -315,77 +335,27 @@ static auto GetWitnessIdForImpl(Context& context, SemIR::LocId loc_id,
             .specific_id = specific_id});
   }
 
-  if (query_is_concrete || impl.is_final) {
-    // TODO: These final results should be cached somehow. Positive (non-None)
-    // results could be cached globally, as they can not change. But
-    // negative results can change after a final impl is written, so
-    // they can only be cached in a limited way, or the cache needs to
-    // be invalidated by writing a final impl that would match.
-    return EvalImplLookupResult::MakeFinal(
-        context.constant_values().GetInstId(SemIR::GetConstantValueInSpecific(
-            context.sem_ir(), specific_id, impl.witness_id)));
-  } else {
-    return EvalImplLookupResult::MakeNonFinal();
-  }
+  return SemIR::GetConstantValueInSpecific(context.sem_ir(), specific_id,
+                                           impl.witness_id);
 }
 
-// Finds a lookup result from `query_self_inst_id` if it is a facet value that
-// names the query interface in its facet type. Note that `query_self_inst_id`
-// is allowed to be a non-canonical facet value in order to find a concrete
-// witness, so it's not referenced as a constant value.
-static auto LookupImplWitnessInSelfFacetValue(
-    Context& context, SemIR::LocId loc_id,
-    SemIR::InstId self_facet_value_inst_id,
-    SemIR::SpecificInterface query_specific_interface) -> EvalImplLookupResult {
+// Identify the facet type of the query self. It is allowed to be partially
+// identified.
+static auto IdentifyQuerySelfFacetType(Context& context, SemIR::LocId loc_id,
+                                       SemIR::ConstantId query_self_const_id)
+    -> SemIR::IdentifiedFacetTypeId {
+  auto query_self_inst_id =
+      context.constant_values().GetInstId(query_self_const_id);
+
   auto facet_type = context.types().TryGetAs<SemIR::FacetType>(
-      context.insts().Get(self_facet_value_inst_id).type_id());
+      context.insts().Get(query_self_inst_id).type_id());
   if (!facet_type) {
-    return EvalImplLookupResult::MakeNone();
-  }
-
-  auto self_facet_value_const_id =
-      context.constant_values().Get(self_facet_value_inst_id);
-
-  // The position of the interface in `required_impls()` is also the
-  // position of the witness for that interface in `FacetValue`. The
-  // `FacetValue` witnesses are the output of an impl lookup, which finds and
-  // returns witnesses in the same order.
-  auto identified_id = RequireIdentifiedFacetType(
-      context, loc_id, self_facet_value_const_id, *facet_type,
-      [&](auto& builder) {
-        CARBON_DIAGNOSTIC(ImplLookupInUnidentifiedFacetTypeOfQuerySelf, Context,
-                          "facet type of value {0} can not be identified",
-                          InstIdAsType);
-        builder.Context(loc_id, ImplLookupInUnidentifiedFacetTypeOfQuerySelf,
-                        self_facet_value_inst_id);
-      });
-  if (!identified_id.has_value()) {
-    return EvalImplLookupResult::MakeNone();
-  }
-  auto facet_type_req_impls = llvm::enumerate(
-      context.identified_facet_types().Get(identified_id).required_impls());
-  auto it = llvm::find_if(facet_type_req_impls, [&](auto e) {
-    auto [req_self, req_specific_interface] = e.value();
-    // The `self_facet_value_inst_id` in eval is a canonicalized facet value, as
-    // is the self in the identified facet type.
-    return req_self == self_facet_value_const_id &&
-           req_specific_interface == query_specific_interface;
-  });
-  if (it == facet_type_req_impls.end()) {
-    return EvalImplLookupResult::MakeNone();
+    return SemIR::IdentifiedFacetTypeId::None;
   }
-  auto index = (*it).index();
 
-  if (auto facet_value = context.insts().TryGetAs<SemIR::FacetValue>(
-          self_facet_value_inst_id)) {
-    auto witness_id =
-        context.inst_blocks().Get(facet_value->witnesses_block_id)[index];
-    if (context.insts().IsOneOf<SemIR::ImplWitness, SemIR::CustomWitness>(
-            witness_id)) {
-      return EvalImplLookupResult::MakeFinal(witness_id);
-    }
-  }
-  return EvalImplLookupResult::MakeNonFinal();
+  return TryToIdentifyFacetType(context, loc_id, query_self_const_id,
+                                *facet_type,
+                                /*allow_partially_identified=*/true);
 }
 
 // Substitutes witnesess in place of `LookupImplWitness` queries into `.Self`,
@@ -561,120 +531,6 @@ static auto VerifyQueryFacetTypeConstraints(
   return true;
 }
 
-// Begin a search for an impl declaration matching the query. We do this by
-// creating an LookupImplWitness instruction and evaluating. If it's able to
-// find a final concrete impl, then it will evaluate to that `ImplWitness` but
-// if not, it will evaluate to itself as a symbolic witness to be further
-// evaluated with a more specific query when building a specific for the generic
-// context the query came from.
-static auto GetOrAddLookupImplWitness(Context& context, SemIR::LocId loc_id,
-                                      SemIR::ConstantId query_self_const_id,
-                                      SemIR::SpecificInterface interface)
-    -> SemIR::InstId {
-  auto witness_const_id = EvalOrAddInst(
-      context, context.insts().GetLocIdForDesugaring(loc_id),
-      SemIR::LookupImplWitness{
-          .type_id = GetSingletonType(context, SemIR::WitnessType::TypeInstId),
-          .query_self_inst_id =
-              context.constant_values().GetInstId(query_self_const_id),
-          .query_specific_interface_id =
-              context.specific_interfaces().Add(interface),
-      });
-  // We use a NotConstant result from eval to communicate back an impl
-  // lookup failure. See `EvalConstantInst()` for `LookupImplWitness`.
-  if (!witness_const_id.is_constant()) {
-    return SemIR::InstId::None;
-  }
-  return context.constant_values().GetInstId(witness_const_id);
-}
-
-auto LookupImplWitness(Context& context, SemIR::LocId loc_id,
-                       SemIR::ConstantId query_self_const_id,
-                       SemIR::ConstantId query_facet_type_const_id)
-    -> SemIR::InstBlockIdOrError {
-  if (query_self_const_id == SemIR::ErrorInst::ConstantId ||
-      query_facet_type_const_id == SemIR::ErrorInst::ConstantId) {
-    return SemIR::InstBlockIdOrError::MakeError();
-  }
-
-  {
-    // The query self value is a type value or a facet value.
-    auto query_self_type_id =
-        context.insts()
-            .Get(context.constant_values().GetInstId(query_self_const_id))
-            .type_id();
-    CARBON_CHECK((context.types().IsOneOf<SemIR::TypeType, SemIR::FacetType>(
-        query_self_type_id)));
-    // The query facet type value is indeed a facet type.
-    CARBON_CHECK(context.insts().Is<SemIR::FacetType>(
-        context.constant_values().GetInstId(query_facet_type_const_id)));
-  }
-
-  auto req_impls_from_constraint = GetRequiredImplsFromConstraint(
-      context, loc_id, query_self_const_id, query_facet_type_const_id);
-  if (!req_impls_from_constraint) {
-    return SemIR::InstBlockIdOrError::MakeError();
-  }
-  auto [req_impls, other_requirements] = *req_impls_from_constraint;
-  if (other_requirements) {
-    // TODO: Remove this when other requirements go away.
-    return SemIR::InstBlockId::None;
-  }
-  if (req_impls.empty()) {
-    return SemIR::InstBlockId::Empty;
-  }
-
-  if (FindAndDiagnoseImplLookupCycle(context, context.impl_lookup_stack(),
-                                     loc_id, query_self_const_id,
-                                     query_facet_type_const_id)) {
-    return SemIR::InstBlockIdOrError::MakeError();
-  }
-
-  auto& stack = context.impl_lookup_stack();
-  stack.push_back({
-      .query_self_const_id = query_self_const_id,
-      .query_facet_type_const_id = query_facet_type_const_id,
-  });
-  // We need to find a witness for each self+interface pair in `req_impls`.
-  //
-  // Every consumer of a facet type needs to agree on the order of interfaces
-  // used for its witnesses, which is done by following the order in the
-  // IdentifiedFacetType.
-  llvm::SmallVector<SemIR::InstId> result_witness_ids;
-  for (const auto& req_impl : req_impls) {
-    // TODO: Since both `interfaces` and `query_self_const_id` are sorted lists,
-    // do an O(N+M) merge instead of O(N*M) nested loops.
-    auto result_witness_id =
-        GetOrAddLookupImplWitness(context, loc_id, req_impl.self_facet_value,
-                                  req_impl.specific_interface);
-    if (result_witness_id.has_value()) {
-      result_witness_ids.push_back(result_witness_id);
-    } else {
-      // At least one queried interface in the facet type has no witness for the
-      // given type, we can stop looking for more.
-      break;
-    }
-  }
-  stack.pop_back();
-
-  // All interfaces in the query facet type must have been found to be available
-  // through some impl, or directly on the value's facet type if
-  // `query_self_const_id` is a facet value.
-  if (result_witness_ids.size() != req_impls.size()) {
-    return SemIR::InstBlockId::None;
-  }
-
-  // Verify rewrite constraints in the query constraint are satisfied after
-  // applying the rewrites from the found witnesses.
-  if (!VerifyQueryFacetTypeConstraints(context, loc_id, query_self_const_id,
-                                       query_facet_type_const_id, req_impls,
-                                       result_witness_ids)) {
-    return SemIR::InstBlockId::None;
-  }
-
-  return context.inst_blocks().AddCanonical(result_witness_ids);
-}
-
 // Returns whether the query is concrete, it is false if the self type or
 // interface specifics have a symbolic dependency.
 static auto QueryIsConcrete(Context& context, SemIR::ConstantId self_const_id,
@@ -815,7 +671,7 @@ static auto CollectCandidateImplsForQuery(
   for (auto [id, impl] : context.impls().enumerate()) {
     CARBON_CHECK(impl.witness_id.has_value());
 
-    if (final_only && !IsImplEffectivelyFinal(context, impl)) {
+    if (final_only && !TreatImplAsFinal(context, impl)) {
       continue;
     }
 
@@ -870,36 +726,355 @@ static auto CollectCandidateImplsForQuery(
   return candidates;
 }
 
+class IndexInFacetValue {
+ public:
+  static const IndexInFacetValue None;
+  static const IndexInFacetValue Unstable;
+
+  explicit constexpr IndexInFacetValue(int32_t index) : index_(index) {}
+
+  // Returns whether the value represents a successful attempt to find the index
+  // of an interface in a FacetValue. Returns true regardless of whether the
+  // index is stable and able to be used or not.
+  auto WasFound() const -> bool { return index_ != None.index_; }
+
+  // Gets the stable index which can be used to index into the witness table in
+  // a FacetValue, if there is one. Otherwise, returns -1.
+  auto GetStableIndex() const -> int32_t {
+    if (index_ == Unstable.index_) {
+      return None.index_;
+    }
+    return index_;
+  }
+
+ private:
+  int32_t index_;
+};
+
+inline constexpr auto IndexInFacetValue::None = IndexInFacetValue(-1);
+inline constexpr auto IndexInFacetValue::Unstable = IndexInFacetValue(-2);
+
+// Looks in the facet type of the query self facet value and returns the index
+// of `query_specific_interface` in the defined interface order for that facet
+// type. The order comes from the `query_self_type_identified_id` which must be
+// the IdentifiedFacetType of the type of `query_self_const_id `.
+//
+// If the query self is not a facet value, the IdentifiedFacetType would be
+// None.
+//
+// The IdentifiedFacetType must not be partially identified in order to find an
+// index, as that implies the interface order is not yet stable. In that case,
+// no index will be found.
+//
+// If the `query_specific_interface` is not part of the facet type of the query
+// self, returns -1 to indicate it was not found.
+static auto IndexOfImplWitnessInSelfFacetValue(
+    Context& context, SemIR::ConstantId query_self_const_id,
+    SemIR::IdentifiedFacetTypeId query_self_type_identified_id,
+    SemIR::SpecificInterface query_specific_interface) -> IndexInFacetValue {
+  if (!query_self_type_identified_id.has_value()) {
+    return IndexInFacetValue::None;
+  }
+
+  // The self in the identified facet type is a canonicalized facet value, so we
+  // canonicalize the query for comparison.
+  auto canonical_query_self_const_id =
+      GetCanonicalFacetOrTypeValue(context, query_self_const_id);
+
+  const auto& identified =
+      context.identified_facet_types().Get(query_self_type_identified_id);
+  auto facet_type_req_impls = llvm::enumerate(identified.required_impls());
+  auto it = llvm::find_if(facet_type_req_impls, [&](auto e) {
+    auto [req_self, req_specific_interface] = e.value();
+    return req_self == canonical_query_self_const_id &&
+           req_specific_interface == query_specific_interface;
+  });
+  if (it == facet_type_req_impls.end()) {
+    return IndexInFacetValue::None;
+  }
+
+  if (identified.partially_identified()) {
+    return IndexInFacetValue::Unstable;
+  }
+  return IndexInFacetValue(static_cast<int32_t>((*it).index()));
+}
+
+static auto FindFinalWitnessFromSelfFacetValue(
+    Context& context, SemIR::ConstantId query_self_const_id,
+    SemIR::IdentifiedFacetTypeId query_self_type_identified_id,
+    SemIR::SpecificInterface query_specific_interface) -> SemIR::InstId {
+  // TODO: Add and use constant_values().GetAs<SemIR::FacetType>().
+  auto query_self_inst_id =
+      context.constant_values().GetInstId(query_self_const_id);
+  auto facet_value =
+      context.insts().TryGetAs<SemIR::FacetValue>(query_self_inst_id);
+  if (!facet_value) {
+    return SemIR::InstId::None;
+  }
+
+  auto index_in_facet_value = IndexOfImplWitnessInSelfFacetValue(
+      context, query_self_const_id, query_self_type_identified_id,
+      query_specific_interface);
+  auto stable_index = index_in_facet_value.GetStableIndex();
+  if (stable_index < 0) {
+    return SemIR::InstId::None;
+  }
+
+  auto witness_id =
+      context.inst_blocks().Get(facet_value->witnesses_block_id)[stable_index];
+  if (context.insts().Is<SemIR::LookupImplWitness>(witness_id)) {
+    // Did not find a final witness.
+    return SemIR::InstId::None;
+  }
+
+  return witness_id;
+}
+
+static auto FindNonFinalWitness(
+    Context& context, SemIR::LocId loc_id,
+    SemIR::ConstantId query_self_const_id,
+    SemIR::IdentifiedFacetTypeId query_self_type_identified_id,
+    SemIR::SpecificInterface query_specific_interface) -> bool {
+  auto index = IndexOfImplWitnessInSelfFacetValue(context, query_self_const_id,
+                                                  query_self_type_identified_id,
+                                                  query_specific_interface);
+  if (index.WasFound()) {
+    return true;
+  }
+
+  // TODO: Remove SpecificInterfaceId from LookupCustomWitness apis, switch to
+  // just SpecificInterface.
+  auto query_specific_interface_id =
+      context.specific_interfaces().Add(query_specific_interface);
+
+  // Consider a custom witness for core interfaces.
+  // TODO: This needs to expand to more interfaces, and we might want to have
+  // that dispatch in custom_witness.cpp instead of here.
+  auto core_interface =
+      GetCoreInterface(context, query_specific_interface.interface_id);
+  if (auto witness_id = LookupCustomWitness(
+          context, loc_id, core_interface, query_self_const_id,
+          query_specific_interface_id, false)) {
+    // If there's a final witness, we would have already found it via evaluating
+    // the LookupImplWitness instruction.
+    CARBON_CHECK(!witness_id->has_value());
+    return true;
+  }
+
+  auto query_type_structure = BuildTypeStructure(
+      context, context.constant_values().GetInstId(query_self_const_id),
+      query_specific_interface);
+  // We looked for errors in the query self and facet type already, and we're
+  // not dealing with monomorphizations here.
+  CARBON_CHECK(query_type_structure, "error in impl lookup query");
+
+  auto candidates = CollectCandidateImplsForQuery(
+      context, /*final_only=*/false, query_self_const_id, *query_type_structure,
+      query_specific_interface);
+
+  for (const auto& candidate : candidates.impls) {
+    const auto& impl = *candidate.impl;
+    context.impl_lookup_stack().back().impl_loc = impl.definition_id;
+
+    auto witness_id = TryGetSpecificWitnessIdForImpl(
+        context, loc_id, query_self_const_id, query_specific_interface, impl);
+    if (witness_id.has_value()) {
+      // We looked for errors in the query self and facet type already, and
+      // we're not dealing with monomorphizations here.
+      CARBON_CHECK(witness_id != SemIR::ErrorInst::ConstantId,
+                   "error in impl lookup query");
+      return true;
+    }
+  }
+
+  // C++ interop only provides final witnesses, so we don't look for a witness
+  // from C++ here. Those are found in eval of the `LookupImplWitness`
+  // instruction.
+
+  return false;
+}
+
+auto LookupImplWitness(Context& context, SemIR::LocId loc_id,
+                       SemIR::ConstantId query_self_const_id,
+                       SemIR::ConstantId query_facet_type_const_id,
+                       bool diagnose) -> SemIR::InstBlockIdOrError {
+  if (query_self_const_id == SemIR::ErrorInst::ConstantId ||
+      query_facet_type_const_id == SemIR::ErrorInst::ConstantId) {
+    return SemIR::InstBlockIdOrError::MakeError();
+  }
+
+  {
+    // The query self value is a type value or a facet value.
+    auto query_self_type_id =
+        context.insts()
+            .Get(context.constant_values().GetInstId(query_self_const_id))
+            .type_id();
+    CARBON_CHECK((context.types().IsOneOf<SemIR::TypeType, SemIR::FacetType>(
+        query_self_type_id)));
+    // The query facet type value is indeed a facet type.
+    CARBON_CHECK(context.insts().Is<SemIR::FacetType>(
+        context.constant_values().GetInstId(query_facet_type_const_id)));
+  }
+
+  auto req_impls_from_constraint =
+      GetRequiredImplsFromConstraint(context, loc_id, query_self_const_id,
+                                     query_facet_type_const_id, diagnose);
+  if (!req_impls_from_constraint) {
+    return SemIR::InstBlockIdOrError::MakeError();
+  }
+  auto [req_impls, other_requirements] = *req_impls_from_constraint;
+  if (other_requirements) {
+    // TODO: Remove this when other requirements go away.
+    return SemIR::InstBlockId::None;
+  }
+  if (req_impls.empty()) {
+    return SemIR::InstBlockId::Empty;
+  }
+
+  // Cycles are diagnosed even if they are found when diagnostics are otherwise
+  // being suppressed (such as during deduce).
+  if (FindAndDiagnoseImplLookupCycle(context, context.impl_lookup_stack(),
+                                     loc_id, query_self_const_id,
+                                     query_facet_type_const_id, true)) {
+    return SemIR::InstBlockIdOrError::MakeError();
+  }
+
+  auto& stack = context.impl_lookup_stack();
+  stack.push_back({
+      .query_self_const_id = query_self_const_id,
+      .query_facet_type_const_id = query_facet_type_const_id,
+      .diagnosed_cycle = stack.empty() ? false : stack.back().diagnosed_cycle,
+  });
+  // We need to find a witness for each self+interface pair in `req_impls`.
+  //
+  // Every consumer of a facet type needs to agree on the order of interfaces
+  // used for its witnesses, which is done by following the order in the
+  // IdentifiedFacetType of the query facet type, and this is represented in the
+  // order of the interfaces in `req_impls`.
+  llvm::SmallVector<SemIR::InstId> result_witness_ids;
+  for (const auto& req_impl : req_impls) {
+    // Identify the type of the requirement's self up front, if it's a facet, so
+    // we only have to do this once.
+    auto req_self_type_identified_id =
+        IdentifyQuerySelfFacetType(context, loc_id, req_impl.self_facet_value);
+
+    // If the self facet contains a final witness for the required interface, we
+    // use that and avoid any further work. This is strictly an optimization,
+    // since that same final witness should be found by evaluating a
+    // LookupImplWitness instruction for the required self+interface pair.
+    auto result_witness_id = FindFinalWitnessFromSelfFacetValue(
+        context, req_impl.self_facet_value, req_self_type_identified_id,
+        req_impl.specific_interface);
+    if (result_witness_id.has_value()) {
+      // Found a final witness, use it.
+      result_witness_ids.push_back(result_witness_id);
+      continue;
+    }
+
+    auto witness_const_id = EvalOrAddInst<SemIR::LookupImplWitness>(
+        context, context.insts().GetLocIdForDesugaring(loc_id),
+        {.type_id = GetSingletonType(context, SemIR::WitnessType::TypeInstId),
+         .query_self_inst_id =
+             context.constant_values().GetInstId(req_impl.self_facet_value),
+         .query_specific_interface_id =
+             context.specific_interfaces().Add(req_impl.specific_interface)});
+    result_witness_id = context.constant_values().GetInstId(witness_const_id);
+    if (!context.insts().Is<SemIR::LookupImplWitness>(result_witness_id)) {
+      // Found a final witness, use it.
+      result_witness_ids.push_back(result_witness_id);
+      continue;
+    }
+
+    if (QueryIsConcrete(context, req_impl.self_facet_value,
+                        req_impl.specific_interface)) {
+      // Failed to find a final witness for a concrete query. There won't be a
+      // non-final witness, as any witness would have been treated as final.
+      break;
+    }
+
+    // Did not find a final witness. If we find a non-final witness, then we use
+    // the `LookupImplWitness` as our witness so that monomorphization can
+    // produce a final witness later.
+    if (!FindNonFinalWitness(context, loc_id, req_impl.self_facet_value,
+                             req_self_type_identified_id,
+                             req_impl.specific_interface)) {
+      // At least one queried interface in the facet type has no witness for the
+      // given type, we can stop looking for more.
+      //
+      // TODO: The LookupImplWitness won't be used. We should find a way to
+      // discard it, which would remove it from the generic eval block if the
+      // lookup is within a generic context.
+      break;
+    }
+
+    // Save the non-final witness, which will eventually resolve to a final
+    // witness as specifics are applied to make the query more concrete.
+    result_witness_ids.push_back(result_witness_id);
+  }
+  auto pop = stack.pop_back_val();
+  if (pop.diagnosed_cycle && !stack.empty()) {
+    stack.back().diagnosed_cycle = true;
+  }
+
+  // All interfaces in the query facet type must have been found to be available
+  // through some impl, or directly on the value's facet type if
+  // `query_self_const_id` is a facet value.
+  if (result_witness_ids.size() != req_impls.size()) {
+    return SemIR::InstBlockId::None;
+  }
+
+  // Verify rewrite constraints in the query constraint are satisfied after
+  // applying the rewrites from the found witnesses.
+  if (!VerifyQueryFacetTypeConstraints(context, loc_id, query_self_const_id,
+                                       query_facet_type_const_id, req_impls,
+                                       result_witness_ids)) {
+    return SemIR::InstBlockId::None;
+  }
+
+  return context.inst_blocks().AddCanonical(result_witness_ids);
+}
+
 // Record the query which found a final impl witness. It's illegal to
 // write a final impl afterward that would match the same query.
 static auto PoisonImplLookupQuery(Context& context, SemIR::LocId loc_id,
                                   EvalImplLookupMode mode,
                                   SemIR::LookupImplWitness eval_query,
-                                  const EvalImplLookupResult& result,
+                                  SemIR::ConstantId witness_id,
                                   const SemIR::Impl& impl) -> void {
   if (mode == EvalImplLookupMode::RecheckPoisonedLookup) {
     return;
   }
-  if (!result.has_final_value()) {
-    return;
-  }
   // If the impl was effectively final, then we don't need to poison here. A
   // change of query result will already be diagnosed at the point where the
   // new impl decl was written that changes the result.
-  if (IsImplEffectivelyFinal(context, impl)) {
+  if (TreatImplAsFinal(context, impl)) {
     return;
   }
   context.poisoned_concrete_impl_lookup_queries().push_back(
-      {.loc_id = loc_id,
-       .query = eval_query,
-       .impl_witness = result.final_witness()});
+      {.loc_id = loc_id, .query = eval_query, .witness_id = witness_id});
 }
 
-auto EvalLookupSingleImplWitness(Context& context, SemIR::LocId loc_id,
-                                 SemIR::LookupImplWitness eval_query,
-                                 SemIR::InstId self_facet_value_inst_id,
-                                 EvalImplLookupMode mode)
-    -> EvalImplLookupResult {
+// Return whether the `FacetType` in `type_id` extends a single interface, and
+// that it matches `specific_interface`.
+static auto FacetTypeIsSingleInterface(
+    Context& context, SemIR::TypeId type_id,
+    SemIR::SpecificInterface specific_interface) -> bool {
+  auto facet_type = context.types().GetAs<SemIR::FacetType>(type_id);
+  const auto& facet_type_info =
+      context.facet_types().Get(facet_type.facet_type_id);
+  if (auto single = facet_type_info.TryAsSingleExtend()) {
+    if (auto* si = std::get_if<SemIR::SpecificInterface>(&*single)) {
+      return *si == specific_interface;
+    }
+  }
+  return false;
+}
+
+auto EvalLookupSingleFinalWitness(Context& context, SemIR::LocId loc_id,
+                                  SemIR::LookupImplWitness eval_query,
+                                  SemIR::InstId self_facet_value_inst_id,
+                                  EvalImplLookupMode mode)
+    -> SemIR::ConstantId {
   auto query_specific_interface =
       context.specific_interfaces().Get(eval_query.query_specific_interface_id);
 
@@ -909,40 +1084,59 @@ auto EvalLookupSingleImplWitness(Context& context, SemIR::LocId loc_id,
   SemIR::ConstantId query_self_const_id =
       context.constant_values().Get(eval_query.query_self_inst_id);
 
-  auto facet_lookup_result = LookupImplWitnessInSelfFacetValue(
-      context, loc_id, self_facet_value_inst_id, query_specific_interface);
-  if (facet_lookup_result.has_final_value()) {
-    return facet_lookup_result;
-  }
-
-  // If the self type is a facet that provides a witness, then we are in an
-  // `interface` or an `impl`. In both cases, we don't want to do any impl
-  // lookups. The query will eventually resolve to a concrete witness when it
-  // can get it from the self facet value, when it has a specific applied in the
-  // future.
+  // If the query self is monomorphized as a FacetValue, we can't use its
+  // witnesses in general, since we are not allowed to identify facet types in
+  // monomorphization. And we need to identify it to know which witness is for
+  // which interface.
   //
-  // In particular, this avoids a LookupImplWitness instruction in the eval
-  // block of an impl declaration from doing impl lookup. Specifically the
-  // lookup of the implicit .Self in `impl ... where .X`. If it does impl lookup
-  // when the eval block is run, it finds the same `impl`, tries to build a
-  // specific from it, which runs the eval block, creating a recursive loop that
-  // crashes.
-  if (facet_lookup_result.has_value()) {
-    if (auto bind = context.insts().TryGetAs<SemIR::SymbolicBinding>(
-            eval_query.query_self_inst_id)) {
-      const auto& entity = context.entity_names().Get(bind->entity_name_id);
-      if (entity.name_id == SemIR::NameId::PeriodSelf ||
-          entity.name_id == SemIR::NameId::SelfType) {
-        return facet_lookup_result;
+  // However, if the facet type has only a single interface and it matches the
+  // query, then we can use the witness, since there is only one.
+  //
+  // This looks like an optimization, but it's done to prefer the FacetValue's
+  // witness over the cached value for monomorphizations of `Self` inside an
+  // `impl` definition. If a final witness was previously found for the same
+  // type as the monomorphized `Self`, the cache would reuse it. But associated
+  // constants may differ in that witness from the current `impl`'s witness
+  // which leads to inconsistency within the impl definition.
+  //
+  // By preferring the impl's FacetValue, the `impl` remains self-consistent
+  // even if it's ultimately not valid due to a conflict. When a conflict with
+  // another `impl` does exist, a poisoning error will occur showing the two
+  // `impl`s are in disagreement for a concrete value, as the poisoning lookup
+  // does not preserve the FacetValue.
+  if (auto facet_value = context.insts().TryGetAsIfValid<SemIR::FacetValue>(
+          self_facet_value_inst_id)) {
+    if (FacetTypeIsSingleInterface(context, facet_value->type_id,
+                                   query_specific_interface)) {
+      auto witnesses =
+          context.inst_blocks().Get(facet_value->witnesses_block_id);
+      CARBON_CHECK(witnesses.size() == 1);
+      auto witness_inst_id = witnesses.front();
+      // Only use the witness in monomoprhization if it's a final witness.
+      if (!context.insts().Is<SemIR::LookupImplWitness>(witness_inst_id)) {
+        return context.constant_values().Get(witness_inst_id);
       }
     }
   }
 
-  auto query_type_structure = BuildTypeStructure(
-      context, context.constant_values().GetInstId(query_self_const_id),
-      query_specific_interface);
-  if (!query_type_structure) {
-    return EvalImplLookupResult::MakeNone();
+  // If the query is on `.Self` and looking for the same interface as `.Self`
+  // provides, do not look for a witness in monomorphization - a non-final
+  // witness will be found from the facet type. This happens inside an `impl`
+  // declaration, and we must avoid finding that same `impl` and trying to
+  // deduce `.Self` for it, as that results in a specific declaration for the
+  // `impl` which evaluates this lookup again, producing a cycle.
+  //
+  // If the query is for `.Self` and for the facet type of `.Self`, then there
+  // is no final witness yet.
+  if (auto bind = context.insts().TryGetAs<SemIR::SymbolicBinding>(
+          eval_query.query_self_inst_id)) {
+    const auto& entity = context.entity_names().Get(bind->entity_name_id);
+    if (entity.name_id == SemIR::NameId::PeriodSelf) {
+      if (FacetTypeIsSingleInterface(context, bind->type_id,
+                                     query_specific_interface)) {
+        return SemIR::ConstantId::None;
+      }
+    }
   }
 
   // Check to see if this result is in the cache. But skip the cache if we're
@@ -952,37 +1146,37 @@ auto EvalLookupSingleImplWitness(Context& context, SemIR::LocId loc_id,
   if (mode != EvalImplLookupMode::RecheckPoisonedLookup) {
     if (auto result =
             context.impl_lookup_cache().Lookup(impl_lookup_cache_key)) {
-      return EvalImplLookupResult::MakeFinal(result.value());
+      return result.value();
     }
   }
 
-  // If the self value is a (symbolic) facet value that has a symbolic witness,
-  // then we don't need to do impl lookup, except that we want to find any final
-  // impls to return a concrete witness if possible. So we limit the query to
-  // final impls only in that case. Note as in the CHECK above, the query can
-  // not be concrete in this case, so only final impls can produce a concrete
-  // witness for this query.
-  auto candidates = CollectCandidateImplsForQuery(
-      context, facet_lookup_result.has_value(), query_self_const_id,
-      *query_type_structure, query_specific_interface);
-
   bool query_is_concrete =
       QueryIsConcrete(context, query_self_const_id, query_specific_interface);
-  CARBON_CHECK(!query_is_concrete || !facet_lookup_result.has_value(),
-               "Non-concrete facet lookup value for concrete query");
 
-  // Perform a lookup for an `impl` that matches the query. If we don't find a
-  // final impl, the self value may still have been a facet that provides a
-  // symbolic witness in the `facet_lookup_result`, which we want to fall back
-  // to. It records that an `impl` will exist for the query, but is yet unknown.
+  auto query_type_structure = BuildTypeStructure(
+      context, context.constant_values().GetInstId(query_self_const_id),
+      query_specific_interface);
+  if (!query_type_structure) {
+    // TODO: We should return an error here; an error was found in the type
+    // structure.
+    return SemIR::ConstantId::None;
+  }
+
+  // We only want to return final witneses in monomorphization. If the query is
+  // concrete, we can find all impls, otherwise we want only (effectively) final
+  // impls.
+  auto candidates = CollectCandidateImplsForQuery(
+      context, /*final_only=*/!query_is_concrete, query_self_const_id,
+      *query_type_structure, query_specific_interface);
 
   struct LookupResult {
-    EvalImplLookupResult result;
+    SemIR::ConstantId witness_id = SemIR::ConstantId::None;
+    // Holds a pointer into `candidates`.
     const TypeStructure* impl_type_structure = nullptr;
     SemIR::LocId impl_loc_id = SemIR::LocId::None;
   };
 
-  LookupResult lookup_result = {.result = facet_lookup_result};
+  LookupResult lookup_result;
 
   auto core_interface =
       GetCoreInterface(context, query_specific_interface.interface_id);
@@ -991,15 +1185,14 @@ auto EvalLookupSingleImplWitness(Context& context, SemIR::LocId loc_id,
   // TODO: This needs to expand to more interfaces, and we might want to have
   // that dispatch in custom_witness.cpp instead of here.
   bool used_custom_witness = false;
-  if (auto witness_id = LookupCustomWitness(
+  if (auto witness_inst_id = LookupCustomWitness(
           context, loc_id, core_interface, query_self_const_id,
-          eval_query.query_specific_interface_id)) {
-    if (witness_id->has_value()) {
-      lookup_result = {.result = EvalImplLookupResult::MakeFinal(*witness_id)};
-    } else {
-      lookup_result = {.result = EvalImplLookupResult::MakeNonFinal()};
+          eval_query.query_specific_interface_id, true)) {
+    if (witness_inst_id->has_value()) {
+      lookup_result = {.witness_id =
+                           context.constant_values().Get(*witness_inst_id)};
+      used_custom_witness = true;
     }
-    used_custom_witness = true;
   }
 
   // Only consider candidates when a custom witness didn't apply.
@@ -1007,20 +1200,19 @@ auto EvalLookupSingleImplWitness(Context& context, SemIR::LocId loc_id,
     for (const auto& candidate : candidates.impls) {
       const auto& impl = *candidate.impl;
 
-      // In deferred lookup for a symbolic impl witness, while building a
-      // specific, there may be no stack yet as this may be the first lookup. If
-      // further lookups are started as a result in deduce, they will build the
-      // stack.
+      // In monomorphization, while resolving a specific, there may be no stack
+      // yet as this may be the first lookup. If further lookups are started as
+      // a result in deduce, they will build the stack.
       if (!context.impl_lookup_stack().empty()) {
         context.impl_lookup_stack().back().impl_loc = impl.definition_id;
       }
 
-      auto result = GetWitnessIdForImpl(context, loc_id, query_is_concrete,
-                                        query_self_const_id,
-                                        query_specific_interface, impl);
-      if (result.has_value()) {
-        PoisonImplLookupQuery(context, loc_id, mode, eval_query, result, impl);
-        lookup_result = {.result = result,
+      auto witness_id = TryGetSpecificWitnessIdForImpl(
+          context, loc_id, query_self_const_id, query_specific_interface, impl);
+      if (witness_id.has_value()) {
+        PoisonImplLookupQuery(context, loc_id, mode, eval_query, witness_id,
+                              impl);
+        lookup_result = {.witness_id = witness_id,
                          .impl_type_structure = &candidate.type_structure,
                          .impl_loc_id = SemIR::LocId(impl.definition_id)};
         break;
@@ -1037,17 +1229,17 @@ auto EvalLookupSingleImplWitness(Context& context, SemIR::LocId loc_id,
         eval_query.query_specific_interface_id,
         lookup_result.impl_type_structure, lookup_result.impl_loc_id);
     if (cpp_witness_id.has_value()) {
-      lookup_result = {.result =
-                           EvalImplLookupResult::MakeFinal(cpp_witness_id)};
+      lookup_result = {.witness_id =
+                           context.constant_values().Get(cpp_witness_id)};
     }
   }
 
   if (mode != EvalImplLookupMode::RecheckPoisonedLookup &&
-      lookup_result.result.has_final_value()) {
+      lookup_result.witness_id.has_value()) {
     context.impl_lookup_cache().Insert(impl_lookup_cache_key,
-                                       lookup_result.result.final_witness());
+                                       lookup_result.witness_id);
   }
-  return lookup_result.result;
+  return lookup_result.witness_id;
 }
 
 auto LookupMatchesImpl(Context& context, SemIR::LocId loc_id,
@@ -1057,10 +1249,14 @@ auto LookupMatchesImpl(Context& context, SemIR::LocId loc_id,
   if (query_self_const_id == SemIR::ErrorInst::ConstantId) {
     return false;
   }
-  auto result = GetWitnessIdForImpl(
-      context, loc_id, /*query_is_concrete=*/false, query_self_const_id,
-      query_specific_interface, context.impls().Get(target_impl));
-  return result.has_value();
+  auto witness_id = TryGetSpecificWitnessIdForImpl(
+      context, loc_id, query_self_const_id, query_specific_interface,
+      context.impls().Get(target_impl));
+  // TODO: If this fails, it would be because there is an error in the specific
+  // interface. Should we check for that and return false?
+  CARBON_CHECK(witness_id != SemIR::ErrorInst::ConstantId,
+               "error in lookup specific interface");
+  return witness_id.has_value();
 }
 
 }  // namespace Carbon::Check

+ 12 - 62
toolchain/check/impl_lookup.h

@@ -36,8 +36,8 @@ namespace Carbon::Check {
 //   produced, either in this function or before.
 auto LookupImplWitness(Context& context, SemIR::LocId loc_id,
                        SemIR::ConstantId query_self_const_id,
-                       SemIR::ConstantId query_facet_type_const_id)
-    -> SemIR::InstBlockIdOrError;
+                       SemIR::ConstantId query_facet_type_const_id,
+                       bool diagnose = true) -> SemIR::InstBlockIdOrError;
 
 // Returns whether the query matches against the given impl. This is like a
 // `LookupImplWitness` operation but for a single interface, and against only
@@ -47,57 +47,8 @@ auto LookupMatchesImpl(Context& context, SemIR::LocId loc_id,
                        SemIR::SpecificInterface query_specific_interface,
                        SemIR::ImplId target_impl) -> bool;
 
-// The result of EvalLookupSingleImplWitness(). It can be one of:
-// - No value. Lookup failed to find an impl declaration.
-// - An effectively final value. Lookup found either a concrete impl or a
-//   `final` impl declaration; both can be used definitely. A witness is
-//   available.
-// - A non-`final` symbolic value. Lookup found an impl, but it is not returned
-//   since lookup will need to be done again with a more specific query to look
-//   for specializations.
-class [[nodiscard]] EvalImplLookupResult {
- public:
-  static auto MakeNone() -> EvalImplLookupResult {
-    return EvalImplLookupResult(FoundNone());
-  }
-  static auto MakeFinal(SemIR::InstId inst_id) -> EvalImplLookupResult {
-    return EvalImplLookupResult(inst_id);
-  }
-  static auto MakeNonFinal() -> EvalImplLookupResult {
-    return EvalImplLookupResult(FoundNonFinalImpl());
-  }
-
-  // True if an impl declaration was found, either effectively final or
-  // symbolic.
-  auto has_value() const -> bool {
-    return !std::holds_alternative<FoundNone>(value_);
-  }
-
-  // True if there is an effectively final witness in the result. If false, and
-  // `has_value()` is true, it means an impl was found that's not effectively
-  // final, and a further more specific query will need to be done.
-  auto has_final_value() const -> bool {
-    return std::holds_alternative<SemIR::InstId>(value_);
-  }
-
-  // Returns the witness id for an effectively final value's impl declaration.
-  // Only valid to call if `has_final_value` is true.
-  auto final_witness() const -> SemIR::InstId {
-    return std::get<SemIR::InstId>(value_);
-  }
-
- private:
-  struct FoundNone {};
-  struct FoundNonFinalImpl {};
-  using Value = std::variant<SemIR::InstId, FoundNone, FoundNonFinalImpl>;
-
-  explicit EvalImplLookupResult(Value value) : value_(value) {}
-
-  Value value_;
-};
-
 // The kind of impl lookup being performed by a call to
-// `EvalLookupSingleImplWitness`.
+// `EvalLookupSingleFinalWitness`.
 enum class EvalImplLookupMode {
   // This is a regular impl lookup performed during check. If we produce a final
   // witness value that uses a specializable impl, the query will be poisoned so
@@ -109,16 +60,15 @@ enum class EvalImplLookupMode {
   RecheckPoisonedLookup,
 };
 
-// Looks for a witness instruction of an impl declaration for a query consisting
-// of a type value or facet value, and a single interface. This is for eval to
-// execute lookup via the LookupImplWitness instruction. It does not consider
-// the self facet value for finding a witness, since LookupImplWitness() would
-// have found that and not caused us to defer lookup to here.
-auto EvalLookupSingleImplWitness(Context& context, SemIR::LocId loc_id,
-                                 SemIR::LookupImplWitness eval_query,
-                                 SemIR::InstId self_facet_value_inst_id,
-                                 EvalImplLookupMode mode)
-    -> EvalImplLookupResult;
+// Looks for a final witness for an impl lookup query consisting of a self (type
+// or facet) and a single interface. This is for eval to execute lookup via the
+// `LookupImplWitness` instruction. Since this query is re-evaluated against
+// specifics, it provides monomorphization of the impl lookup, which allows for
+// finding specializations.
+auto EvalLookupSingleFinalWitness(Context& context, SemIR::LocId loc_id,
+                                  SemIR::LookupImplWitness eval_query,
+                                  SemIR::InstId self_facet_value_inst_id,
+                                  EvalImplLookupMode mode) -> SemIR::ConstantId;
 
 }  // namespace Carbon::Check
 

+ 36 - 0
toolchain/check/require_impls_stack.cpp

@@ -0,0 +1,36 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#include "toolchain/check/require_impls_stack.h"
+
+namespace Carbon::Check {
+
+auto RequireImplsStack::Push(EnclosingScopeId scope_id) -> void {
+  scope_ids_.push_back(scope_id);
+  array_stack_.PushArray();
+}
+
+auto RequireImplsStack::Pop() -> void {
+  scope_ids_.pop_back();
+  array_stack_.PopArray();
+}
+
+auto RequireImplsStack::AppendToTop(SemIR::RequireImplsId id) -> void {
+  array_stack_.AppendToTop(id);
+}
+
+auto RequireImplsStack::PeekTop() const
+    -> llvm::ArrayRef<SemIR::RequireImplsId> {
+  return array_stack_.PeekArray();
+}
+
+auto RequireImplsStack::PeekForScope(EnclosingScopeId scope_id)
+    -> llvm::ArrayRef<SemIR::RequireImplsId> {
+  auto it = std::find(scope_ids_.rbegin(), scope_ids_.rend(), scope_id);
+  CARBON_CHECK(it != scope_ids_.rend());
+  auto index = std::distance(it, scope_ids_.rend()) - 1;
+  return array_stack_.PeekArrayAt(index);
+}
+
+}  // namespace Carbon::Check

+ 44 - 0
toolchain/check/require_impls_stack.h

@@ -0,0 +1,44 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#ifndef CARBON_TOOLCHAIN_CHECK_REQUIRE_IMPLS_STACK_H_
+#define CARBON_TOOLCHAIN_CHECK_REQUIRE_IMPLS_STACK_H_
+
+#include "common/array_stack.h"
+#include "toolchain/sem_ir/ids.h"
+
+namespace Carbon::Check {
+
+// A stack where each frame holds an array of RequireImplsIds and is associated
+// with an enclosing scope that can be searched for in the stack.
+class RequireImplsStack {
+ public:
+  using EnclosingScopeId =
+      std::variant<SemIR::InterfaceId, SemIR::NamedConstraintId>;
+
+  // Push a new stack frame for an interface or named constraint to add
+  // RequireImplsIds.
+  auto Push(EnclosingScopeId scope_id) -> void;
+  // Pop the top stack frame and all its RequireImplsIds.
+  auto Pop() -> void;
+
+  // Append to the top stack frame.
+  auto AppendToTop(SemIR::RequireImplsId id) -> void;
+
+  // Returns the RequireImplsIds in the top stack frame.
+  auto PeekTop() const -> llvm::ArrayRef<SemIR::RequireImplsId>;
+
+  // Finds the stack frame for a given scope and returns the RequireImplsIds in
+  // that stack frame.
+  auto PeekForScope(EnclosingScopeId scope_id)
+      -> llvm::ArrayRef<SemIR::RequireImplsId>;
+
+ private:
+  llvm::SmallVector<EnclosingScopeId> scope_ids_;
+  ArrayStack<SemIR::RequireImplsId> array_stack_;
+};
+
+}  // namespace Carbon::Check
+
+#endif  // CARBON_TOOLCHAIN_CHECK_REQUIRE_IMPLS_STACK_H_

+ 18 - 18
toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon

@@ -813,21 +813,21 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     inst7800016C:    {kind: ImplWitness, arg0: inst78000124, arg1: specific78000021, type: type(inst(WitnessType))}
 // CHECK:STDOUT:     inst7800016D:    {kind: FunctionType, arg0: function78000005, arg1: specific78000021, type: type(TypeType)}
 // CHECK:STDOUT:     inst7800016E:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant7800013C)}
-// CHECK:STDOUT:     inst7800016F:    {kind: RequireSpecificDefinition, arg0: specific7800000B, type: type(inst(RequireSpecificDefinitionType))}
-// CHECK:STDOUT:     inst78000170:    {kind: RequireSpecificDefinition, arg0: specific7800000B, type: type(inst(RequireSpecificDefinitionType))}
-// CHECK:STDOUT:     inst78000171:    {kind: RequireSpecificDefinition, arg0: specific78000022, type: type(inst(RequireSpecificDefinitionType))}
-// CHECK:STDOUT:     inst78000172:    {kind: LookupImplWitness, arg0: inst7800001D, arg1: specific_interface78000000, type: type(inst(WitnessType))}
-// CHECK:STDOUT:     inst78000173:    {kind: LookupImplWitness, arg0: inst7800001E, arg1: specific_interface78000000, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst7800016F:    {kind: LookupImplWitness, arg0: inst7800001D, arg1: specific_interface78000000, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst78000170:    {kind: LookupImplWitness, arg0: inst7800001E, arg1: specific_interface78000000, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst78000171:    {kind: RequireSpecificDefinition, arg0: specific7800000B, type: type(inst(RequireSpecificDefinitionType))}
+// CHECK:STDOUT:     inst78000172:    {kind: RequireSpecificDefinition, arg0: specific7800000B, type: type(inst(RequireSpecificDefinitionType))}
+// CHECK:STDOUT:     inst78000173:    {kind: RequireSpecificDefinition, arg0: specific78000022, type: type(inst(RequireSpecificDefinitionType))}
 // CHECK:STDOUT:     inst78000174:    {kind: FacetValue, arg0: inst7800001D, arg1: inst_block78000088, type: type(inst78000050)}
 // CHECK:STDOUT:     inst78000175:    {kind: FunctionType, arg0: function78000001, arg1: specific78000023, type: type(TypeType)}
 // CHECK:STDOUT:     inst78000176:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant78000144)}
 // CHECK:STDOUT:     inst78000177:    {kind: FunctionTypeWithSelfType, arg0: inst78000175, arg1: inst78000174, type: type(TypeType)}
-// CHECK:STDOUT:     inst78000178:    {kind: ImplWitnessAccess, arg0: inst78000172, arg1: element0, type: type(symbolic_constant7800014A)}
-// CHECK:STDOUT:     inst78000179:    {kind: ImplWitnessAccess, arg0: inst78000172, arg1: element0, type: type(symbolic_constant78000146)}
+// CHECK:STDOUT:     inst78000178:    {kind: ImplWitnessAccess, arg0: inst7800016F, arg1: element0, type: type(symbolic_constant7800014A)}
+// CHECK:STDOUT:     inst78000179:    {kind: ImplWitnessAccess, arg0: inst7800016F, arg1: element0, type: type(symbolic_constant78000146)}
 // CHECK:STDOUT:     inst7800017A:    {kind: FacetValue, arg0: inst7800001E, arg1: inst_block7800008B, type: type(inst78000050)}
 // CHECK:STDOUT:     inst7800017B:    {kind: FunctionType, arg0: function78000001, arg1: specific78000024, type: type(TypeType)}
 // CHECK:STDOUT:     inst7800017C:    {kind: FunctionTypeWithSelfType, arg0: inst7800017B, arg1: inst7800017A, type: type(TypeType)}
-// CHECK:STDOUT:     inst7800017D:    {kind: ImplWitnessAccess, arg0: inst78000173, arg1: element0, type: type(symbolic_constant7800014A)}
+// CHECK:STDOUT:     inst7800017D:    {kind: ImplWitnessAccess, arg0: inst78000170, arg1: element0, type: type(symbolic_constant7800014A)}
 // CHECK:STDOUT:     inst7800017E:    {kind: BoundMethod, arg0: inst78000048, arg1: inst78000178, type: type(inst(BoundMethodType))}
 // CHECK:STDOUT:     inst7800017F:    {kind: SpecificImplFunction, arg0: inst78000178, arg1: specific78000025, type: type(inst(SpecificFunctionType))}
 // CHECK:STDOUT:     inst78000180:    {kind: SpecificImplFunction, arg0: inst78000179, arg1: specific78000025, type: type(inst(SpecificFunctionType))}
@@ -930,7 +930,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       inst7800006B:    concrete_constant(inst7800006B)
 // CHECK:STDOUT:       inst7800006C:    symbolic_constant78000017
 // CHECK:STDOUT:       inst7800006D:    concrete_constant(inst7800006D)
-// CHECK:STDOUT:       inst7800006E:    symbolic_constant78000142
+// CHECK:STDOUT:       inst7800006E:    symbolic_constant7800013F
 // CHECK:STDOUT:       inst7800006F:    constant<none>
 // CHECK:STDOUT:       inst78000070:    concrete_constant(inst78000070)
 // CHECK:STDOUT:       inst78000071:    symbolic_constant7800002B
@@ -1000,7 +1000,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       inst780000B1:    concrete_constant(inst780000B1)
 // CHECK:STDOUT:       inst780000B2:    concrete_constant(inst(IntLiteralType))
 // CHECK:STDOUT:       inst780000B3:    concrete_constant(inst78000050)
-// CHECK:STDOUT:       inst780000B4:    symbolic_constant7800013E
+// CHECK:STDOUT:       inst780000B4:    symbolic_constant78000140
 // CHECK:STDOUT:       inst780000B5:    concrete_constant(inst780000B5)
 // CHECK:STDOUT:       inst780000B6:    constant<none>
 // CHECK:STDOUT:       inst780000B7:    concrete_constant(inst780000B7)
@@ -1187,9 +1187,9 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       inst7800016C:    symbolic_constant7800013A
 // CHECK:STDOUT:       inst7800016D:    symbolic_constant7800013C
 // CHECK:STDOUT:       inst7800016E:    symbolic_constant7800013D
-// CHECK:STDOUT:       inst7800016F:    symbolic_constant78000140
+// CHECK:STDOUT:       inst7800016F:    symbolic_constant7800013E
 // CHECK:STDOUT:       inst78000170:    symbolic_constant7800013F
-// CHECK:STDOUT:       inst78000171:    symbolic_constant78000140
+// CHECK:STDOUT:       inst78000171:    symbolic_constant78000142
 // CHECK:STDOUT:       inst78000172:    symbolic_constant78000141
 // CHECK:STDOUT:       inst78000173:    symbolic_constant78000142
 // CHECK:STDOUT:       inst78000174:    symbolic_constant78000143
@@ -1526,9 +1526,9 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       symbolic_constant7800013B: {inst: inst78000128, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_def1}}
 // CHECK:STDOUT:       symbolic_constant7800013C: {inst: inst78000127, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_def0}}
 // CHECK:STDOUT:       symbolic_constant7800013D: {inst: inst78000128, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_def1}}
-// CHECK:STDOUT:       symbolic_constant7800013E: {inst: inst780000B8, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_decl2}}
-// CHECK:STDOUT:       symbolic_constant7800013F: {inst: inst78000170, kind: checked, attached: null}
-// CHECK:STDOUT:       symbolic_constant78000140: {inst: inst78000170, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_def2}}
+// CHECK:STDOUT:       symbolic_constant7800013E: {inst: inst7800016F, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant7800013F: {inst: inst7800016F, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_def2}}
+// CHECK:STDOUT:       symbolic_constant78000140: {inst: inst780000B8, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_decl2}}
 // CHECK:STDOUT:       symbolic_constant78000141: {inst: inst78000172, kind: checked, attached: null}
 // CHECK:STDOUT:       symbolic_constant78000142: {inst: inst78000172, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_def3}}
 // CHECK:STDOUT:       symbolic_constant78000143: {inst: inst78000174, kind: checked, attached: null}
@@ -2171,7 +2171,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     inst_block78000087:
 // CHECK:STDOUT:       0:               inst78000019
 // CHECK:STDOUT:     inst_block78000088:
-// CHECK:STDOUT:       0:               inst78000172
+// CHECK:STDOUT:       0:               inst7800016F
 // CHECK:STDOUT:     inst_block78000089:
 // CHECK:STDOUT:       0:               inst78000174
 // CHECK:STDOUT:     inst_block7800008A:
@@ -2179,7 +2179,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       1:               inst78000175
 // CHECK:STDOUT:       2:               inst78000176
 // CHECK:STDOUT:     inst_block7800008B:
-// CHECK:STDOUT:       0:               inst78000173
+// CHECK:STDOUT:       0:               inst78000170
 // CHECK:STDOUT:     inst_block7800008C:
 // CHECK:STDOUT:       0:               inst7800017A
 // CHECK:STDOUT:     inst_block7800008D:
@@ -2197,7 +2197,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     inst_block78000091:
 // CHECK:STDOUT:       0:               inst78000043
 // CHECK:STDOUT:       1:               inst78000047
-// CHECK:STDOUT:       2:               inst78000171
+// CHECK:STDOUT:       2:               inst78000170
 // CHECK:STDOUT:       3:               inst78000173
 // CHECK:STDOUT:       4:               inst7800017A
 // CHECK:STDOUT:       5:               inst7800017B

+ 2 - 2
toolchain/check/testdata/class/generic/basic.carbon

@@ -63,8 +63,8 @@ class Declaration(T:! type);
 // CHECK:STDOUT:   %specific_impl_fn.bdc: <specific function> = specific_impl_function %impl.elem0.594, @Copy.WithSelf.Op(%T.035) [symbolic]
 // CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]
-// CHECK:STDOUT:   %.3a3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.2e7: <witness> = lookup_impl_witness %ptr.e7d, @Copy [symbolic]
+// CHECK:STDOUT:   %.3a3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.e7d, (%Copy.lookup_impl_witness.2e7) [symbolic]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.486: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic]
 // CHECK:STDOUT:   %.b63: type = fn_type_with_self_type %Copy.WithSelf.Op.type.486, %Copy.facet [symbolic]
@@ -195,8 +195,8 @@ class Declaration(T:! type);
 // CHECK:STDOUT:   %require_complete.loc6_22: <witness> = require_complete_type %Class [symbolic = %require_complete.loc6_22 (constants.%require_complete.904)]
 // CHECK:STDOUT:   %require_complete.loc6_36: <witness> = require_complete_type %ptr.loc6_36.1 [symbolic = %require_complete.loc6_36 (constants.%require_complete.9dc)]
 // CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.binding.as_type [symbolic = %Class.elem (constants.%Class.elem)]
-// CHECK:STDOUT:   %.loc7_12.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic = %.loc7_12.1 (constants.%.3a3)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc6_36.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e7)]
+// CHECK:STDOUT:   %.loc7_12.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic = %.loc7_12.1 (constants.%.3a3)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.loc6_36.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.486)]
 // CHECK:STDOUT:   %.loc7_12.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc7_12.2 (constants.%.b63)]

+ 3 - 3
toolchain/check/testdata/class/generic/member_access.carbon

@@ -91,8 +91,8 @@ fn StaticMemberFunctionCall(T:! type) -> Class(T) {
 // CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]
 // CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]
-// CHECK:STDOUT:   %.3a3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.2e7: <witness> = lookup_impl_witness %ptr.e7d, @Copy [symbolic]
+// CHECK:STDOUT:   %.3a3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic]
 // CHECK:STDOUT:   %Copy.facet.8e7: %Copy.type = facet_value %ptr.e7d, (%Copy.lookup_impl_witness.2e7) [symbolic]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.486: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.8e7) [symbolic]
 // CHECK:STDOUT:   %.b63: type = fn_type_with_self_type %Copy.WithSelf.Op.type.486, %Copy.facet.8e7 [symbolic]
@@ -201,8 +201,8 @@ fn StaticMemberFunctionCall(T:! type) -> Class(T) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.binding.as_type [symbolic = %Class.elem (constants.%Class.elem.05d)]
-// CHECK:STDOUT:   %.loc15_12.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic = %.loc15_12.1 (constants.%.3a3)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc13_36.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e7)]
+// CHECK:STDOUT:   %.loc15_12.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic = %.loc15_12.1 (constants.%.3a3)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.loc13_36.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet.8e7)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.486)]
 // CHECK:STDOUT:   %.loc15_12.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc15_12.2 (constants.%.b63)]
@@ -355,8 +355,8 @@ fn StaticMemberFunctionCall(T:! type) -> Class(T) {
 // CHECK:STDOUT:   %require_complete.loc13_22 => constants.%complete_type.1ec
 // CHECK:STDOUT:   %require_complete.loc13_36 => constants.%complete_type.3d0
 // CHECK:STDOUT:   %Class.elem => constants.%Class.elem.da5
-// CHECK:STDOUT:   %.loc15_12.1 => constants.%.cab
 // CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.impl_witness.843
+// CHECK:STDOUT:   %.loc15_12.1 => constants.%.cab
 // CHECK:STDOUT:   %Copy.facet => constants.%Copy.facet.a7b
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.e01
 // CHECK:STDOUT:   %.loc15_12.2 => constants.%.a62

+ 3 - 3
toolchain/check/testdata/class/generic/member_type.carbon

@@ -446,8 +446,8 @@ fn Test() -> i32 {
 // CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
 // CHECK:STDOUT:   %require_complete.4fd: <witness> = require_complete_type %C.131 [symbolic]
 // CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]
-// CHECK:STDOUT:   %.1f8: require_specific_def_type = require_specific_def @C.as.Inner.impl(%T) [symbolic]
 // CHECK:STDOUT:   %Inner.lookup_impl_witness: <witness> = lookup_impl_witness %C.131, @Inner, @Inner(%T) [symbolic]
+// CHECK:STDOUT:   %.1f8: require_specific_def_type = require_specific_def @C.as.Inner.impl(%T) [symbolic]
 // CHECK:STDOUT:   %Inner.facet.f78: %Inner.type.6ef = facet_value %C.131, (%Inner.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %Inner.WithSelf.F.type.d96: type = fn_type @Inner.WithSelf.F, @Inner.WithSelf(%T, %Inner.facet.f78) [symbolic]
 // CHECK:STDOUT:   %Inner.WithSelf.F.66d: %Inner.WithSelf.F.type.d96 = struct_value () [symbolic]
@@ -731,8 +731,8 @@ fn Test() -> i32 {
 // CHECK:STDOUT:   %require_complete.loc11_48: <witness> = require_complete_type %Inner.type [symbolic = %require_complete.loc11_48 (constants.%require_complete.8b6)]
 // CHECK:STDOUT:   %Inner.assoc_type: type = assoc_entity_type @Inner, @Inner(%T) [symbolic = %Inner.assoc_type (constants.%Inner.assoc_type.be2)]
 // CHECK:STDOUT:   %assoc0: @C.as.Inner.impl.F.%Inner.assoc_type (%Inner.assoc_type.be2) = assoc_entity element0, @Inner.WithSelf.%Inner.WithSelf.F.decl [symbolic = %assoc0 (constants.%assoc0.058)]
-// CHECK:STDOUT:   %.loc11_41.1: require_specific_def_type = require_specific_def @C.as.Inner.impl(%T) [symbolic = %.loc11_41.1 (constants.%.1f8)]
 // CHECK:STDOUT:   %Inner.lookup_impl_witness: <witness> = lookup_impl_witness %C, @Inner, @Inner(%T) [symbolic = %Inner.lookup_impl_witness (constants.%Inner.lookup_impl_witness)]
+// CHECK:STDOUT:   %.loc11_41.1: require_specific_def_type = require_specific_def @C.as.Inner.impl(%T) [symbolic = %.loc11_41.1 (constants.%.1f8)]
 // CHECK:STDOUT:   %Inner.facet: @C.as.Inner.impl.F.%Inner.type (%Inner.type.6ef) = facet_value %C, (%Inner.lookup_impl_witness) [symbolic = %Inner.facet (constants.%Inner.facet.f78)]
 // CHECK:STDOUT:   %Inner.WithSelf.F.type: type = fn_type @Inner.WithSelf.F, @Inner.WithSelf(%T, %Inner.facet) [symbolic = %Inner.WithSelf.F.type (constants.%Inner.WithSelf.F.type.d96)]
 // CHECK:STDOUT:   %.loc11_41.2: type = fn_type_with_self_type %Inner.WithSelf.F.type, %Inner.facet [symbolic = %.loc11_41.2 (constants.%.29b)]
@@ -988,8 +988,8 @@ fn Test() -> i32 {
 // CHECK:STDOUT:   %require_complete.loc11_48 => constants.%complete_type.087
 // CHECK:STDOUT:   %Inner.assoc_type => constants.%Inner.assoc_type.564
 // CHECK:STDOUT:   %assoc0 => constants.%assoc0.958
-// CHECK:STDOUT:   %.loc11_41.1 => constants.%.c0b
 // CHECK:STDOUT:   %Inner.lookup_impl_witness => constants.%Inner.impl_witness.d48
+// CHECK:STDOUT:   %.loc11_41.1 => constants.%.c0b
 // CHECK:STDOUT:   %Inner.facet => constants.%Inner.facet.ac9
 // CHECK:STDOUT:   %Inner.WithSelf.F.type => constants.%Inner.WithSelf.F.type.96b
 // CHECK:STDOUT:   %.loc11_41.2 => constants.%.fd6

+ 4 - 0
toolchain/check/testdata/deduce/binding_pattern.carbon

@@ -99,6 +99,7 @@ fn F(unused U:! type, V:! type where {} impls Core.ImplicitAs(.Self)) {
 // CHECK:STDOUT:   %assoc0.3d8: %ImplicitAs.assoc_type.d88 = assoc_entity element0, imports.%Core.import_ref.201 [symbolic]
 // CHECK:STDOUT:   %require_complete.cc6: <witness> = require_complete_type %ImplicitAs.type.1e5 [symbolic]
 // CHECK:STDOUT:   %assoc0.843: %ImplicitAs.assoc_type.ff3 = assoc_entity element0, imports.%Core.import_ref.cc1 [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.lookup_impl_witness: <witness> = lookup_impl_witness %empty_struct_type, @ImplicitAs, @ImplicitAs(%V) [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -200,6 +201,7 @@ fn F(unused U:! type, V:! type where {} impls Core.ImplicitAs(.Self)) {
 // CHECK:STDOUT:   %require_complete.loc19_16.2: <witness> = require_complete_type %ImplicitAs.type.loc19_16.2 [symbolic = %require_complete.loc19_16.2 (constants.%require_complete.cc6)]
 // CHECK:STDOUT:   %ImplicitAs.assoc_type: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%V.loc8_23.1) [symbolic = %ImplicitAs.assoc_type (constants.%ImplicitAs.assoc_type.d88)]
 // CHECK:STDOUT:   %assoc0: @F.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.d88) = assoc_entity element0, imports.%Core.import_ref.201 [symbolic = %assoc0 (constants.%assoc0.3d8)]
+// CHECK:STDOUT:   %ImplicitAs.lookup_impl_witness: <witness> = lookup_impl_witness constants.%empty_struct_type, @ImplicitAs, @ImplicitAs(%V.loc8_23.1) [symbolic = %ImplicitAs.lookup_impl_witness (constants.%ImplicitAs.lookup_impl_witness)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn() {
 // CHECK:STDOUT:   !entry:
@@ -300,6 +302,7 @@ fn F(unused U:! type, V:! type where {} impls Core.ImplicitAs(.Self)) {
 // CHECK:STDOUT:   %assoc0.a1c: %ImplicitAs.assoc_type.f30 = assoc_entity element0, imports.%Core.import_ref.201 [symbolic]
 // CHECK:STDOUT:   %require_complete.24c: <witness> = require_complete_type %ImplicitAs.type.ee4 [symbolic]
 // CHECK:STDOUT:   %assoc0.843: %ImplicitAs.assoc_type.ff3 = assoc_entity element0, imports.%Core.import_ref.cc1 [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.lookup_impl_witness: <witness> = lookup_impl_witness %empty_struct_type, @ImplicitAs, @ImplicitAs(%V.binding.as_type) [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -413,6 +416,7 @@ fn F(unused U:! type, V:! type where {} impls Core.ImplicitAs(.Self)) {
 // CHECK:STDOUT:   %require_complete.loc20_16.2: <witness> = require_complete_type %ImplicitAs.type.loc20_16.2 [symbolic = %require_complete.loc20_16.2 (constants.%require_complete.24c)]
 // CHECK:STDOUT:   %ImplicitAs.assoc_type: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%V.binding.as_type) [symbolic = %ImplicitAs.assoc_type (constants.%ImplicitAs.assoc_type.f30)]
 // CHECK:STDOUT:   %assoc0: @F.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.f30) = assoc_entity element0, imports.%Core.import_ref.201 [symbolic = %assoc0 (constants.%assoc0.a1c)]
+// CHECK:STDOUT:   %ImplicitAs.lookup_impl_witness: <witness> = lookup_impl_witness constants.%empty_struct_type, @ImplicitAs, @ImplicitAs(%V.binding.as_type) [symbolic = %ImplicitAs.lookup_impl_witness (constants.%ImplicitAs.lookup_impl_witness)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn() {
 // CHECK:STDOUT:   !entry:

+ 8 - 8
toolchain/check/testdata/eval/aggregates.carbon

@@ -493,8 +493,8 @@ fn G(N:! i32) {
 // CHECK:STDOUT:   %require_complete.666: <witness> = require_complete_type %tuple.type.3c8 [symbolic]
 // CHECK:STDOUT:   %pattern_type.4ac: type = pattern_type %tuple.type.3c8 [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]
-// CHECK:STDOUT:   %.f7e: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%tuple.type.3c8) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness.2ad: <witness> = lookup_impl_witness %tuple.type.3c8, @DefaultOrUnformed [symbolic]
+// CHECK:STDOUT:   %.f7e: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%tuple.type.3c8) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.facet.9a0: %DefaultOrUnformed.type = facet_value %tuple.type.3c8, (%DefaultOrUnformed.lookup_impl_witness.2ad) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.0af: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.9a0) [symbolic]
 // CHECK:STDOUT:   %.246: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.0af, %DefaultOrUnformed.facet.9a0 [symbolic]
@@ -503,8 +503,8 @@ fn G(N:! i32) {
 // CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %T.67d} [symbolic]
 // CHECK:STDOUT:   %require_complete.5d6: <witness> = require_complete_type %struct_type.a [symbolic]
 // CHECK:STDOUT:   %pattern_type.7b9: type = pattern_type %struct_type.a [symbolic]
-// CHECK:STDOUT:   %.d26: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%struct_type.a) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness.169: <witness> = lookup_impl_witness %struct_type.a, @DefaultOrUnformed [symbolic]
+// CHECK:STDOUT:   %.d26: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%struct_type.a) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.facet.ca5: %DefaultOrUnformed.type = facet_value %struct_type.a, (%DefaultOrUnformed.lookup_impl_witness.169) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.0c5: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.ca5) [symbolic]
 // CHECK:STDOUT:   %.9ac: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.0c5, %DefaultOrUnformed.facet.ca5 [symbolic]
@@ -514,8 +514,8 @@ fn G(N:! i32) {
 // CHECK:STDOUT:   %array_type.742: type = array_type %int_5, %T.67d [symbolic]
 // CHECK:STDOUT:   %require_complete.345: <witness> = require_complete_type %array_type.742 [symbolic]
 // CHECK:STDOUT:   %pattern_type.d52: type = pattern_type %array_type.742 [symbolic]
-// CHECK:STDOUT:   %.617: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%array_type.742) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness.945: <witness> = lookup_impl_witness %array_type.742, @DefaultOrUnformed [symbolic]
+// CHECK:STDOUT:   %.617: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%array_type.742) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.facet.ad6: %DefaultOrUnformed.type = facet_value %array_type.742, (%DefaultOrUnformed.lookup_impl_witness.945) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.2f0: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.ad6) [symbolic]
 // CHECK:STDOUT:   %.544: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.2f0, %DefaultOrUnformed.facet.ad6 [symbolic]
@@ -560,8 +560,8 @@ fn G(N:! i32) {
 // CHECK:STDOUT:   %array_type.2ec: type = array_type %Int.as.ImplicitAs.impl.Convert.call, %i32 [symbolic]
 // CHECK:STDOUT:   %require_complete.5d1: <witness> = require_complete_type %array_type.2ec [symbolic]
 // CHECK:STDOUT:   %pattern_type.99c: type = pattern_type %array_type.2ec [symbolic]
-// CHECK:STDOUT:   %.d6f: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%array_type.2ec) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness.162: <witness> = lookup_impl_witness %array_type.2ec, @DefaultOrUnformed [symbolic]
+// CHECK:STDOUT:   %.d6f: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%array_type.2ec) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.facet.0c7: %DefaultOrUnformed.type = facet_value %array_type.2ec, (%DefaultOrUnformed.lookup_impl_witness.162) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.839: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.0c7) [symbolic]
 // CHECK:STDOUT:   %.78e: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.839, %DefaultOrUnformed.facet.0c7 [symbolic]
@@ -590,8 +590,8 @@ fn G(N:! i32) {
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (%ptr.loc6_19.2, %const.loc6_22.2) [symbolic = %tuple.type (constants.%tuple.type.3c8)]
 // CHECK:STDOUT:   %require_complete.loc6: <witness> = require_complete_type %tuple.type [symbolic = %require_complete.loc6 (constants.%require_complete.666)]
 // CHECK:STDOUT:   %pattern_type.loc6: type = pattern_type %tuple.type [symbolic = %pattern_type.loc6 (constants.%pattern_type.4ac)]
-// CHECK:STDOUT:   %.loc6_30.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%tuple.type) [symbolic = %.loc6_30.3 (constants.%.f7e)]
 // CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness.loc6: <witness> = lookup_impl_witness %tuple.type, @DefaultOrUnformed [symbolic = %DefaultOrUnformed.lookup_impl_witness.loc6 (constants.%DefaultOrUnformed.lookup_impl_witness.2ad)]
+// CHECK:STDOUT:   %.loc6_30.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%tuple.type) [symbolic = %.loc6_30.3 (constants.%.f7e)]
 // CHECK:STDOUT:   %DefaultOrUnformed.facet.loc6_30.2: %DefaultOrUnformed.type = facet_value %tuple.type, (%DefaultOrUnformed.lookup_impl_witness.loc6) [symbolic = %DefaultOrUnformed.facet.loc6_30.2 (constants.%DefaultOrUnformed.facet.9a0)]
 // CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.loc6: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.loc6_30.2) [symbolic = %DefaultOrUnformed.WithSelf.Op.type.loc6 (constants.%DefaultOrUnformed.WithSelf.Op.type.0af)]
 // CHECK:STDOUT:   %.loc6_30.4: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.loc6, %DefaultOrUnformed.facet.loc6_30.2 [symbolic = %.loc6_30.4 (constants.%.246)]
@@ -600,8 +600,8 @@ fn G(N:! i32) {
 // CHECK:STDOUT:   %struct_type.a.loc7_23.2: type = struct_type {.a: @F.%T.loc4_6.1 (%T.67d)} [symbolic = %struct_type.a.loc7_23.2 (constants.%struct_type.a)]
 // CHECK:STDOUT:   %require_complete.loc7: <witness> = require_complete_type %struct_type.a.loc7_23.2 [symbolic = %require_complete.loc7 (constants.%require_complete.5d6)]
 // CHECK:STDOUT:   %pattern_type.loc7: type = pattern_type %struct_type.a.loc7_23.2 [symbolic = %pattern_type.loc7 (constants.%pattern_type.7b9)]
-// CHECK:STDOUT:   %.loc7_24.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%struct_type.a.loc7_23.2) [symbolic = %.loc7_24.3 (constants.%.d26)]
 // CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness.loc7: <witness> = lookup_impl_witness %struct_type.a.loc7_23.2, @DefaultOrUnformed [symbolic = %DefaultOrUnformed.lookup_impl_witness.loc7 (constants.%DefaultOrUnformed.lookup_impl_witness.169)]
+// CHECK:STDOUT:   %.loc7_24.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%struct_type.a.loc7_23.2) [symbolic = %.loc7_24.3 (constants.%.d26)]
 // CHECK:STDOUT:   %DefaultOrUnformed.facet.loc7_24.2: %DefaultOrUnformed.type = facet_value %struct_type.a.loc7_23.2, (%DefaultOrUnformed.lookup_impl_witness.loc7) [symbolic = %DefaultOrUnformed.facet.loc7_24.2 (constants.%DefaultOrUnformed.facet.ca5)]
 // CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.loc7: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.loc7_24.2) [symbolic = %DefaultOrUnformed.WithSelf.Op.type.loc7 (constants.%DefaultOrUnformed.WithSelf.Op.type.0c5)]
 // CHECK:STDOUT:   %.loc7_24.4: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.loc7, %DefaultOrUnformed.facet.loc7_24.2 [symbolic = %.loc7_24.4 (constants.%.9ac)]
@@ -610,8 +610,8 @@ fn G(N:! i32) {
 // CHECK:STDOUT:   %array_type.loc8_27.2: type = array_type constants.%int_5, %T.loc4_6.1 [symbolic = %array_type.loc8_27.2 (constants.%array_type.742)]
 // CHECK:STDOUT:   %require_complete.loc8: <witness> = require_complete_type %array_type.loc8_27.2 [symbolic = %require_complete.loc8 (constants.%require_complete.345)]
 // CHECK:STDOUT:   %pattern_type.loc8: type = pattern_type %array_type.loc8_27.2 [symbolic = %pattern_type.loc8 (constants.%pattern_type.d52)]
-// CHECK:STDOUT:   %.loc8_28.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%array_type.loc8_27.2) [symbolic = %.loc8_28.3 (constants.%.617)]
 // CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness.loc8: <witness> = lookup_impl_witness %array_type.loc8_27.2, @DefaultOrUnformed [symbolic = %DefaultOrUnformed.lookup_impl_witness.loc8 (constants.%DefaultOrUnformed.lookup_impl_witness.945)]
+// CHECK:STDOUT:   %.loc8_28.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%array_type.loc8_27.2) [symbolic = %.loc8_28.3 (constants.%.617)]
 // CHECK:STDOUT:   %DefaultOrUnformed.facet.loc8_28.2: %DefaultOrUnformed.type = facet_value %array_type.loc8_27.2, (%DefaultOrUnformed.lookup_impl_witness.loc8) [symbolic = %DefaultOrUnformed.facet.loc8_28.2 (constants.%DefaultOrUnformed.facet.ad6)]
 // CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.loc8: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.loc8_28.2) [symbolic = %DefaultOrUnformed.WithSelf.Op.type.loc8 (constants.%DefaultOrUnformed.WithSelf.Op.type.2f0)]
 // CHECK:STDOUT:   %.loc8_28.4: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.loc8, %DefaultOrUnformed.facet.loc8_28.2 [symbolic = %.loc8_28.4 (constants.%.544)]
@@ -728,8 +728,8 @@ fn G(N:! i32) {
 // CHECK:STDOUT:   %array_type.loc14_29.2: type = array_type %Int.as.ImplicitAs.impl.Convert.call.loc14_28.2, constants.%i32 [symbolic = %array_type.loc14_29.2 (constants.%array_type.2ec)]
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %array_type.loc14_29.2 [symbolic = %require_complete (constants.%require_complete.5d1)]
 // CHECK:STDOUT:   %pattern_type: type = pattern_type %array_type.loc14_29.2 [symbolic = %pattern_type (constants.%pattern_type.99c)]
-// CHECK:STDOUT:   %.loc14_30.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%array_type.loc14_29.2) [symbolic = %.loc14_30.3 (constants.%.d6f)]
 // CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness: <witness> = lookup_impl_witness %array_type.loc14_29.2, @DefaultOrUnformed [symbolic = %DefaultOrUnformed.lookup_impl_witness (constants.%DefaultOrUnformed.lookup_impl_witness.162)]
+// CHECK:STDOUT:   %.loc14_30.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%array_type.loc14_29.2) [symbolic = %.loc14_30.3 (constants.%.d6f)]
 // CHECK:STDOUT:   %DefaultOrUnformed.facet.loc14_30.2: %DefaultOrUnformed.type = facet_value %array_type.loc14_29.2, (%DefaultOrUnformed.lookup_impl_witness) [symbolic = %DefaultOrUnformed.facet.loc14_30.2 (constants.%DefaultOrUnformed.facet.0c7)]
 // CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.loc14_30.2) [symbolic = %DefaultOrUnformed.WithSelf.Op.type (constants.%DefaultOrUnformed.WithSelf.Op.type.839)]
 // CHECK:STDOUT:   %.loc14_30.4: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type, %DefaultOrUnformed.facet.loc14_30.2 [symbolic = %.loc14_30.4 (constants.%.78e)]

+ 2 - 2
toolchain/check/testdata/facet/convert_facet_value_to_narrowed_facet_type.carbon

@@ -558,11 +558,11 @@ fn CallsWithTypeExplicit(U:! type) {
 // CHECK:STDOUT:   %HandleTameAnimal2.type: type = fn_type @HandleTameAnimal2 [concrete]
 // CHECK:STDOUT:   %HandleTameAnimal2: %HandleTameAnimal2.type = struct_value () [concrete]
 // CHECK:STDOUT:   %require_complete.80f: <witness> = require_complete_type %W.binding.as_type [symbolic]
+// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %W, @Eats [symbolic]
 // CHECK:STDOUT:   %Animal.lookup_impl_witness: <witness> = lookup_impl_witness %W, @Animal [symbolic]
 // CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value %W.binding.as_type, (%Animal.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %Eats.impl_witness.8ab: <witness> = impl_witness @A.binding.as_type.as.Eats.impl.%Eats.impl_witness_table, @A.binding.as_type.as.Eats.impl(%Animal.facet) [symbolic]
 // CHECK:STDOUT:   %.3cf: require_specific_def_type = require_specific_def @A.binding.as_type.as.Eats.impl(%Animal.facet) [symbolic]
-// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %W, @Eats [symbolic]
 // CHECK:STDOUT:   %Tame.lookup_impl_witness: <witness> = lookup_impl_witness %W, @Tame [symbolic]
 // CHECK:STDOUT:   %facet_value: %facet_type.2db = facet_value %W.binding.as_type, (%Eats.lookup_impl_witness, %Tame.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %FeedTame2.specific_fn: <specific function> = specific_function %FeedTame2, @FeedTame2(%facet_value) [symbolic]
@@ -725,10 +725,10 @@ fn CallsWithTypeExplicit(U:! type) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %W.binding.as_type [symbolic = %require_complete (constants.%require_complete.80f)]
+// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %W.loc11_22.1, @Eats [symbolic = %Eats.lookup_impl_witness (constants.%Eats.lookup_impl_witness)]
 // CHECK:STDOUT:   %Animal.lookup_impl_witness: <witness> = lookup_impl_witness %W.loc11_22.1, @Animal [symbolic = %Animal.lookup_impl_witness (constants.%Animal.lookup_impl_witness)]
 // CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value %W.binding.as_type, (%Animal.lookup_impl_witness) [symbolic = %Animal.facet (constants.%Animal.facet)]
 // CHECK:STDOUT:   %.loc12_14.2: require_specific_def_type = require_specific_def @A.binding.as_type.as.Eats.impl(%Animal.facet) [symbolic = %.loc12_14.2 (constants.%.3cf)]
-// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %W.loc11_22.1, @Eats [symbolic = %Eats.lookup_impl_witness (constants.%Eats.lookup_impl_witness)]
 // CHECK:STDOUT:   %Tame.lookup_impl_witness: <witness> = lookup_impl_witness %W.loc11_22.1, @Tame [symbolic = %Tame.lookup_impl_witness (constants.%Tame.lookup_impl_witness)]
 // CHECK:STDOUT:   %facet_value.loc12_14.2: %facet_type.2db = facet_value %W.binding.as_type, (%Eats.lookup_impl_witness, %Tame.lookup_impl_witness) [symbolic = %facet_value.loc12_14.2 (constants.%facet_value)]
 // CHECK:STDOUT:   %FeedTame2.specific_fn.loc12_3.2: <specific function> = specific_function constants.%FeedTame2, @FeedTame2(%facet_value.loc12_14.2) [symbolic = %FeedTame2.specific_fn.loc12_3.2 (constants.%FeedTame2.specific_fn)]

+ 2 - 2
toolchain/check/testdata/facet/convert_facet_value_value_to_blanket_impl.carbon

@@ -49,9 +49,9 @@ fn HandleAnimal[T:! Animal](a: T) { Feed(a); }
 // CHECK:STDOUT:   %HandleAnimal.type: type = fn_type @HandleAnimal [concrete]
 // CHECK:STDOUT:   %HandleAnimal: %HandleAnimal.type = struct_value () [concrete]
 // CHECK:STDOUT:   %require_complete.72f: <witness> = require_complete_type %T.binding.as_type.e4f [symbolic]
+// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %T.998, @Eats [symbolic]
 // CHECK:STDOUT:   %Eats.impl_witness.760d13.2: <witness> = impl_witness @A.binding.as_type.as.Eats.impl.%Eats.impl_witness_table, @A.binding.as_type.as.Eats.impl(%T.998) [symbolic]
 // CHECK:STDOUT:   %.860: require_specific_def_type = require_specific_def @A.binding.as_type.as.Eats.impl(%T.998) [symbolic]
-// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %T.998, @Eats [symbolic]
 // CHECK:STDOUT:   %Eats.facet.a05: %Eats.type = facet_value %T.binding.as_type.e4f, (%Eats.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %Feed.specific_fn: <specific function> = specific_function %Feed, @Feed(%Eats.facet.a05) [symbolic]
 // CHECK:STDOUT: }
@@ -184,8 +184,8 @@ fn HandleAnimal[T:! Animal](a: T) { Feed(a); }
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.72f)]
-// CHECK:STDOUT:   %.loc22_43.2: require_specific_def_type = require_specific_def @A.binding.as_type.as.Eats.impl(%T.loc22_17.1) [symbolic = %.loc22_43.2 (constants.%.860)]
 // CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc22_17.1, @Eats [symbolic = %Eats.lookup_impl_witness (constants.%Eats.lookup_impl_witness)]
+// CHECK:STDOUT:   %.loc22_43.2: require_specific_def_type = require_specific_def @A.binding.as_type.as.Eats.impl(%T.loc22_17.1) [symbolic = %.loc22_43.2 (constants.%.860)]
 // CHECK:STDOUT:   %Eats.facet.loc22_43.2: %Eats.type = facet_value %T.binding.as_type, (%Eats.lookup_impl_witness) [symbolic = %Eats.facet.loc22_43.2 (constants.%Eats.facet.a05)]
 // CHECK:STDOUT:   %Feed.specific_fn.loc22_37.2: <specific function> = specific_function constants.%Feed, @Feed(%Eats.facet.loc22_43.2) [symbolic = %Feed.specific_fn.loc22_37.2 (constants.%Feed.specific_fn)]
 // CHECK:STDOUT:

+ 11 - 11
toolchain/check/testdata/facet/convert_facet_value_value_to_generic_facet_value_value.carbon

@@ -94,10 +94,10 @@ fn F() {
 // CHECK:STDOUT:   %require_complete.72f: <witness> = require_complete_type %A.binding.as_type [symbolic]
 // CHECK:STDOUT:   %require_complete.0a9: <witness> = require_complete_type %Food.binding.as_type.e7e [symbolic]
 // CHECK:STDOUT:   %Eats.type.bb4cf6.2: type = facet_type <@Eats, @Eats(%Food.binding.as_type.e7e)> [symbolic]
+// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %A, @Eats, @Eats(%Food.binding.as_type.e7e) [symbolic]
 // CHECK:STDOUT:   %Eats.impl_witness.0150b7.2: <witness> = impl_witness @T.binding.as_type.as.Eats.impl.%Eats.impl_witness_table, @T.binding.as_type.as.Eats.impl(%A, %Food.2fc) [symbolic]
 // CHECK:STDOUT:   %require_complete.a2722e.2: <witness> = require_complete_type %Eats.type.bb4cf6.2 [symbolic]
 // CHECK:STDOUT:   %.f9e: require_specific_def_type = require_specific_def @T.binding.as_type.as.Eats.impl(%A, %Food.2fc) [symbolic]
-// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %A, @Eats, @Eats(%Food.binding.as_type.e7e) [symbolic]
 // CHECK:STDOUT:   %Eats.facet.702: %Eats.type.bb4cf6.2 = facet_value %A.binding.as_type, (%Eats.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %pattern_type.67b: type = pattern_type %Eats.type.bb4cf6.2 [symbolic]
 // CHECK:STDOUT:   %Feed.specific_fn.1f9: <specific function> = specific_function %Feed, @Feed(%Food.2fc, %Eats.facet.702) [symbolic]
@@ -387,8 +387,8 @@ fn F() {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete.loc32_45: <witness> = require_complete_type %A.binding.as_type [symbolic = %require_complete.loc32_45 (constants.%require_complete.72f)]
 // CHECK:STDOUT:   %require_complete.loc32_54: <witness> = require_complete_type %Food.binding.as_type [symbolic = %require_complete.loc32_54 (constants.%require_complete.0a9)]
-// CHECK:STDOUT:   %.loc32_76.3: require_specific_def_type = require_specific_def @T.binding.as_type.as.Eats.impl(%A.loc32_17.1, %Food.loc32_29.1) [symbolic = %.loc32_76.3 (constants.%.f9e)]
 // CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %A.loc32_17.1, @Eats, @Eats(%Food.binding.as_type) [symbolic = %Eats.lookup_impl_witness (constants.%Eats.lookup_impl_witness)]
+// CHECK:STDOUT:   %.loc32_76.3: require_specific_def_type = require_specific_def @T.binding.as_type.as.Eats.impl(%A.loc32_17.1, %Food.loc32_29.1) [symbolic = %.loc32_76.3 (constants.%.f9e)]
 // CHECK:STDOUT:   %Eats.type: type = facet_type <@Eats, @Eats(%Food.binding.as_type)> [symbolic = %Eats.type (constants.%Eats.type.bb4cf6.2)]
 // CHECK:STDOUT:   %Eats.facet.loc32_76.2: @HandleAnimal.%Eats.type (%Eats.type.bb4cf6.2) = facet_value %A.binding.as_type, (%Eats.lookup_impl_witness) [symbolic = %Eats.facet.loc32_76.2 (constants.%Eats.facet.702)]
 // CHECK:STDOUT:   %Feed.specific_fn.loc32_64.2: <specific function> = specific_function constants.%Feed, @Feed(%Food.loc32_29.1, %Eats.facet.loc32_76.2) [symbolic = %Feed.specific_fn.loc32_64.2 (constants.%Feed.specific_fn.1f9)]
@@ -562,13 +562,21 @@ fn F() {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete.loc32_45 => constants.%complete_type.357
 // CHECK:STDOUT:   %require_complete.loc32_54 => constants.%complete_type.357
-// CHECK:STDOUT:   %.loc32_76.3 => constants.%.767
 // CHECK:STDOUT:   %Eats.lookup_impl_witness => constants.%Eats.impl_witness.f54
+// CHECK:STDOUT:   %.loc32_76.3 => constants.%.767
 // CHECK:STDOUT:   %Eats.type => constants.%Eats.type.8c2
 // CHECK:STDOUT:   %Eats.facet.loc32_76.2 => constants.%Eats.facet.a4e
 // CHECK:STDOUT:   %Feed.specific_fn.loc32_64.2 => constants.%Feed.specific_fn.7dd
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: specific @Eats(constants.%Grass) {
+// CHECK:STDOUT:   %Food.loc21_16.1 => constants.%Grass
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %Eats.type => constants.%Eats.type.8c2
+// CHECK:STDOUT:   %Self.loc21_29.2 => constants.%Self.ebd
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
 // CHECK:STDOUT: specific @T.binding.as_type.as.Eats.impl(constants.%Animal.facet, constants.%Edible.facet) {
 // CHECK:STDOUT:   %T.loc26_14.2 => constants.%Animal.facet
 // CHECK:STDOUT:   %U.loc26_26.2 => constants.%Edible.facet
@@ -581,14 +589,6 @@ fn F() {
 // CHECK:STDOUT:   %require_complete => constants.%complete_type.cf8
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @Eats(constants.%Grass) {
-// CHECK:STDOUT:   %Food.loc21_16.1 => constants.%Grass
-// CHECK:STDOUT:
-// CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %Eats.type => constants.%Eats.type.8c2
-// CHECK:STDOUT:   %Self.loc21_29.2 => constants.%Self.ebd
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
 // CHECK:STDOUT: specific @Eats.WithSelf(constants.%Grass, constants.%Self.857) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT: }

+ 2 - 0
toolchain/check/testdata/facet/fail_convert_facet_value_to_missing_impl.carbon

@@ -49,6 +49,7 @@ fn HandleAnimal[T:! Animal](a: T) { Feed(a); }
 // CHECK:STDOUT:   %HandleAnimal.type: type = fn_type @HandleAnimal [concrete]
 // CHECK:STDOUT:   %HandleAnimal: %HandleAnimal.type = struct_value () [concrete]
 // CHECK:STDOUT:   %require_complete.72f: <witness> = require_complete_type %T.binding.as_type.e4f [symbolic]
+// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %T.998, @Eats [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -150,6 +151,7 @@ fn HandleAnimal[T:! Animal](a: T) { Feed(a); }
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.72f)]
+// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc27_17.1, @Eats [symbolic = %Eats.lookup_impl_witness (constants.%Eats.lookup_impl_witness)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%a.param: @HandleAnimal.%T.binding.as_type (%T.binding.as_type.e4f)) {
 // CHECK:STDOUT:   !entry:

+ 0 - 33
toolchain/check/testdata/facet/fail_incomplete.carbon

@@ -1,33 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon
-//
-// AUTOUPDATE
-// TIP: To test this file alone, run:
-// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/fail_incomplete.carbon
-// TIP: To dump output, run:
-// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/fail_incomplete.carbon
-
-// --- fail_impl_lookup_incomplete.carbon
-library "[[@TEST_NAME]]";
-
-constraint Z;
-
-fn AsZ(unused T:! Z) {}
-
-fn F() {
-  // Requires Z identified.
-  // CHECK:STDERR: fail_impl_lookup_incomplete.carbon:[[@LINE+10]]:3: error: facet type `Z` can not be identified [ImplLookupInUnidentifiedFacetType]
-  // CHECK:STDERR:   AsZ(());
-  // CHECK:STDERR:   ^~~~~~~
-  // CHECK:STDERR: fail_impl_lookup_incomplete.carbon:[[@LINE-9]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
-  // CHECK:STDERR: constraint Z;
-  // CHECK:STDERR: ^~~~~~~~~~~~~
-  // CHECK:STDERR: fail_impl_lookup_incomplete.carbon:[[@LINE-10]]:15: note: initializing generic parameter `T` declared here [InitializingGenericParam]
-  // CHECK:STDERR: fn AsZ(unused T:! Z) {}
-  // CHECK:STDERR:               ^
-  // CHECK:STDERR:
-  AsZ(());
-}

+ 216 - 0
toolchain/check/testdata/facet/partially_identified.carbon

@@ -0,0 +1,216 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/partially_identified.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/partially_identified.carbon
+
+// --- fail_self_doesnt_meet_constraint.carbon
+library "[[@TEST_NAME]]";
+
+interface Y {}
+interface NeedsY(T:! Y) {}
+constraint W {
+  // CHECK:STDERR: fail_self_doesnt_meet_constraint.carbon:[[@LINE+7]]:24: error: cannot convert type `Self` that implements `W` into type implementing `Y` [ConversionFailureFacetToFacet]
+  // CHECK:STDERR:   extend require impls NeedsY(Self);
+  // CHECK:STDERR:                        ^~~~~~~~~~~~
+  // CHECK:STDERR: fail_self_doesnt_meet_constraint.carbon:[[@LINE-5]]:18: note: initializing generic parameter `T` declared here [InitializingGenericParam]
+  // CHECK:STDERR: interface NeedsY(T:! Y) {}
+  // CHECK:STDERR:                  ^
+  // CHECK:STDERR:
+  extend require impls NeedsY(Self);
+}
+
+// --- self_meets_constraint.carbon
+library "[[@TEST_NAME]]";
+
+interface Y {}
+interface NeedsY(T:! Y) {}
+constraint W {
+  require impls Y;
+  extend require impls NeedsY(Self);
+}
+
+fn F(w:! W) {
+  w as Y;
+  w as NeedsY(w);
+}
+
+// --- self_meets_constraint_through_indirection.carbon
+library "[[@TEST_NAME]]";
+
+interface Y {}
+interface NeedsY(T:! Y) {}
+constraint GivesY {
+  require impls Y;
+}
+constraint W {
+  require impls GivesY;
+  extend require impls NeedsY(Self);
+}
+
+fn F(w:! W) {
+  w as Y;
+  w as NeedsY(w);
+}
+
+// --- self_in_constraint_specific_interface.carbon
+library "[[@TEST_NAME]]";
+
+interface Y {}
+interface NeedsY(T:! Y) {}
+
+// All types impl Y. This requires an impl lookup to find a witness, and it will
+// be a symbolic witness for a symbolic self type.
+impl forall [T:! type] T as Y {}
+
+constraint W {
+  // Constructs a FacetValue of `Self as Y`, containing the impl lookup
+  // instruction as its witness, which will be part of the generic definition of
+  // this require.
+  require impls NeedsY(Self);
+}
+
+class C {}
+impl C as NeedsY(C) {}
+
+fn G(w:! W) {
+  // The witness of NeedsY(Self) monomorphized by `w` must be the same as the
+  // witness of `NeedsY(w)` constructed directly here in order for this to find
+  // `NeedsY(w)` in the facet type `W`.
+  w as NeedsY(w);
+}
+
+fn F() {
+  // Further monomorphize `NeedsY(w)` to `NeedsY(C)`.
+  G(C);
+}
+
+// --- fail_todo_facet_access_type_of_self_meets_constraint.carbon
+library "[[@TEST_NAME]]";
+
+class C(T:! type) {}
+
+interface Y {}
+interface NeedsY(T:! Y) {}
+constraint W {
+  require C(Self) impls Y;
+  // CHECK:STDERR: fail_todo_facet_access_type_of_self_meets_constraint.carbon:[[@LINE+7]]:17: error: cannot convert type `C(Self)` into type implementing `Y` [ConversionFailureTypeToFacet]
+  // CHECK:STDERR:   require impls NeedsY(C(Self));
+  // CHECK:STDERR:                 ^~~~~~~~~~~~~~~
+  // CHECK:STDERR: fail_todo_facet_access_type_of_self_meets_constraint.carbon:[[@LINE-6]]:18: note: initializing generic parameter `T` declared here [InitializingGenericParam]
+  // CHECK:STDERR: interface NeedsY(T:! Y) {}
+  // CHECK:STDERR:                  ^
+  // CHECK:STDERR:
+  require impls NeedsY(C(Self));
+}
+
+fn F(w:! W) {
+  // TODO: Lookups for `C(w) as <something>` need to look into the facet types
+  // of any facet value in the type `C(w)`, so that it can find a witness from
+  // the constraint `W`.
+  // CHECK:STDERR: fail_todo_facet_access_type_of_self_meets_constraint.carbon:[[@LINE+4]]:3: error: cannot convert type `C(w)` into type implementing `Y` [ConversionFailureTypeToFacet]
+  // CHECK:STDERR:   C(w) as Y;
+  // CHECK:STDERR:   ^~~~~~~~~
+  // CHECK:STDERR:
+  C(w) as Y;
+  // CHECK:STDERR: fail_todo_facet_access_type_of_self_meets_constraint.carbon:[[@LINE+7]]:11: error: cannot convert type `C(w)` into type implementing `Y` [ConversionFailureTypeToFacet]
+  // CHECK:STDERR:   C(w) as NeedsY(C(w));
+  // CHECK:STDERR:           ^~~~~~~~~~~~
+  // CHECK:STDERR: fail_todo_facet_access_type_of_self_meets_constraint.carbon:[[@LINE-25]]:18: note: initializing generic parameter `T` declared here [InitializingGenericParam]
+  // CHECK:STDERR: interface NeedsY(T:! Y) {}
+  // CHECK:STDERR:                  ^
+  // CHECK:STDERR:
+  C(w) as NeedsY(C(w));
+}
+
+// --- multiple_use_of_self.carbon
+library "[[@TEST_NAME]]";
+
+interface Y {}
+interface NeedsY(T:! Y) {}
+interface NeedsNeedsY(T:! Y, U:! NeedsY(T)) {}
+constraint W {
+  require impls Y;
+  // The identified facet type of Self is {Y}.
+  extend require impls NeedsY(Self);
+  // The identified facet type of Self is {Y, NeedsY}. Ensure we don't keep
+  // seeing the previous identified facet type of Self.
+  extend require impls NeedsNeedsY(Self, Self);
+}
+
+fn F(w:! W) {
+  w as Y;
+  w as NeedsY(w);
+}
+
+// --- access_through_previous_require.carbon
+library "[[@TEST_NAME]]";
+
+interface Z { let Z0:! type; }
+interface Y {}
+interface X {
+  let X0:! type;
+  fn XF() -> X0;
+}
+
+class P(T:! type) { adapt (); }
+
+constraint M {
+  require impls Z where .Z0 = {};
+  require impls Y;
+}
+constraint N {
+  require impls M;
+  // The facts from M travel back to here.
+  require impls X where .X0 = P(Self.(Z.Z0));
+}
+
+fn F(T:! N) -> T.(X.X0) { return T.(X.XF)(); }
+
+fn G() -> P({}) {
+  class C {}
+  impl C as Z where .Z0 = {} {}
+  impl C as Y {}
+  impl C as X where .X0 = P({}) {
+    fn XF() -> P({}) { return () as P({}); }
+  }
+  return F(C);
+}
+
+// --- fail_impl_lookup_target_partially_identified.carbon
+library "[[@TEST_NAME]]";
+
+interface Z {}
+
+interface X { let XZ:! Z; }
+constraint W {
+  require impls Z;
+  // Target of impl lookup can not be partially identified.
+  // CHECK:STDERR: fail_impl_lookup_target_partially_identified.carbon:[[@LINE+7]]:32: error: facet type `Z & W` can not be identified [ImplLookupInUnidentifiedFacetType]
+  // CHECK:STDERR:   require impls X where .XZ = (Self as (W & Z));
+  // CHECK:STDERR:                                ^~~~~~~~~~~~~~~
+  // CHECK:STDERR: fail_impl_lookup_target_partially_identified.carbon:[[@LINE-6]]:1: note: constraint is currently being defined [NamedConstraintIncompleteWithinDefinition]
+  // CHECK:STDERR: constraint W {
+  // CHECK:STDERR: ^~~~~~~~~~~~~~
+  // CHECK:STDERR:
+  require impls X where .XZ = (Self as (W & Z));
+}
+
+// --- convert_from_forward_declaration.carbon
+library "[[@TEST_NAME]]";
+
+interface Z {}
+// The facet type `W` is partially identified as soon as it is declared.
+// Converting from a facet requires its facet type to be at least partially
+// identified, not fully identified.
+constraint W;
+
+fn F(T:! W & Z) {
+  T as Z;
+}

+ 0 - 66
toolchain/check/testdata/facet/require_constrains_self.carbon

@@ -1,66 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon
-//
-// AUTOUPDATE
-// TIP: To test this file alone, run:
-// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/require_constrains_self.carbon
-// TIP: To dump output, run:
-// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/require_constrains_self.carbon
-
-// --- fail_self_doesnt_meet_constraint.carbon
-library "[[@TEST_NAME]]";
-
-interface Y2 {}
-interface Y(T:! Y2) {}
-// TODO: The error should be that Self does not implement Y2, not that it can't
-// be identified. We should allow identifying `Self`.
-//
-// CHECK:STDERR: fail_self_doesnt_meet_constraint.carbon:[[@LINE+17]]:37: error: facet type of value `Self` can not be identified [ImplLookupInUnidentifiedFacetTypeOfQuerySelf]
-// CHECK:STDERR: constraint W { extend require impls Y(Self); }
-// CHECK:STDERR:                                     ^~~~~~~
-// CHECK:STDERR: fail_self_doesnt_meet_constraint.carbon:[[@LINE+14]]:1: note: constraint is currently being defined [NamedConstraintIncompleteWithinDefinition]
-// CHECK:STDERR: constraint W { extend require impls Y(Self); }
-// CHECK:STDERR: ^~~~~~~~~~~~~~
-// CHECK:STDERR: fail_self_doesnt_meet_constraint.carbon:[[@LINE-10]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]
-// CHECK:STDERR: interface Y(T:! Y2) {}
-// CHECK:STDERR:             ^
-// CHECK:STDERR:
-// CHECK:STDERR: fail_self_doesnt_meet_constraint.carbon:[[@LINE+7]]:37: error: cannot convert type `Self` that implements `W` into type implementing `Y2` [ConversionFailureFacetToFacet]
-// CHECK:STDERR: constraint W { extend require impls Y(Self); }
-// CHECK:STDERR:                                     ^~~~~~~
-// CHECK:STDERR: fail_self_doesnt_meet_constraint.carbon:[[@LINE-17]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]
-// CHECK:STDERR: interface Y(T:! Y2) {}
-// CHECK:STDERR:             ^
-// CHECK:STDERR:
-constraint W { extend require impls Y(Self); }
-
-// --- fail_todo_self_meets_constraint.carbon
-library "[[@TEST_NAME]]";
-
-interface Y2 {}
-interface Y(T:! Y2) {}
-constraint W {
-  // TODO: This should allow the next line to work, as Self should be known to impl Y2.
-  require impls Y2;
-  // CHECK:STDERR: fail_todo_self_meets_constraint.carbon:[[@LINE+17]]:24: error: facet type of value `Self` can not be identified [ImplLookupInUnidentifiedFacetTypeOfQuerySelf]
-  // CHECK:STDERR:   extend require impls Y(Self);
-  // CHECK:STDERR:                        ^~~~~~~
-  // CHECK:STDERR: fail_todo_self_meets_constraint.carbon:[[@LINE-6]]:1: note: constraint is currently being defined [NamedConstraintIncompleteWithinDefinition]
-  // CHECK:STDERR: constraint W {
-  // CHECK:STDERR: ^~~~~~~~~~~~~~
-  // CHECK:STDERR: fail_todo_self_meets_constraint.carbon:[[@LINE-10]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]
-  // CHECK:STDERR: interface Y(T:! Y2) {}
-  // CHECK:STDERR:             ^
-  // CHECK:STDERR:
-  // CHECK:STDERR: fail_todo_self_meets_constraint.carbon:[[@LINE+7]]:24: error: cannot convert type `Self` that implements `W` into type implementing `Y2` [ConversionFailureFacetToFacet]
-  // CHECK:STDERR:   extend require impls Y(Self);
-  // CHECK:STDERR:                        ^~~~~~~
-  // CHECK:STDERR: fail_todo_self_meets_constraint.carbon:[[@LINE-17]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]
-  // CHECK:STDERR: interface Y(T:! Y2) {}
-  // CHECK:STDERR:             ^
-  // CHECK:STDERR:
-  extend require impls Y(Self);
-}

+ 17 - 0
toolchain/check/testdata/facet/require_invalid.carbon

@@ -192,3 +192,20 @@ interface Z {
     Self.A;
   }
 }
+
+// --- todo_fail_impl_mismatch_named_constraint_rewrites.carbon
+library "[[@TEST_NAME]]";
+
+interface Z { let Z0:! type; }
+
+constraint M {
+  require impls Z where .Z0 = {};
+}
+
+fn G() {
+  class C {}
+  // .Z0 has the wrong type for M.
+  impl C as Z where .Z0 = () {}
+  // TODO: Converting C to M should fail since the rewrite constraints are incompatible.
+  C as M;
+}

+ 29 - 38
toolchain/check/testdata/for/actual.carbon

@@ -83,30 +83,30 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:   %Optional.None.type.fc5: type = fn_type @Optional.None, @Optional(%T.542) [symbolic]
 // CHECK:STDOUT:   %Optional.None.fcb: %Optional.None.type.fc5 = struct_value () [symbolic]
 // CHECK:STDOUT:   %.Self.2b2: %Iterate.type = symbolic_binding .Self [symbolic_self]
-// CHECK:STDOUT:   %Iterate.lookup_impl_witness.53f: <witness> = lookup_impl_witness %.Self.2b2, @Iterate [symbolic_self]
-// CHECK:STDOUT:   %impl.elem0.3b1: %facet_type.7e2 = impl_witness_access %Iterate.lookup_impl_witness.53f, element0 [symbolic_self]
 // CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.2b2 [symbolic_self]
 // CHECK:STDOUT:   %Iterate.assoc_type: type = assoc_entity_type @Iterate [concrete]
 // CHECK:STDOUT:   %assoc1.a27: %Iterate.assoc_type = assoc_entity element1, imports.%Core.import_ref.cd6 [concrete]
+// CHECK:STDOUT:   %Iterate.lookup_impl_witness.53f: <witness> = lookup_impl_witness %.Self.2b2, @Iterate [symbolic_self]
 // CHECK:STDOUT:   %impl.elem1.49e: type = impl_witness_access %Iterate.lookup_impl_witness.53f, element1 [symbolic_self]
 // CHECK:STDOUT:   %assoc0.4bd: %Iterate.assoc_type = assoc_entity element0, imports.%Core.import_ref.f74 [concrete]
+// CHECK:STDOUT:   %impl.elem0.3b1: %facet_type.7e2 = impl_witness_access %Iterate.lookup_impl_witness.53f, element0 [symbolic_self]
 // CHECK:STDOUT:   %Destroy.lookup_impl_witness.93c: <witness> = lookup_impl_witness %Int.fc6021.1, @Destroy [symbolic]
 // CHECK:STDOUT:   %require_complete.9019d7.1: <witness> = require_complete_type %Int.fc6021.1 [symbolic]
 // CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]
 // CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]
 // CHECK:STDOUT:   %.83cba3.1: Core.Form = init_form %Int.fc6021.1 [symbolic]
-// CHECK:STDOUT:   %.4f8: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.7a8: <witness> = lookup_impl_witness %Int.fc6021.1, @Copy [symbolic]
+// CHECK:STDOUT:   %.4f8: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic]
 // CHECK:STDOUT:   %facet_value: %facet_type.7e2 = facet_value %Int.fc6021.1, (%Destroy.lookup_impl_witness.93c, %Copy.lookup_impl_witness.7a8) [symbolic]
-// CHECK:STDOUT:   %Iterate_where.type: type = facet_type <@Iterate where %impl.elem0.3b1 = %facet_value and %impl.elem1.49e = %Int.fc6021.1> [symbolic]
+// CHECK:STDOUT:   %Iterate_where.type: type = facet_type <@Iterate where %impl.elem1.49e = %Int.fc6021.1 and %impl.elem0.3b1 = %facet_value> [symbolic]
 // CHECK:STDOUT:   %Iterate.impl_witness: <witness> = impl_witness @IntRange.as.Iterate.impl.%Iterate.impl_witness_table, @IntRange.as.Iterate.impl(%N) [symbolic]
-// CHECK:STDOUT:   %require_complete.234: <witness> = require_complete_type %Iterate_where.type [symbolic]
+// CHECK:STDOUT:   %require_complete.63d: <witness> = require_complete_type %Iterate_where.type [symbolic]
 // CHECK:STDOUT:   %IntRange.as.Iterate.impl.NewCursor.type: type = fn_type @IntRange.as.Iterate.impl.NewCursor, @IntRange.as.Iterate.impl(%N) [symbolic]
 // CHECK:STDOUT:   %IntRange.as.Iterate.impl.NewCursor: %IntRange.as.Iterate.impl.NewCursor.type = struct_value () [symbolic]
 // CHECK:STDOUT:   %ptr.c9c: type = ptr_type %Int.fc6021.1 [symbolic]
 // CHECK:STDOUT:   %pattern_type.bda: type = pattern_type %ptr.c9c [symbolic]
-// CHECK:STDOUT:   %.63c: require_specific_def_type = require_specific_def @T.binding.as_type.as.OptionalStorage.impl(%facet_value) [symbolic]
 // CHECK:STDOUT:   %OptionalStorage.lookup_impl_witness.b62: <witness> = lookup_impl_witness %Int.fc6021.1, @OptionalStorage [symbolic]
+// CHECK:STDOUT:   %.63c: require_specific_def_type = require_specific_def @T.binding.as_type.as.OptionalStorage.impl(%facet_value) [symbolic]
 // CHECK:STDOUT:   %OptionalStorage.facet.01e: %OptionalStorage.type = facet_value %Int.fc6021.1, (%OptionalStorage.lookup_impl_witness.b62) [symbolic]
 // CHECK:STDOUT:   %Optional.e48: type = class_type @Optional, @Optional(%OptionalStorage.facet.01e) [symbolic]
 // CHECK:STDOUT:   %.949: Core.Form = init_form %Optional.e48 [symbolic]
@@ -155,8 +155,8 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:   %.48d: type = fn_type_with_self_type %OrderedWith.WithSelf.Less.type.3a2, %OrderedWith.facet [symbolic]
 // CHECK:STDOUT:   %Int.as.OrderedWith.impl.Less.specific_fn.4c2: <specific function> = specific_function %Int.as.OrderedWith.impl.Less.4cf, @Int.as.OrderedWith.impl.Less.1(%N, %N) [symbolic]
 // CHECK:STDOUT:   %Inc.type: type = facet_type <@Inc> [concrete]
-// CHECK:STDOUT:   %.53b: require_specific_def_type = require_specific_def @Int.as.Inc.impl(%N) [symbolic]
 // CHECK:STDOUT:   %Inc.lookup_impl_witness: <witness> = lookup_impl_witness %Int.fc6021.1, @Inc [symbolic]
+// CHECK:STDOUT:   %.53b: require_specific_def_type = require_specific_def @Int.as.Inc.impl(%N) [symbolic]
 // CHECK:STDOUT:   %Inc.facet: %Inc.type = facet_value %Int.fc6021.1, (%Inc.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %Inc.WithSelf.Op.type.17b: type = fn_type @Inc.WithSelf.Op, @Inc.WithSelf(%Inc.facet) [symbolic]
 // CHECK:STDOUT:   %.9a6: type = fn_type_with_self_type %Inc.WithSelf.Op.type.17b, %Inc.facet [symbolic]
@@ -181,10 +181,6 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]
 // CHECK:STDOUT:   %IntRange.Make.type.045: type = fn_type @IntRange.Make, @IntRange(%int_32) [concrete]
 // CHECK:STDOUT:   %IntRange.Make.3e9: %IntRange.Make.type.045 = struct_value () [concrete]
-// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]
-// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]
-// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]
-// CHECK:STDOUT:   %.14e: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%int_32) [concrete]
 // CHECK:STDOUT:   %IntRange.elem.a58: type = unbound_element_type %IntRange.a89, %i32 [concrete]
 // CHECK:STDOUT:   %struct_type.start.end.d0a: type = struct_type {.start: %i32, .end: %i32} [concrete]
 // CHECK:STDOUT:   %complete_type.c45: <witness> = complete_type_witness %struct_type.start.end.d0a [concrete]
@@ -204,6 +200,10 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]
 // CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]
+// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]
+// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]
+// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]
+// CHECK:STDOUT:   %.14e: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%int_32) [concrete]
 // CHECK:STDOUT:   %Copy.facet.de4: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.de4) [concrete]
 // CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet.de4 [concrete]
@@ -298,17 +298,16 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:   %IntRange: type = class_type @IntRange, @IntRange(%N) [symbolic = %IntRange (constants.%IntRange.265)]
 // CHECK:STDOUT:   %Int.loc9_54.1: type = class_type @Int, @Int(%N) [symbolic = %Int.loc9_54.1 (constants.%Int.fc6021.1)]
 // CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc9_54.1, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness.93c)]
-// CHECK:STDOUT:   %.loc9_85.1: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic = %.loc9_85.1 (constants.%.4f8)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc9_54.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.7a8)]
+// CHECK:STDOUT:   %.loc9_85.1: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic = %.loc9_85.1 (constants.%.4f8)]
 // CHECK:STDOUT:   %facet_value.loc9_85.1: %facet_type.7e2 = facet_value %Int.loc9_54.1, (%Destroy.lookup_impl_witness, %Copy.lookup_impl_witness) [symbolic = %facet_value.loc9_85.1 (constants.%facet_value)]
-// CHECK:STDOUT:   %Iterate_where.type: type = facet_type <@Iterate where constants.%impl.elem0.3b1 = %facet_value.loc9_85.1 and constants.%impl.elem1.49e = %Int.loc9_54.1> [symbolic = %Iterate_where.type (constants.%Iterate_where.type)]
+// CHECK:STDOUT:   %Iterate_where.type: type = facet_type <@Iterate where constants.%impl.elem1.49e = %Int.loc9_54.1 and constants.%impl.elem0.3b1 = %facet_value.loc9_85.1> [symbolic = %Iterate_where.type (constants.%Iterate_where.type)]
 // CHECK:STDOUT:   %Iterate.impl_witness.loc9_87.2: <witness> = impl_witness %Iterate.impl_witness_table, @IntRange.as.Iterate.impl(%N) [symbolic = %Iterate.impl_witness.loc9_87.2 (constants.%Iterate.impl_witness)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Iterate_where.type [symbolic = %require_complete (constants.%require_complete.234)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Iterate_where.type [symbolic = %require_complete (constants.%require_complete.63d)]
 // CHECK:STDOUT:   %IntRange.as.Iterate.impl.NewCursor.type: type = fn_type @IntRange.as.Iterate.impl.NewCursor, @IntRange.as.Iterate.impl(%N) [symbolic = %IntRange.as.Iterate.impl.NewCursor.type (constants.%IntRange.as.Iterate.impl.NewCursor.type)]
 // CHECK:STDOUT:   %IntRange.as.Iterate.impl.NewCursor: @IntRange.as.Iterate.impl.%IntRange.as.Iterate.impl.NewCursor.type (%IntRange.as.Iterate.impl.NewCursor.type) = struct_value () [symbolic = %IntRange.as.Iterate.impl.NewCursor (constants.%IntRange.as.Iterate.impl.NewCursor)]
-// CHECK:STDOUT:   %.loc11: require_specific_def_type = require_specific_def @T.binding.as_type.as.OptionalStorage.impl(%facet_value.loc9_85.1) [symbolic = %.loc11 (constants.%.63c)]
 // CHECK:STDOUT:   %IntRange.as.Iterate.impl.Next.type: type = fn_type @IntRange.as.Iterate.impl.Next, @IntRange.as.Iterate.impl(%N) [symbolic = %IntRange.as.Iterate.impl.Next.type (constants.%IntRange.as.Iterate.impl.Next.type)]
 // CHECK:STDOUT:   %IntRange.as.Iterate.impl.Next: @IntRange.as.Iterate.impl.%IntRange.as.Iterate.impl.Next.type (%IntRange.as.Iterate.impl.Next.type) = struct_value () [symbolic = %IntRange.as.Iterate.impl.Next (constants.%IntRange.as.Iterate.impl.Next)]
 // CHECK:STDOUT:
@@ -369,10 +368,10 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:       %return.param: ref @IntRange.as.Iterate.impl.Next.%Optional.loc11_75.1 (%Optional.e48) = out_param call_param2
 // CHECK:STDOUT:       %return: ref @IntRange.as.Iterate.impl.Next.%Optional.loc11_75.1 (%Optional.e48) = return_slot %return.param
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %Iterate.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant.loc9_87.1, %impl_witness_assoc_constant.loc9_87.2, %IntRange.as.Iterate.impl.NewCursor.decl, %IntRange.as.Iterate.impl.Next.decl), @IntRange.as.Iterate.impl [concrete]
+// CHECK:STDOUT:     %Iterate.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant.loc9_87.2, %impl_witness_assoc_constant.loc9_87.1, %IntRange.as.Iterate.impl.NewCursor.decl, %IntRange.as.Iterate.impl.Next.decl), @IntRange.as.Iterate.impl [concrete]
 // CHECK:STDOUT:     %Iterate.impl_witness.loc9_87.1: <witness> = impl_witness %Iterate.impl_witness_table, @IntRange.as.Iterate.impl(constants.%N) [symbolic = %Iterate.impl_witness.loc9_87.2 (constants.%Iterate.impl_witness)]
-// CHECK:STDOUT:     %impl_witness_assoc_constant.loc9_87.1: %facet_type.7e2 = impl_witness_assoc_constant constants.%facet_value [symbolic = %facet_value.loc9_85.1 (constants.%facet_value)]
-// CHECK:STDOUT:     %impl_witness_assoc_constant.loc9_87.2: type = impl_witness_assoc_constant constants.%Int.fc6021.1 [symbolic = %Int.loc9_54.1 (constants.%Int.fc6021.1)]
+// CHECK:STDOUT:     %impl_witness_assoc_constant.loc9_87.1: type = impl_witness_assoc_constant constants.%Int.fc6021.1 [symbolic = %Int.loc9_54.1 (constants.%Int.fc6021.1)]
+// CHECK:STDOUT:     %impl_witness_assoc_constant.loc9_87.2: %facet_type.7e2 = impl_witness_assoc_constant constants.%facet_value [symbolic = %facet_value.loc9_85.1 (constants.%facet_value)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   !members:
 // CHECK:STDOUT:     .N = <poisoned>
@@ -388,7 +387,6 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %IntRange.Make.type: type = fn_type @IntRange.Make, @IntRange(%N.loc4_16.1) [symbolic = %IntRange.Make.type (constants.%IntRange.Make.type.1df)]
 // CHECK:STDOUT:   %IntRange.Make: @IntRange.%IntRange.Make.type (%IntRange.Make.type.1df) = struct_value () [symbolic = %IntRange.Make (constants.%IntRange.Make.8a9)]
-// CHECK:STDOUT:   %.loc9: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N.loc4_16.1) [symbolic = %.loc9 (constants.%.4f8)]
 // CHECK:STDOUT:   %Int.loc22_32.2: type = class_type @Int, @Int(%N.loc4_16.1) [symbolic = %Int.loc22_32.2 (constants.%Int.fc6021.1)]
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Int.loc22_32.2 [symbolic = %require_complete (constants.%require_complete.9019d7.1)]
 // CHECK:STDOUT:   %IntRange: type = class_type @IntRange, @IntRange(%N.loc4_16.1) [symbolic = %IntRange (constants.%IntRange.265)]
@@ -492,8 +490,8 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:   %require_complete.loc5_16: <witness> = require_complete_type %Int.loc5_28.1 [symbolic = %require_complete.loc5_16 (constants.%require_complete.9019d7.1)]
 // CHECK:STDOUT:   %require_complete.loc5_52: <witness> = require_complete_type %IntRange [symbolic = %require_complete.loc5_52 (constants.%require_complete.8a1)]
 // CHECK:STDOUT:   %struct_type.start.end: type = struct_type {.start: @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1), .end: @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1)} [symbolic = %struct_type.start.end (constants.%struct_type.start.end.ff1)]
-// CHECK:STDOUT:   %.loc6_22.1: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic = %.loc6_22.1 (constants.%.4f8)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc5_28.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.7a8)]
+// CHECK:STDOUT:   %.loc6_22.1: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic = %.loc6_22.1 (constants.%.4f8)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %Int.loc5_28.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet.3b9)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.e13)]
 // CHECK:STDOUT:   %.loc6_22.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc6_22.2 (constants.%.e29)]
@@ -537,8 +535,8 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:   %require_complete.loc10_22: <witness> = require_complete_type %IntRange [symbolic = %require_complete.loc10_22 (constants.%require_complete.8a1)]
 // CHECK:STDOUT:   %IntRange.elem: type = unbound_element_type %IntRange, %Int.loc10_45.1 [symbolic = %IntRange.elem (constants.%IntRange.elem.541)]
 // CHECK:STDOUT:   %require_complete.loc10_60: <witness> = require_complete_type %Int.loc10_45.1 [symbolic = %require_complete.loc10_60 (constants.%require_complete.9019d7.1)]
-// CHECK:STDOUT:   %.loc10_60.3: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic = %.loc10_60.3 (constants.%.4f8)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc10_45.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.7a8)]
+// CHECK:STDOUT:   %.loc10_60.3: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic = %.loc10_60.3 (constants.%.4f8)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %Int.loc10_45.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet.3b9)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.e13)]
 // CHECK:STDOUT:   %.loc10_60.4: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc10_60.4 (constants.%.e29)]
@@ -567,11 +565,11 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:   %Int.loc11_43.1: type = class_type @Int, @Int(%N) [symbolic = %Int.loc11_43.1 (constants.%Int.fc6021.1)]
 // CHECK:STDOUT:   %ptr.loc11_44.1: type = ptr_type %Int.loc11_43.1 [symbolic = %ptr.loc11_44.1 (constants.%ptr.c9c)]
 // CHECK:STDOUT:   %pattern_type.loc11_31: type = pattern_type %ptr.loc11_44.1 [symbolic = %pattern_type.loc11_31 (constants.%pattern_type.bda)]
+// CHECK:STDOUT:   %OptionalStorage.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc11_43.1, @OptionalStorage [symbolic = %OptionalStorage.lookup_impl_witness (constants.%OptionalStorage.lookup_impl_witness.b62)]
 // CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc11_43.1, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness.93c)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc11_43.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.7a8)]
 // CHECK:STDOUT:   %facet_value: %facet_type.7e2 = facet_value %Int.loc11_43.1, (%Destroy.lookup_impl_witness, %Copy.lookup_impl_witness) [symbolic = %facet_value (constants.%facet_value)]
 // CHECK:STDOUT:   %.loc11_75.3: require_specific_def_type = require_specific_def @T.binding.as_type.as.OptionalStorage.impl(%facet_value) [symbolic = %.loc11_75.3 (constants.%.63c)]
-// CHECK:STDOUT:   %OptionalStorage.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc11_43.1, @OptionalStorage [symbolic = %OptionalStorage.lookup_impl_witness (constants.%OptionalStorage.lookup_impl_witness.b62)]
 // CHECK:STDOUT:   %OptionalStorage.facet.loc11_75.1: %OptionalStorage.type = facet_value %Int.loc11_43.1, (%OptionalStorage.lookup_impl_witness) [symbolic = %OptionalStorage.facet.loc11_75.1 (constants.%OptionalStorage.facet.01e)]
 // CHECK:STDOUT:   %Optional.loc11_75.1: type = class_type @Optional, @Optional(%OptionalStorage.facet.loc11_75.1) [symbolic = %Optional.loc11_75.1 (constants.%Optional.e48)]
 // CHECK:STDOUT:   %.loc11_75.4: Core.Form = init_form %Optional.loc11_75.1 [symbolic = %.loc11_75.4 (constants.%.949)]
@@ -602,8 +600,8 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:   %Int.as.OrderedWith.impl.Less.type: type = fn_type @Int.as.OrderedWith.impl.Less.1, @Int.as.OrderedWith.impl.2e6(%N, %N) [symbolic = %Int.as.OrderedWith.impl.Less.type (constants.%Int.as.OrderedWith.impl.Less.type.3f1)]
 // CHECK:STDOUT:   %Int.as.OrderedWith.impl.Less: @IntRange.as.Iterate.impl.Next.%Int.as.OrderedWith.impl.Less.type (%Int.as.OrderedWith.impl.Less.type.3f1) = struct_value () [symbolic = %Int.as.OrderedWith.impl.Less (constants.%Int.as.OrderedWith.impl.Less.4cf)]
 // CHECK:STDOUT:   %Int.as.OrderedWith.impl.Less.specific_fn: <specific function> = specific_function %Int.as.OrderedWith.impl.Less, @Int.as.OrderedWith.impl.Less.1(%N, %N) [symbolic = %Int.as.OrderedWith.impl.Less.specific_fn (constants.%Int.as.OrderedWith.impl.Less.specific_fn.4c2)]
-// CHECK:STDOUT:   %.loc14_9.1: require_specific_def_type = require_specific_def @Int.as.Inc.impl(%N) [symbolic = %.loc14_9.1 (constants.%.53b)]
 // CHECK:STDOUT:   %Inc.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc11_43.1, @Inc [symbolic = %Inc.lookup_impl_witness (constants.%Inc.lookup_impl_witness)]
+// CHECK:STDOUT:   %.loc14_9.1: require_specific_def_type = require_specific_def @Int.as.Inc.impl(%N) [symbolic = %.loc14_9.1 (constants.%.53b)]
 // CHECK:STDOUT:   %Inc.facet: %Inc.type = facet_value %Int.loc11_43.1, (%Inc.lookup_impl_witness) [symbolic = %Inc.facet (constants.%Inc.facet)]
 // CHECK:STDOUT:   %Inc.WithSelf.Op.type: type = fn_type @Inc.WithSelf.Op, @Inc.WithSelf(%Inc.facet) [symbolic = %Inc.WithSelf.Op.type (constants.%Inc.WithSelf.Op.type.17b)]
 // CHECK:STDOUT:   %.loc14_9.2: type = fn_type_with_self_type %Inc.WithSelf.Op.type, %Inc.facet [symbolic = %.loc14_9.2 (constants.%.9a6)]
@@ -747,7 +745,6 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %IntRange.Make.type => constants.%IntRange.Make.type.1df
 // CHECK:STDOUT:   %IntRange.Make => constants.%IntRange.Make.8a9
-// CHECK:STDOUT:   %.loc9 => constants.%.4f8
 // CHECK:STDOUT:   %Int.loc22_32.2 => constants.%Int.fc6021.1
 // CHECK:STDOUT:   %require_complete => constants.%require_complete.9019d7.1
 // CHECK:STDOUT:   %IntRange => constants.%IntRange.265
@@ -770,17 +767,16 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:   %IntRange => constants.%IntRange.265
 // CHECK:STDOUT:   %Int.loc9_54.1 => constants.%Int.fc6021.1
 // CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%Destroy.lookup_impl_witness.93c
-// CHECK:STDOUT:   %.loc9_85.1 => constants.%.4f8
 // CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.lookup_impl_witness.7a8
+// CHECK:STDOUT:   %.loc9_85.1 => constants.%.4f8
 // CHECK:STDOUT:   %facet_value.loc9_85.1 => constants.%facet_value
 // CHECK:STDOUT:   %Iterate_where.type => constants.%Iterate_where.type
 // CHECK:STDOUT:   %Iterate.impl_witness.loc9_87.2 => constants.%Iterate.impl_witness
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete => constants.%require_complete.234
+// CHECK:STDOUT:   %require_complete => constants.%require_complete.63d
 // CHECK:STDOUT:   %IntRange.as.Iterate.impl.NewCursor.type => constants.%IntRange.as.Iterate.impl.NewCursor.type
 // CHECK:STDOUT:   %IntRange.as.Iterate.impl.NewCursor => constants.%IntRange.as.Iterate.impl.NewCursor
-// CHECK:STDOUT:   %.loc11 => constants.%.63c
 // CHECK:STDOUT:   %IntRange.as.Iterate.impl.Next.type => constants.%IntRange.as.Iterate.impl.Next.type
 // CHECK:STDOUT:   %IntRange.as.Iterate.impl.Next => constants.%IntRange.as.Iterate.impl.Next
 // CHECK:STDOUT: }
@@ -801,11 +797,11 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:   %Int.loc11_43.1 => constants.%Int.fc6021.1
 // CHECK:STDOUT:   %ptr.loc11_44.1 => constants.%ptr.c9c
 // CHECK:STDOUT:   %pattern_type.loc11_31 => constants.%pattern_type.bda
+// CHECK:STDOUT:   %OptionalStorage.lookup_impl_witness => constants.%OptionalStorage.lookup_impl_witness.b62
 // CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%Destroy.lookup_impl_witness.93c
 // CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.lookup_impl_witness.7a8
 // CHECK:STDOUT:   %facet_value => constants.%facet_value
 // CHECK:STDOUT:   %.loc11_75.3 => constants.%.63c
-// CHECK:STDOUT:   %OptionalStorage.lookup_impl_witness => constants.%OptionalStorage.lookup_impl_witness.b62
 // CHECK:STDOUT:   %OptionalStorage.facet.loc11_75.1 => constants.%OptionalStorage.facet.01e
 // CHECK:STDOUT:   %Optional.loc11_75.1 => constants.%Optional.e48
 // CHECK:STDOUT:   %.loc11_75.4 => constants.%.949
@@ -818,7 +814,6 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %IntRange.Make.type => constants.%IntRange.Make.type.045
 // CHECK:STDOUT:   %IntRange.Make => constants.%IntRange.Make.3e9
-// CHECK:STDOUT:   %.loc9 => constants.%.14e
 // CHECK:STDOUT:   %Int.loc22_32.2 => constants.%i32
 // CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a
 // CHECK:STDOUT:   %IntRange => constants.%IntRange.a89
@@ -839,8 +834,8 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:   %require_complete.loc5_16 => constants.%complete_type.f8a
 // CHECK:STDOUT:   %require_complete.loc5_52 => constants.%complete_type.c45
 // CHECK:STDOUT:   %struct_type.start.end => constants.%struct_type.start.end.d0a
-// CHECK:STDOUT:   %.loc6_22.1 => constants.%.14e
 // CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.impl_witness.f17
+// CHECK:STDOUT:   %.loc6_22.1 => constants.%.14e
 // CHECK:STDOUT:   %Copy.facet => constants.%Copy.facet.de4
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.081
 // CHECK:STDOUT:   %.loc6_22.2 => constants.%.8e2
@@ -869,19 +864,19 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:   %IntRange.265: type = class_type @IntRange, @IntRange(%N) [symbolic]
 // CHECK:STDOUT:   %IntRange.elem.302: type = unbound_element_type %IntRange.265, %Int.b6d943.1 [symbolic]
 // CHECK:STDOUT:   %require_complete.2ded7d.1: <witness> = require_complete_type %Int.b6d943.1 [symbolic]
-// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]
-// CHECK:STDOUT:   %pattern_type.bb68b6.1: type = pattern_type %Int.b6d943.1 [symbolic]
-// CHECK:STDOUT:   %.b26: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic]
 // CHECK:STDOUT:   %IntRange.Make.type.1df: type = fn_type @IntRange.Make, @IntRange(%N) [symbolic]
 // CHECK:STDOUT:   %IntRange.Make.8a9: %IntRange.Make.type.1df = struct_value () [symbolic]
 // CHECK:STDOUT:   %pattern_type.b16: type = pattern_type %IntRange.265 [symbolic]
 // CHECK:STDOUT:   %.e1e: Core.Form = init_form %IntRange.265 [symbolic]
+// CHECK:STDOUT:   %pattern_type.bb68b6.1: type = pattern_type %Int.b6d943.1 [symbolic]
+// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.4c7: <witness> = lookup_impl_witness %Int.b6d943.1, @Copy [symbolic]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %Int.b6d943.1, (%Copy.lookup_impl_witness.4c7) [symbolic]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.2e7: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic]
 // CHECK:STDOUT:   %.cf8: type = fn_type_with_self_type %Copy.WithSelf.Op.type.2e7, %Copy.facet [symbolic]
 // CHECK:STDOUT:   %impl.elem0.84f: %.cf8 = impl_witness_access %Copy.lookup_impl_witness.4c7, element0 [symbolic]
 // CHECK:STDOUT:   %specific_impl_fn.508: <specific function> = specific_impl_function %impl.elem0.84f, @Copy.WithSelf.Op(%Copy.facet) [symbolic]
+// CHECK:STDOUT:   %.b26: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic]
 // CHECK:STDOUT:   %require_complete.8a1: <witness> = require_complete_type %IntRange.265 [symbolic]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %IntRange.a89: type = class_type @IntRange, @IntRange(%int_32) [concrete]
@@ -890,7 +885,6 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]
 // CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]
-// CHECK:STDOUT:   %.fc8: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%int_32) [concrete]
 // CHECK:STDOUT:   %IntRange.elem.d76: type = unbound_element_type %IntRange.a89, %i32 [concrete]
 // CHECK:STDOUT:   %struct_type.start.end.0fe: type = struct_type {.start: %i32, .end: %i32} [concrete]
 // CHECK:STDOUT:   %complete_type.a43: <witness> = complete_type_witness %struct_type.start.end.0fe [concrete]
@@ -972,7 +966,6 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %IntRange.Make.type: type = fn_type @IntRange.Make, @IntRange(%N) [symbolic = %IntRange.Make.type (constants.%IntRange.Make.type.1df)]
 // CHECK:STDOUT:   %IntRange.Make: @IntRange.%IntRange.Make.type (%IntRange.Make.type.1df) = struct_value () [symbolic = %IntRange.Make (constants.%IntRange.Make.8a9)]
-// CHECK:STDOUT:   %.1: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic = %.1 (constants.%.b26)]
 // CHECK:STDOUT:   %Int: type = class_type @Int, @Int(%N) [symbolic = %Int (constants.%Int.b6d943.1)]
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Int [symbolic = %require_complete (constants.%require_complete.2ded7d.1)]
 // CHECK:STDOUT:   %IntRange: type = class_type @IntRange, @IntRange(%N) [symbolic = %IntRange (constants.%IntRange.265)]
@@ -1042,8 +1035,8 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:   %require_complete.1: <witness> = require_complete_type %Int [symbolic = %require_complete.1 (constants.%require_complete.2ded7d.1)]
 // CHECK:STDOUT:   %require_complete.2: <witness> = require_complete_type %IntRange [symbolic = %require_complete.2 (constants.%require_complete.8a1)]
 // CHECK:STDOUT:   %struct_type.start.end: type = struct_type {.start: @IntRange.Make.%Int (%Int.b6d943.1), .end: @IntRange.Make.%Int (%Int.b6d943.1)} [symbolic = %struct_type.start.end (constants.%struct_type.start.end.79a)]
-// CHECK:STDOUT:   %.2: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic = %.2 (constants.%.b26)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %Int, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.4c7)]
+// CHECK:STDOUT:   %.2: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic = %.2 (constants.%.b26)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %Int, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.2e7)]
 // CHECK:STDOUT:   %.3: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.3 (constants.%.cf8)]
@@ -1067,7 +1060,6 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %IntRange.Make.type => constants.%IntRange.Make.type.1df
 // CHECK:STDOUT:   %IntRange.Make => constants.%IntRange.Make.8a9
-// CHECK:STDOUT:   %.1 => constants.%.b26
 // CHECK:STDOUT:   %Int => constants.%Int.b6d943.1
 // CHECK:STDOUT:   %require_complete => constants.%require_complete.2ded7d.1
 // CHECK:STDOUT:   %IntRange => constants.%IntRange.265
@@ -1091,7 +1083,6 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %IntRange.Make.type => constants.%IntRange.Make.type.045
 // CHECK:STDOUT:   %IntRange.Make => constants.%IntRange.Make.3e9
-// CHECK:STDOUT:   %.1 => constants.%.fc8
 // CHECK:STDOUT:   %Int => constants.%i32
 // CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a
 // CHECK:STDOUT:   %IntRange => constants.%IntRange.a89

+ 4 - 4
toolchain/check/testdata/function/generic/call.carbon

@@ -95,8 +95,8 @@ fn CallSpecific(x: C*) -> C* {
 // CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]
 // CHECK:STDOUT:   %.cb6: Core.Form = init_form %ptr.e8f [symbolic]
 // CHECK:STDOUT:   %Function.specific_fn.a87: <specific function> = specific_function %Function, @Function(%T.035) [symbolic]
-// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr.e8f, @Copy [symbolic]
+// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.facet.c25: %Copy.type = facet_value %ptr.e8f, (%Copy.lookup_impl_witness.2e6) [symbolic]
 // CHECK:STDOUT:   %Function.specific_fn.919: <specific function> = specific_function %Function, @Function(%Copy.facet.c25) [symbolic]
 // CHECK:STDOUT:   %C: type = class_type @C [concrete]
@@ -211,8 +211,8 @@ fn CallSpecific(x: C*) -> C* {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %.loc18_24.3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc16_19.1) [symbolic = %.loc18_24.3 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc16_33.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]
+// CHECK:STDOUT:   %.loc18_24.3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc16_19.1) [symbolic = %.loc18_24.3 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.facet.loc18_24.3: %Copy.type = facet_value %ptr.loc16_33.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet.loc18_24.3 (constants.%Copy.facet.c25)]
 // CHECK:STDOUT:   %Function.specific_fn.loc18_10.2: <specific function> = specific_function constants.%Function, @Function(%Copy.facet.loc18_24.3) [symbolic = %Function.specific_fn.loc18_10.2 (constants.%Function.specific_fn.919)]
 // CHECK:STDOUT:
@@ -331,8 +331,8 @@ fn CallSpecific(x: C*) -> C* {
 // CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]
 // CHECK:STDOUT:   %.cb6: Core.Form = init_form %ptr.e8f [symbolic]
 // CHECK:STDOUT:   %Function.specific_fn.a87: <specific function> = specific_function %Function, @Function(%T.035) [symbolic]
-// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr.e8f, @Copy [symbolic]
+// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.facet.c25: %Copy.type = facet_value %ptr.e8f, (%Copy.lookup_impl_witness.2e6) [symbolic]
 // CHECK:STDOUT:   %Function.specific_fn.919: <specific function> = specific_function %Function, @Function(%Copy.facet.c25) [symbolic]
 // CHECK:STDOUT:   %C: type = class_type @C [concrete]
@@ -446,8 +446,8 @@ fn CallSpecific(x: C*) -> C* {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %.loc18_20.2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc16_19.1) [symbolic = %.loc18_20.2 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc16_33.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]
+// CHECK:STDOUT:   %.loc18_20.2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc16_19.1) [symbolic = %.loc18_20.2 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.facet.loc18_20.2: %Copy.type = facet_value %ptr.loc16_33.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet.loc18_20.2 (constants.%Copy.facet.c25)]
 // CHECK:STDOUT:   %Function.specific_fn.loc18_10.2: <specific function> = specific_function constants.%Function, @Function(%Copy.facet.loc18_20.2) [symbolic = %Function.specific_fn.loc18_10.2 (constants.%Function.specific_fn.919)]
 // CHECK:STDOUT:

+ 4 - 4
toolchain/check/testdata/function/generic/deduce.carbon

@@ -1672,8 +1672,8 @@ fn F() {
 // CHECK:STDOUT:   %CC.type: type = generic_class_type @CC [concrete]
 // CHECK:STDOUT:   %CC.generic: %CC.type = struct_value () [concrete]
 // CHECK:STDOUT:   %CC.a1b: type = class_type @CC, @CC(%D) [symbolic]
-// CHECK:STDOUT:   %.bf4: require_specific_def_type = require_specific_def @DD.as.Z.impl(%E) [symbolic]
 // CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %DD.a29, @Z [symbolic]
+// CHECK:STDOUT:   %.bf4: require_specific_def_type = require_specific_def @DD.as.Z.impl(%E) [symbolic]
 // CHECK:STDOUT:   %Z.facet.892: %Z.type = facet_value %DD.a29, (%Z.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %CC.4e1: type = class_type @CC, @CC(%Z.facet.892) [symbolic]
 // CHECK:STDOUT:   %Z.impl_witness.40e: <witness> = impl_witness @CC.as.Z.impl.%Z.impl_witness_table, @CC.as.Z.impl(%E) [symbolic]
@@ -1801,8 +1801,8 @@ fn F() {
 // CHECK:STDOUT: generic impl @CC.as.Z.impl(%E.loc12_14.1: type) {
 // CHECK:STDOUT:   %E.loc12_14.2: type = symbolic_binding E, 0 [symbolic = %E.loc12_14.2 (constants.%E)]
 // CHECK:STDOUT:   %DD.loc12_31.2: type = class_type @DD, @DD(%E.loc12_14.2) [symbolic = %DD.loc12_31.2 (constants.%DD.a29)]
-// CHECK:STDOUT:   %.loc12_32.2: require_specific_def_type = require_specific_def @DD.as.Z.impl(%E.loc12_14.2) [symbolic = %.loc12_32.2 (constants.%.bf4)]
 // CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %DD.loc12_31.2, @Z [symbolic = %Z.lookup_impl_witness (constants.%Z.lookup_impl_witness)]
+// CHECK:STDOUT:   %.loc12_32.2: require_specific_def_type = require_specific_def @DD.as.Z.impl(%E.loc12_14.2) [symbolic = %.loc12_32.2 (constants.%.bf4)]
 // CHECK:STDOUT:   %Z.facet.loc12_32.2: %Z.type = facet_value %DD.loc12_31.2, (%Z.lookup_impl_witness) [symbolic = %Z.facet.loc12_32.2 (constants.%Z.facet.892)]
 // CHECK:STDOUT:   %CC.loc12_32.2: type = class_type @CC, @CC(%Z.facet.loc12_32.2) [symbolic = %CC.loc12_32.2 (constants.%CC.4e1)]
 // CHECK:STDOUT:   %Z.impl_witness.loc12_39.2: <witness> = impl_witness %Z.impl_witness_table, @CC.as.Z.impl(%E.loc12_14.2) [symbolic = %Z.impl_witness.loc12_39.2 (constants.%Z.impl_witness.40e)]
@@ -1904,8 +1904,8 @@ fn F() {
 // CHECK:STDOUT: specific @CC.as.Z.impl(constants.%E) {
 // CHECK:STDOUT:   %E.loc12_14.2 => constants.%E
 // CHECK:STDOUT:   %DD.loc12_31.2 => constants.%DD.a29
-// CHECK:STDOUT:   %.loc12_32.2 => constants.%.bf4
 // CHECK:STDOUT:   %Z.lookup_impl_witness => constants.%Z.lookup_impl_witness
+// CHECK:STDOUT:   %.loc12_32.2 => constants.%.bf4
 // CHECK:STDOUT:   %Z.facet.loc12_32.2 => constants.%Z.facet.892
 // CHECK:STDOUT:   %CC.loc12_32.2 => constants.%CC.4e1
 // CHECK:STDOUT:   %Z.impl_witness.loc12_39.2 => constants.%Z.impl_witness.40e
@@ -1934,8 +1934,8 @@ fn F() {
 // CHECK:STDOUT: specific @CC.as.Z.impl(constants.%EE) {
 // CHECK:STDOUT:   %E.loc12_14.2 => constants.%EE
 // CHECK:STDOUT:   %DD.loc12_31.2 => constants.%DD.2e1
-// CHECK:STDOUT:   %.loc12_32.2 => constants.%.36d
 // CHECK:STDOUT:   %Z.lookup_impl_witness => constants.%Z.impl_witness.8a3
+// CHECK:STDOUT:   %.loc12_32.2 => constants.%.36d
 // CHECK:STDOUT:   %Z.facet.loc12_32.2 => constants.%Z.facet.74c
 // CHECK:STDOUT:   %CC.loc12_32.2 => constants.%CC.b19
 // CHECK:STDOUT:   %Z.impl_witness.loc12_39.2 => constants.%Z.impl_witness.cb4

+ 2 - 2
toolchain/check/testdata/function/generic/indirect_generic_type.carbon

@@ -30,8 +30,8 @@ fn F(T:! type, p: T**) -> T* {
 // CHECK:STDOUT:   %.cb6: Core.Form = init_form %ptr.e8f [symbolic]
 // CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]
 // CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]
-// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr.e8f, @Copy [symbolic]
+// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.e8f, (%Copy.lookup_impl_witness.2e6) [symbolic]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.d82: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic]
 // CHECK:STDOUT:   %.299: type = fn_type_with_self_type %Copy.WithSelf.Op.type.d82, %Copy.facet [symbolic]
@@ -44,8 +44,8 @@ fn F(T:! type, p: T**) -> T* {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %.loc6_10.3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc4_6.1) [symbolic = %.loc6_10.3 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc4_20.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]
+// CHECK:STDOUT:   %.loc6_10.3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc4_6.1) [symbolic = %.loc6_10.3 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.loc4_20.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.d82)]
 // CHECK:STDOUT:   %.loc6_10.4: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc6_10.4 (constants.%.299)]

+ 3 - 3
toolchain/check/testdata/function/generic/resolve_used.carbon

@@ -59,8 +59,8 @@ fn CallNegative() {
 // CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]
 // CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]
-// CHECK:STDOUT:   %.4a9: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%Int) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness: <witness> = lookup_impl_witness %Int, @DefaultOrUnformed [symbolic]
+// CHECK:STDOUT:   %.4a9: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%Int) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.facet.c82: %DefaultOrUnformed.type = facet_value %Int, (%DefaultOrUnformed.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.814: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.c82) [symbolic]
 // CHECK:STDOUT:   %.ca4: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.814, %DefaultOrUnformed.facet.c82 [symbolic]
@@ -142,8 +142,8 @@ fn CallNegative() {
 // CHECK:STDOUT:   %Int.loc9_27.2: type = class_type @Int, @Int(%N.loc4_19.1) [symbolic = %Int.loc9_27.2 (constants.%Int)]
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Int.loc9_27.2 [symbolic = %require_complete (constants.%require_complete.901)]
 // CHECK:STDOUT:   %pattern_type: type = pattern_type %Int.loc9_27.2 [symbolic = %pattern_type (constants.%pattern_type.764)]
-// CHECK:STDOUT:   %.loc9_28.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%Int.loc9_27.2) [symbolic = %.loc9_28.3 (constants.%.4a9)]
 // CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc9_27.2, @DefaultOrUnformed [symbolic = %DefaultOrUnformed.lookup_impl_witness (constants.%DefaultOrUnformed.lookup_impl_witness)]
+// CHECK:STDOUT:   %.loc9_28.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%Int.loc9_27.2) [symbolic = %.loc9_28.3 (constants.%.4a9)]
 // CHECK:STDOUT:   %DefaultOrUnformed.facet.loc9_28.2: %DefaultOrUnformed.type = facet_value %Int.loc9_27.2, (%DefaultOrUnformed.lookup_impl_witness) [symbolic = %DefaultOrUnformed.facet.loc9_28.2 (constants.%DefaultOrUnformed.facet.c82)]
 // CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.loc9_28.2) [symbolic = %DefaultOrUnformed.WithSelf.Op.type (constants.%DefaultOrUnformed.WithSelf.Op.type.814)]
 // CHECK:STDOUT:   %.loc9_28.4: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type, %DefaultOrUnformed.facet.loc9_28.2 [symbolic = %.loc9_28.4 (constants.%.ca4)]
@@ -209,8 +209,8 @@ fn CallNegative() {
 // CHECK:STDOUT:   %Int.loc9_27.2 => constants.%i0
 // CHECK:STDOUT:   %require_complete => <error>
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.47b
-// CHECK:STDOUT:   %.loc9_28.3 => constants.%.d6a
 // CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness => constants.%DefaultOrUnformed.impl_witness.879
+// CHECK:STDOUT:   %.loc9_28.3 => constants.%.d6a
 // CHECK:STDOUT:   %DefaultOrUnformed.facet.loc9_28.2 => constants.%DefaultOrUnformed.facet.255
 // CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type => constants.%DefaultOrUnformed.WithSelf.Op.type.bd6
 // CHECK:STDOUT:   %.loc9_28.4 => constants.%.639

+ 2 - 2
toolchain/check/testdata/function/generic/type_param.carbon

@@ -33,8 +33,8 @@ fn F(T:! type) {
 // CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]
 // CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T.67d [symbolic]
 // CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T.67d [symbolic]
-// CHECK:STDOUT:   %.713: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%ptr) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness: <witness> = lookup_impl_witness %ptr, @DefaultOrUnformed [symbolic]
+// CHECK:STDOUT:   %.713: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%ptr) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %ptr, (%DefaultOrUnformed.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.d74: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet) [symbolic]
 // CHECK:STDOUT:   %.425: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.d74, %DefaultOrUnformed.facet [symbolic]
@@ -84,8 +84,8 @@ fn F(T:! type) {
 // CHECK:STDOUT:   %ptr.loc16_11.2: type = ptr_type %T.loc15_6.1 [symbolic = %ptr.loc16_11.2 (constants.%ptr)]
 // CHECK:STDOUT:   %require_complete.loc16: <witness> = require_complete_type %ptr.loc16_11.2 [symbolic = %require_complete.loc16 (constants.%require_complete.ef1)]
 // CHECK:STDOUT:   %pattern_type.loc16: type = pattern_type %ptr.loc16_11.2 [symbolic = %pattern_type.loc16 (constants.%pattern_type.4f4)]
-// CHECK:STDOUT:   %.loc16_12.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%ptr.loc16_11.2) [symbolic = %.loc16_12.3 (constants.%.713)]
 // CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc16_11.2, @DefaultOrUnformed [symbolic = %DefaultOrUnformed.lookup_impl_witness (constants.%DefaultOrUnformed.lookup_impl_witness)]
+// CHECK:STDOUT:   %.loc16_12.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%ptr.loc16_11.2) [symbolic = %.loc16_12.3 (constants.%.713)]
 // CHECK:STDOUT:   %DefaultOrUnformed.facet.loc16_12.2: %DefaultOrUnformed.type = facet_value %ptr.loc16_11.2, (%DefaultOrUnformed.lookup_impl_witness) [symbolic = %DefaultOrUnformed.facet.loc16_12.2 (constants.%DefaultOrUnformed.facet)]
 // CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.loc16_12.2) [symbolic = %DefaultOrUnformed.WithSelf.Op.type (constants.%DefaultOrUnformed.WithSelf.Op.type.d74)]
 // CHECK:STDOUT:   %.loc16_12.4: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type, %DefaultOrUnformed.facet.loc16_12.2 [symbolic = %.loc16_12.4 (constants.%.425)]

+ 2 - 2
toolchain/check/testdata/function/generic/type_param_scope.carbon

@@ -29,8 +29,8 @@ fn F(T:! type, n: T*) -> T* {
 // CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr [symbolic]
 // CHECK:STDOUT:   %.cb6: Core.Form = init_form %ptr [symbolic]
 // CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]
-// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr, @Copy [symbolic]
+// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr, (%Copy.lookup_impl_witness.2e6) [symbolic]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.d82: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic]
 // CHECK:STDOUT:   %.299: type = fn_type_with_self_type %Copy.WithSelf.Op.type.d82, %Copy.facet [symbolic]
@@ -43,8 +43,8 @@ fn F(T:! type, n: T*) -> T* {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %.loc7_10.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc4_6.1) [symbolic = %.loc7_10.1 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc4_20.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]
+// CHECK:STDOUT:   %.loc7_10.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc4_6.1) [symbolic = %.loc7_10.1 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.loc4_20.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.d82)]
 // CHECK:STDOUT:   %.loc7_10.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc7_10.2 (constants.%.299)]

+ 11 - 7
toolchain/check/testdata/generic/dot_self_symbolic_type.carbon

@@ -111,6 +111,7 @@ fn H(T:! type) {
 // CHECK:STDOUT:   %.Self.660472.2: %A.type.ade3d9.3 = symbolic_binding .Self [symbolic]
 // CHECK:STDOUT:   %A.lookup_impl_witness.04abbb.2: <witness> = lookup_impl_witness %.Self.660472.2, @A, @A(%DD) [symbolic]
 // CHECK:STDOUT:   %impl.elem0.f51d29.2: type = impl_witness_access %A.lookup_impl_witness.04abbb.2, element0 [symbolic]
+// CHECK:STDOUT:   %A.lookup_impl_witness.780: <witness> = lookup_impl_witness %T.091, @A, @A(%DD) [symbolic]
 // CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]
 // CHECK:STDOUT:   %D.G.type.235: type = fn_type @D.G, @D(%empty_struct_type) [concrete]
 // CHECK:STDOUT:   %D.G.be1: %D.G.type.235 = struct_value () [concrete]
@@ -121,6 +122,7 @@ fn H(T:! type) {
 // CHECK:STDOUT:   %.Self.f50: %A.type.69e = symbolic_binding .Self [symbolic_self]
 // CHECK:STDOUT:   %A.lookup_impl_witness.219: <witness> = lookup_impl_witness %.Self.f50, @A, @A(%empty_struct_type) [symbolic_self]
 // CHECK:STDOUT:   %impl.elem0.d97: type = impl_witness_access %A.lookup_impl_witness.219, element0 [symbolic_self]
+// CHECK:STDOUT:   %A.lookup_impl_witness.c4c: <witness> = lookup_impl_witness %T.67d, @A, @A(%empty_struct_type) [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: generic class @C(%CC.loc6_9.2: type) {
@@ -216,8 +218,9 @@ fn H(T:! type) {
 // CHECK:STDOUT:   %C.F: @D.G.%C.F.type (%C.F.type.1f899e.2) = struct_value () [symbolic = %C.F (constants.%C.F.faeec9.2)]
 // CHECK:STDOUT:   %A.type: type = facet_type <@A, @A(%DD)> [symbolic = %A.type (constants.%A.type.ade3d9.3)]
 // CHECK:STDOUT:   %.Self.loc11: @D.G.%A.type (%A.type.ade3d9.3) = symbolic_binding .Self [symbolic = %.Self.loc11 (constants.%.Self.660472.2)]
-// CHECK:STDOUT:   %A.lookup_impl_witness: <witness> = lookup_impl_witness %.Self.loc11, @A, @A(%DD) [symbolic = %A.lookup_impl_witness (constants.%A.lookup_impl_witness.04abbb.2)]
-// CHECK:STDOUT:   %impl.elem0: type = impl_witness_access %A.lookup_impl_witness, element0 [symbolic = %impl.elem0 (constants.%impl.elem0.f51d29.2)]
+// CHECK:STDOUT:   %A.lookup_impl_witness.loc11: <witness> = lookup_impl_witness %.Self.loc11, @A, @A(%DD) [symbolic = %A.lookup_impl_witness.loc11 (constants.%A.lookup_impl_witness.04abbb.2)]
+// CHECK:STDOUT:   %impl.elem0: type = impl_witness_access %A.lookup_impl_witness.loc11, element0 [symbolic = %impl.elem0 (constants.%impl.elem0.f51d29.2)]
+// CHECK:STDOUT:   %A.lookup_impl_witness.loc25: <witness> = lookup_impl_witness %T.loc16_8.1, @A, @A(%DD) [symbolic = %A.lookup_impl_witness.loc25 (constants.%A.lookup_impl_witness.780)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn() {
 // CHECK:STDOUT:   !entry:
@@ -293,8 +296,9 @@ fn H(T:! type) {
 // CHECK:STDOUT:   %C.F => constants.%C.F.240
 // CHECK:STDOUT:   %A.type => constants.%A.type.69e
 // CHECK:STDOUT:   %.Self.loc11 => constants.%.Self.f50
-// CHECK:STDOUT:   %A.lookup_impl_witness => constants.%A.lookup_impl_witness.219
+// CHECK:STDOUT:   %A.lookup_impl_witness.loc11 => constants.%A.lookup_impl_witness.219
 // CHECK:STDOUT:   %impl.elem0 => constants.%impl.elem0.d97
+// CHECK:STDOUT:   %A.lookup_impl_witness.loc25 => constants.%A.lookup_impl_witness.c4c
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @C(constants.%empty_struct_type) {
@@ -340,16 +344,16 @@ fn H(T:! type) {
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
 // CHECK:STDOUT:   %ptr.e8f8f9.2: type = ptr_type %DD [symbolic]
 // CHECK:STDOUT:   %B.type.abcc5d.2: type = facet_type <@B, @B(%ptr.e8f8f9.2)> [symbolic]
-// CHECK:STDOUT:   %.77d: require_specific_def_type = require_specific_def @BB.as.B.impl(%ptr.e8f8f9.2, %T.091) [symbolic]
 // CHECK:STDOUT:   %B.lookup_impl_witness.52c: <witness> = lookup_impl_witness %T.091, @B, @B(%ptr.e8f8f9.2) [symbolic]
+// CHECK:STDOUT:   %.77d: require_specific_def_type = require_specific_def @BB.as.B.impl(%ptr.e8f8f9.2, %T.091) [symbolic]
 // CHECK:STDOUT:   %B.facet.b5c: %B.type.abcc5d.2 = facet_value %T.091, (%B.lookup_impl_witness.52c) [symbolic]
 // CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]
 // CHECK:STDOUT:   %D.G.type.235: type = fn_type @D.G, @D(%empty_struct_type) [concrete]
 // CHECK:STDOUT:   %D.G.be1: %D.G.type.235 = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.c28: type = ptr_type %empty_struct_type [concrete]
 // CHECK:STDOUT:   %B.type.a69: type = facet_type <@B, @B(%ptr.c28)> [concrete]
-// CHECK:STDOUT:   %.5ef: require_specific_def_type = require_specific_def @BB.as.B.impl(%ptr.c28, %T.67d) [symbolic]
 // CHECK:STDOUT:   %B.lookup_impl_witness.eb0: <witness> = lookup_impl_witness %T.67d, @B, @B(%ptr.c28) [symbolic]
+// CHECK:STDOUT:   %.5ef: require_specific_def_type = require_specific_def @BB.as.B.impl(%ptr.c28, %T.67d) [symbolic]
 // CHECK:STDOUT:   %B.facet.4b0: %B.type.a69 = facet_value %T.67d, (%B.lookup_impl_witness.eb0) [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -448,8 +452,8 @@ fn H(T:! type) {
 // CHECK:STDOUT:   %DD: type = symbolic_binding DD, 0 [symbolic = %DD (constants.%DD)]
 // CHECK:STDOUT:   %ptr.loc21_14.2: type = ptr_type %DD [symbolic = %ptr.loc21_14.2 (constants.%ptr.e8f8f9.2)]
 // CHECK:STDOUT:   %B.type.loc21_15.2: type = facet_type <@B, @B(%ptr.loc21_14.2)> [symbolic = %B.type.loc21_15.2 (constants.%B.type.abcc5d.2)]
-// CHECK:STDOUT:   %.loc21_7.2: require_specific_def_type = require_specific_def @BB.as.B.impl(%ptr.loc21_14.2, %T.loc15_8.1) [symbolic = %.loc21_7.2 (constants.%.77d)]
 // CHECK:STDOUT:   %B.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc15_8.1, @B, @B(%ptr.loc21_14.2) [symbolic = %B.lookup_impl_witness (constants.%B.lookup_impl_witness.52c)]
+// CHECK:STDOUT:   %.loc21_7.2: require_specific_def_type = require_specific_def @BB.as.B.impl(%ptr.loc21_14.2, %T.loc15_8.1) [symbolic = %.loc21_7.2 (constants.%.77d)]
 // CHECK:STDOUT:   %B.facet.loc21_7.2: @D.G.%B.type.loc21_15.2 (%B.type.abcc5d.2) = facet_value %T.loc15_8.1, (%B.lookup_impl_witness) [symbolic = %B.facet.loc21_7.2 (constants.%B.facet.b5c)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn() {
@@ -511,8 +515,8 @@ fn H(T:! type) {
 // CHECK:STDOUT:   %DD => constants.%empty_struct_type
 // CHECK:STDOUT:   %ptr.loc21_14.2 => constants.%ptr.c28
 // CHECK:STDOUT:   %B.type.loc21_15.2 => constants.%B.type.a69
-// CHECK:STDOUT:   %.loc21_7.2 => constants.%.5ef
 // CHECK:STDOUT:   %B.lookup_impl_witness => constants.%B.lookup_impl_witness.eb0
+// CHECK:STDOUT:   %.loc21_7.2 => constants.%.5ef
 // CHECK:STDOUT:   %B.facet.loc21_7.2 => constants.%B.facet.4b0
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 6 - 0
toolchain/check/testdata/generic/template/unimplemented.carbon

@@ -90,6 +90,7 @@ fn F[template T:! Core.Destroy](x: T) {
 // CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]
 // CHECK:STDOUT:   %MulWith.type.8b4: type = generic_interface_type @MulWith [concrete]
 // CHECK:STDOUT:   %MulWith.generic: %MulWith.type.8b4 = struct_value () [concrete]
+// CHECK:STDOUT:   %MulWith.lookup_impl_witness.052: <witness> = lookup_impl_witness @F.%.loc11_11.5, @MulWith, @MulWith(Core.IntLiteral) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -140,6 +141,7 @@ fn F[template T:! Core.Destroy](x: T) {
 // CHECK:STDOUT:   %.loc11_11.3: <instruction> = refine_type_action %x.ref, %T.loc6_15.1 [template]
 // CHECK:STDOUT:   %.loc11_11.4: <instruction> = access_member_action %.loc11_11.1, n [template]
 // CHECK:STDOUT:   %.loc11_11.5: type = type_of_inst %.loc11_11.4 [template]
+// CHECK:STDOUT:   %MulWith.lookup_impl_witness: <witness> = lookup_impl_witness %.loc11_11.5, @MulWith, @MulWith(Core.IntLiteral) [template = %MulWith.lookup_impl_witness (constants.%MulWith.lookup_impl_witness.052)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%x.param: @F.%T.loc6_15.1 (%T)) -> out %return.param: %i32 {
 // CHECK:STDOUT:   !entry:
@@ -178,6 +180,7 @@ fn F[template T:! Core.Destroy](x: T) {
 // CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]
 // CHECK:STDOUT:   %MulWith.type.8b4: type = generic_interface_type @MulWith [concrete]
 // CHECK:STDOUT:   %MulWith.generic: %MulWith.type.8b4 = struct_value () [concrete]
+// CHECK:STDOUT:   %MulWith.lookup_impl_witness.292: <witness> = lookup_impl_witness @F.%.loc16_11.3, @MulWith, @MulWith(Core.IntLiteral) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -233,6 +236,7 @@ fn F[template T:! Core.Destroy](x: T) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %.loc16_11.2: <instruction> = access_member_action %c.ref, n [template]
 // CHECK:STDOUT:   %.loc16_11.3: type = type_of_inst %.loc16_11.2 [template]
+// CHECK:STDOUT:   %MulWith.lookup_impl_witness: <witness> = lookup_impl_witness %.loc16_11.3, @MulWith, @MulWith(Core.IntLiteral) [template = %MulWith.lookup_impl_witness (constants.%MulWith.lookup_impl_witness.292)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn() -> out %return.param: %i32 {
 // CHECK:STDOUT:   !entry:
@@ -270,6 +274,7 @@ fn F[template T:! Core.Destroy](x: T) {
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
+// CHECK:STDOUT:   %ImplicitAs.lookup_impl_witness.6d3: <witness> = lookup_impl_witness %T.765, @ImplicitAs, @ImplicitAs(%i32) [template]
 // CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]
 // CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]
 // CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %T.765, @Destroy [template]
@@ -329,6 +334,7 @@ fn F[template T:! Core.Destroy](x: T) {
 // CHECK:STDOUT:   %ImplicitAs.type.loc14_3.2: type = facet_type <@ImplicitAs, @ImplicitAs(%T.binding.as_type)> [template = %ImplicitAs.type.loc14_3.2 (constants.%ImplicitAs.type.112)]
 // CHECK:STDOUT:   %.loc14_3.3: <instruction> = access_member_action %ImplicitAs.type.loc14_3.1, Convert [template]
 // CHECK:STDOUT:   %.loc14_3.4: type = type_of_inst %.loc14_3.3 [template]
+// CHECK:STDOUT:   %ImplicitAs.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc4_15.1, @ImplicitAs, @ImplicitAs(constants.%i32) [template = %ImplicitAs.lookup_impl_witness (constants.%ImplicitAs.lookup_impl_witness.6d3)]
 // CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc4_15.1, @Destroy [template = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]
 // CHECK:STDOUT:   %Destroy.WithSelf.Op.type: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%T.loc4_15.1) [template = %Destroy.WithSelf.Op.type (constants.%Destroy.WithSelf.Op.type.cb2e47.2)]
 // CHECK:STDOUT:   %.loc14_3.5: type = fn_type_with_self_type %Destroy.WithSelf.Op.type, %T.loc4_15.1 [template = %.loc14_3.5 (constants.%.d5f)]

+ 2 - 2
toolchain/check/testdata/generic/template_dependence.carbon

@@ -45,8 +45,8 @@ fn F(template T:! type, U:! type) -> (T, U) {
 // CHECK:STDOUT:   %require_complete.fbe: <witness> = require_complete_type %ptr.125 [template]
 // CHECK:STDOUT:   %require_complete.ef162c.1: <witness> = require_complete_type %ptr.e8f8f9.1 [template]
 // CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]
-// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67db0b.1) [template]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr.e8f8f9.1, @Copy [template]
+// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67db0b.1) [template]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.e8f8f9.1, (%Copy.lookup_impl_witness.2e6) [template]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.d82: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [template]
 // CHECK:STDOUT:   %.299: type = fn_type_with_self_type %Copy.WithSelf.Op.type.d82, %Copy.facet [template]
@@ -93,8 +93,8 @@ fn F(template T:! type, U:! type) -> (T, U) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete.loc5_26: <witness> = require_complete_type %ptr.loc5_30.1 [template = %require_complete.loc5_26 (constants.%require_complete.fbe)]
 // CHECK:STDOUT:   %require_complete.loc5_37: <witness> = require_complete_type %ptr.loc5_29.1 [template = %require_complete.loc5_37 (constants.%require_complete.ef162c.1)]
-// CHECK:STDOUT:   %.loc6_10.3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc5_15.1) [template = %.loc6_10.3 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc5_29.1, @Copy [template = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]
+// CHECK:STDOUT:   %.loc6_10.3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc5_15.1) [template = %.loc6_10.3 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.loc5_29.1, (%Copy.lookup_impl_witness) [template = %Copy.facet (constants.%Copy.facet)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [template = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.d82)]
 // CHECK:STDOUT:   %.loc6_10.4: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [template = %.loc6_10.4 (constants.%.299)]

+ 5 - 5
toolchain/check/testdata/impl/error_recovery.carbon

@@ -164,8 +164,8 @@ impl C as I {
 // 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:   %.242: require_specific_def_type = require_specific_def @T.as.Z.impl(%T) [symbolic]
 // CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %T, @Z [symbolic]
+// CHECK:STDOUT:   %.242: require_specific_def_type = require_specific_def @T.as.Z.impl(%T) [symbolic]
 // CHECK:STDOUT:   %Z.facet: %Z.type = facet_value %T, (%Z.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%Z.facet) [symbolic]
 // CHECK:STDOUT: }
@@ -186,8 +186,8 @@ impl C as I {
 // CHECK:STDOUT:   %T.loc13_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc13_6.1 (constants.%T)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %.loc19_6.2: require_specific_def_type = require_specific_def @T.as.Z.impl(%T.loc13_6.1) [symbolic = %.loc19_6.2 (constants.%.242)]
 // CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc13_6.1, @Z [symbolic = %Z.lookup_impl_witness (constants.%Z.lookup_impl_witness)]
+// CHECK:STDOUT:   %.loc19_6.2: require_specific_def_type = require_specific_def @T.as.Z.impl(%T.loc13_6.1) [symbolic = %.loc19_6.2 (constants.%.242)]
 // CHECK:STDOUT:   %Z.facet.loc19_6.2: %Z.type = facet_value %T.loc13_6.1, (%Z.lookup_impl_witness) [symbolic = %Z.facet.loc19_6.2 (constants.%Z.facet)]
 // CHECK:STDOUT:   %F.specific_fn.loc19_3.2: <specific function> = specific_function constants.%F, @F(%Z.facet.loc19_6.2) [symbolic = %F.specific_fn.loc19_3.2 (constants.%F.specific_fn)]
 // CHECK:STDOUT:
@@ -218,8 +218,8 @@ impl C as I {
 // 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:   %.242: require_specific_def_type = require_specific_def @T.as.Z.impl(%T) [symbolic]
 // CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %T, @Z [symbolic]
+// CHECK:STDOUT:   %.242: require_specific_def_type = require_specific_def @T.as.Z.impl(%T) [symbolic]
 // CHECK:STDOUT:   %Z.facet: %Z.type = facet_value %T, (%Z.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%Z.facet) [symbolic]
 // CHECK:STDOUT:   %.194: require_specific_def_type = require_specific_def @T.as.Z.impl(%empty_tuple.type) [concrete]
@@ -241,8 +241,8 @@ impl C as I {
 // CHECK:STDOUT:   %T.loc13_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc13_6.1 (constants.%T)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %.loc19_6.2: require_specific_def_type = require_specific_def @T.as.Z.impl(%T.loc13_6.1) [symbolic = %.loc19_6.2 (constants.%.242)]
 // CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc13_6.1, @Z [symbolic = %Z.lookup_impl_witness (constants.%Z.lookup_impl_witness)]
+// CHECK:STDOUT:   %.loc19_6.2: require_specific_def_type = require_specific_def @T.as.Z.impl(%T.loc13_6.1) [symbolic = %.loc19_6.2 (constants.%.242)]
 // CHECK:STDOUT:   %Z.facet.loc19_6.2: %Z.type = facet_value %T.loc13_6.1, (%Z.lookup_impl_witness) [symbolic = %Z.facet.loc19_6.2 (constants.%Z.facet)]
 // CHECK:STDOUT:   %F.specific_fn.loc19_3.2: <specific function> = specific_function constants.%F, @F(%Z.facet.loc19_6.2) [symbolic = %F.specific_fn.loc19_3.2 (constants.%F.specific_fn)]
 // CHECK:STDOUT:
@@ -266,8 +266,8 @@ impl C as I {
 // CHECK:STDOUT:   %T.loc13_6.1 => constants.%empty_tuple.type
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %.loc19_6.2 => constants.%.194
 // CHECK:STDOUT:   %Z.lookup_impl_witness => <error>
+// CHECK:STDOUT:   %.loc19_6.2 => constants.%.194
 // CHECK:STDOUT:   %Z.facet.loc19_6.2 => <error>
 // CHECK:STDOUT:   %F.specific_fn.loc19_3.2 => <error>
 // CHECK:STDOUT: }

+ 4 - 4
toolchain/check/testdata/impl/impl_thunk.carbon

@@ -837,8 +837,8 @@ impl () as I({}) {
 // CHECK:STDOUT:   %.023143.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.735e75.3, %U.035 [symbolic]
 // CHECK:STDOUT:   %impl.elem0.594c59.2: %.023143.2 = impl_witness_access %Copy.lookup_impl_witness.58dce0.2, element0 [symbolic]
 // CHECK:STDOUT:   %specific_impl_fn.bdce5c.2: <specific function> = specific_impl_function %impl.elem0.594c59.2, @Copy.WithSelf.Op(%U.035) [symbolic]
-// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr.e8f, @Copy [symbolic]
+// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.e8f, (%Copy.lookup_impl_witness.2e6) [symbolic]
 // CHECK:STDOUT:   %empty_tuple.type.as.I.impl.F.specific_fn: <specific function> = specific_function %empty_tuple.type.as.I.impl.F.8be29b.1, @empty_tuple.type.as.I.impl.F.loc10_34.1(%Copy.facet) [symbolic]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.d82: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic]
@@ -929,8 +929,8 @@ impl () as I({}) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %.loc10_34.2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc5_8.1) [symbolic = %.loc10_34.2 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]
+// CHECK:STDOUT:   %.loc10_34.2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc5_8.1) [symbolic = %.loc10_34.2 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.facet.loc10_34.2: %Copy.type = facet_value %ptr, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet.loc10_34.2 (constants.%Copy.facet)]
 // CHECK:STDOUT:   %empty_tuple.type.as.I.impl.F.specific_fn.loc10_34.2: <specific function> = specific_function constants.%empty_tuple.type.as.I.impl.F.8be29b.1, @empty_tuple.type.as.I.impl.F.loc10_34.1(%Copy.facet.loc10_34.2) [symbolic = %empty_tuple.type.as.I.impl.F.specific_fn.loc10_34.2 (constants.%empty_tuple.type.as.I.impl.F.specific_fn)]
 // CHECK:STDOUT:
@@ -1002,8 +1002,8 @@ impl () as I({}) {
 // CHECK:STDOUT:   %.023143.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.735e75.3, %U.035 [symbolic]
 // CHECK:STDOUT:   %impl.elem0.594c59.2: %.023143.2 = impl_witness_access %Copy.lookup_impl_witness.58dce0.2, element0 [symbolic]
 // CHECK:STDOUT:   %specific_impl_fn.bdce5c.2: <specific function> = specific_impl_function %impl.elem0.594c59.2, @Copy.WithSelf.Op(%U.035) [symbolic]
-// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr.e8f, @Copy [symbolic]
+// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.e8f, (%Copy.lookup_impl_witness.2e6) [symbolic]
 // CHECK:STDOUT:   %empty_tuple.type.as.I.impl.F.specific_fn: <specific function> = specific_function %empty_tuple.type.as.I.impl.F.8be29b.1, @empty_tuple.type.as.I.impl.F.loc10_51.1(%Copy.facet) [symbolic]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.d82: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic]
@@ -1102,8 +1102,8 @@ impl () as I({}) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %.loc10_51.2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc5_20.1) [symbolic = %.loc10_51.2 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]
+// CHECK:STDOUT:   %.loc10_51.2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc5_20.1) [symbolic = %.loc10_51.2 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.facet.loc10_51.2: %Copy.type = facet_value %ptr, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet.loc10_51.2 (constants.%Copy.facet)]
 // CHECK:STDOUT:   %empty_tuple.type.as.I.impl.F.specific_fn.loc10_51.2: <specific function> = specific_function constants.%empty_tuple.type.as.I.impl.F.8be29b.1, @empty_tuple.type.as.I.impl.F.loc10_51.1(%Copy.facet.loc10_51.2) [symbolic = %empty_tuple.type.as.I.impl.F.specific_fn.loc10_51.2 (constants.%empty_tuple.type.as.I.impl.F.specific_fn)]
 // CHECK:STDOUT:

+ 4 - 4
toolchain/check/testdata/impl/import_builtin_call.carbon

@@ -113,8 +113,8 @@ var n: Int(64) = MakeFromClass(FromLiteral(64) as OtherInt);
 // CHECK:STDOUT:   %Add.WithSelf.Op.935: %Add.WithSelf.Op.type.6d2 = struct_value () [symbolic]
 // CHECK:STDOUT:   %Double.type: type = fn_type @Double [concrete]
 // CHECK:STDOUT:   %Double: %Double.type = struct_value () [concrete]
-// CHECK:STDOUT:   %.c60: require_specific_def_type = require_specific_def @MyInt.as.Add.impl(%N) [symbolic]
 // CHECK:STDOUT:   %Add.lookup_impl_witness: <witness> = lookup_impl_witness %MyInt, @Add [symbolic]
+// CHECK:STDOUT:   %.c60: require_specific_def_type = require_specific_def @MyInt.as.Add.impl(%N) [symbolic]
 // CHECK:STDOUT:   %Add.facet.9ab: %Add.type = facet_value %MyInt, (%Add.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %Add.WithSelf.Op.type.3e8: type = fn_type @Add.WithSelf.Op, @Add.WithSelf(%Add.facet.9ab) [symbolic]
 // CHECK:STDOUT:   %Add.WithSelf.Op.451: %Add.WithSelf.Op.type.3e8 = struct_value () [symbolic]
@@ -359,8 +359,8 @@ var n: Int(64) = MakeFromClass(FromLiteral(64) as OtherInt);
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %MyInt.loc19_39.1 [symbolic = %require_complete (constants.%require_complete.9fa)]
-// CHECK:STDOUT:   %.loc20_11.1: require_specific_def_type = require_specific_def @MyInt.as.Add.impl(%N.loc19_11.1) [symbolic = %.loc20_11.1 (constants.%.c60)]
 // CHECK:STDOUT:   %Add.lookup_impl_witness: <witness> = lookup_impl_witness %MyInt.loc19_39.1, @Add [symbolic = %Add.lookup_impl_witness (constants.%Add.lookup_impl_witness)]
+// CHECK:STDOUT:   %.loc20_11.1: require_specific_def_type = require_specific_def @MyInt.as.Add.impl(%N.loc19_11.1) [symbolic = %.loc20_11.1 (constants.%.c60)]
 // CHECK:STDOUT:   %Add.facet.loc20_11: %Add.type = facet_value %MyInt.loc19_39.1, (%Add.lookup_impl_witness) [symbolic = %Add.facet.loc20_11 (constants.%Add.facet.9ab)]
 // CHECK:STDOUT:   %Add.WithSelf.Op.type: type = fn_type @Add.WithSelf.Op, @Add.WithSelf(%Add.facet.loc20_11) [symbolic = %Add.WithSelf.Op.type (constants.%Add.WithSelf.Op.type.3e8)]
 // CHECK:STDOUT:   %.loc20_11.2: type = fn_type_with_self_type %Add.WithSelf.Op.type, %Add.facet.loc20_11 [symbolic = %.loc20_11.2 (constants.%.d02)]
@@ -625,8 +625,8 @@ var n: Int(64) = MakeFromClass(FromLiteral(64) as OtherInt);
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %MyInt [symbolic = %require_complete (constants.%require_complete.9fa)]
-// CHECK:STDOUT:   %.2: require_specific_def_type = require_specific_def @MyInt.as.Add.impl(%N) [symbolic = %.2 (constants.%.c60)]
 // CHECK:STDOUT:   %Add.lookup_impl_witness: <witness> = lookup_impl_witness %MyInt, @Add [symbolic = %Add.lookup_impl_witness (constants.%Add.lookup_impl_witness)]
+// CHECK:STDOUT:   %.2: require_specific_def_type = require_specific_def @MyInt.as.Add.impl(%N) [symbolic = %.2 (constants.%.c60)]
 // CHECK:STDOUT:   %Add.facet: %Add.type = facet_value %MyInt, (%Add.lookup_impl_witness) [symbolic = %Add.facet (constants.%Add.facet.9ab)]
 // CHECK:STDOUT:   %Add.WithSelf.Op.type: type = fn_type @Add.WithSelf.Op, @Add.WithSelf(%Add.facet) [symbolic = %Add.WithSelf.Op.type (constants.%Add.WithSelf.Op.type.3e8)]
 // CHECK:STDOUT:   %.3: type = fn_type_with_self_type %Add.WithSelf.Op.type, %Add.facet [symbolic = %.3 (constants.%.d02)]
@@ -735,8 +735,8 @@ var n: Int(64) = MakeFromClass(FromLiteral(64) as OtherInt);
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete => constants.%complete_type.4a1
-// CHECK:STDOUT:   %.2 => constants.%.3de
 // CHECK:STDOUT:   %Add.lookup_impl_witness => constants.%Add.impl_witness.868
+// CHECK:STDOUT:   %.2 => constants.%.3de
 // CHECK:STDOUT:   %Add.facet => constants.%Add.facet.1f9
 // CHECK:STDOUT:   %Add.WithSelf.Op.type => constants.%Add.WithSelf.Op.type.626
 // CHECK:STDOUT:   %.3 => constants.%.166

+ 37 - 79
toolchain/check/testdata/impl/import_generic.carbon

@@ -684,13 +684,13 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.e1f642.1 [symbolic]
 // CHECK:STDOUT:   %empty_struct.a40: %empty_struct_type = struct_value () [concrete]
 // CHECK:STDOUT:   %J.type.d682d6.2: type = facet_type <@J, @J(%empty_struct_type)> [concrete]
-// CHECK:STDOUT:   %Self.e1f642.2: %J.type.d682d6.2 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]
+// CHECK:STDOUT:   %C.type.facet: %type = facet_value %C, () [concrete]
 // CHECK:STDOUT:   %I.type.ab5: type = facet_type <@I, @I(%empty_struct_type)> [concrete]
 // CHECK:STDOUT:   %Self.025: %I.type.ab5 = symbolic_binding Self, 1 [symbolic]
 // CHECK:STDOUT:   %complete_type.5b1: <witness> = complete_type_witness %I.type.ab5 [concrete]
-// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]
-// CHECK:STDOUT:   %C.type.facet: %type = facet_value %C, () [concrete]
 // CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table [concrete]
+// CHECK:STDOUT:   %Self.e1f642.2: %J.type.d682d6.2 = symbolic_binding Self, 1 [symbolic]
 // CHECK:STDOUT:   %I.facet: %I.type.ab5 = facet_value %C, (%I.impl_witness) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -819,7 +819,7 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %Self => constants.%Self.e1f642.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @J.WithSelf(constants.%empty_struct_type, constants.%Self.e1f642.1) {
+// CHECK:STDOUT: specific @J.WithSelf(constants.%empty_struct_type, constants.%C.type.facet) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %T => constants.%empty_struct_type
 // CHECK:STDOUT:   %I.type => constants.%I.type.ab5
@@ -838,13 +838,6 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @J.WithSelf(constants.%empty_struct_type, constants.%C.type.facet) {
-// CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %T => constants.%empty_struct_type
-// CHECK:STDOUT:   %I.type => constants.%I.type.ab5
-// CHECK:STDOUT:   %require_complete => constants.%complete_type.5b1
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
 // CHECK:STDOUT: specific @J.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%empty_struct_type, constants.%C.type.facet) {
 // CHECK:STDOUT:   %T => constants.%empty_struct_type
 // CHECK:STDOUT:   %J.type => constants.%J.type.d682d6.2
@@ -853,6 +846,13 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %I.type => constants.%I.type.ab5
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: specific @J.WithSelf(constants.%empty_struct_type, constants.%Self.e1f642.1) {
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %T => constants.%empty_struct_type
+// CHECK:STDOUT:   %I.type => constants.%I.type.ab5
+// CHECK:STDOUT:   %require_complete => constants.%complete_type.5b1
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
 // CHECK:STDOUT: specific @I.WithSelf(constants.%empty_struct_type, constants.%I.facet) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT: }
@@ -1144,11 +1144,10 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %N.type.b47: type = generic_named_constaint_type @N [concrete]
 // CHECK:STDOUT:   %empty_struct: %N.type.b47 = struct_value () [concrete]
 // CHECK:STDOUT:   %N.type.d682d6.1: type = facet_type <@N, @N(%T)> [symbolic]
-// CHECK:STDOUT:   %Self.e1f642.1: %N.type.d682d6.1 = symbolic_binding Self, 1 [symbolic]
-// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.e1f642.1 [symbolic]
+// CHECK:STDOUT:   %Self.e1f: %N.type.d682d6.1 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.e1f [symbolic]
 // CHECK:STDOUT:   %C.type.facet: %type = facet_value %C, () [concrete]
 // CHECK:STDOUT:   %N.type.d682d6.2: type = facet_type <@N, @N(%ptr)> [symbolic]
-// CHECK:STDOUT:   %Self.e1f642.2: %N.type.d682d6.2 = symbolic_binding Self, 1 [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -1173,7 +1172,7 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %Main.import_ref.213: type = import_ref Main//import_generic, loc15_18, loaded [symbolic = @N.WithSelf.Self.binding.as_type.impls.I.type.require.%Self.binding.as_type (constants.%Self.binding.as_type)]
 // CHECK:STDOUT:   %Main.import_ref.3582b1.2: type = import_ref Main//import_generic, loc15_27, loaded [symbolic = @N.WithSelf.Self.binding.as_type.impls.I.type.require.%I.type (constants.%I.type.1ab)]
 // CHECK:STDOUT:   %Main.import_ref.b3bc94.6: type = import_ref Main//import_generic, loc14_14, loaded [symbolic = @N.%T (constants.%T)]
-// CHECK:STDOUT:   %Main.import_ref.2fc394.2: @N.%N.type (%N.type.d682d6.1) = import_ref Main//import_generic, loc14_24, loaded [symbolic = @N.%Self (constants.%Self.e1f642.1)]
+// CHECK:STDOUT:   %Main.import_ref.2fc394.2: @N.%N.type (%N.type.d682d6.1) = import_ref Main//import_generic, loc14_24, loaded [symbolic = @N.%Self (constants.%Self.e1f)]
 // CHECK:STDOUT:   %Main.import_ref.830 = import_ref Main//import_generic, loc14_24, unloaded
 // CHECK:STDOUT:   %Main.import_ref.b3bc94.7: type = import_ref Main//import_generic, loc14_14, loaded [symbolic = @N.%T (constants.%T)]
 // CHECK:STDOUT: }
@@ -1290,7 +1289,7 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.d682d6.1)]
-// CHECK:STDOUT:   %Self: @N.%N.type (%N.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f642.1)]
+// CHECK:STDOUT:   %Self: @N.%N.type (%N.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   constraint {
 // CHECK:STDOUT:   !members:
@@ -1307,7 +1306,7 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT: generic require @N.WithSelf.Self.binding.as_type.impls.I.type.require(imports.%Main.import_ref.b3bc94.6: type, imports.%Main.import_ref.2fc394.2: @N.%N.type (%N.type.d682d6.1)) [from "import_generic.carbon"] {
 // CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]
 // CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.d682d6.1)]
-// CHECK:STDOUT:   %Self: @N.WithSelf.Self.binding.as_type.impls.I.type.require.%N.type (%N.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f642.1)]
+// CHECK:STDOUT:   %Self: @N.WithSelf.Self.binding.as_type.impls.I.type.require.%N.type (%N.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f)]
 // CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
 // CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.1ab)]
 // CHECK:STDOUT: }
@@ -1460,23 +1459,14 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @N(constants.%T) {
 // CHECK:STDOUT:   %T => constants.%T
-// CHECK:STDOUT:
-// CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.1
-// CHECK:STDOUT:   %Self => constants.%Self.e1f642.1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @N.WithSelf(constants.%T, constants.%Self.e1f642.1) {
-// CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %T => constants.%T
-// CHECK:STDOUT:   %I.type => constants.%I.type.1ab
-// CHECK:STDOUT:   %require_complete => constants.%require_complete.e36
-// CHECK:STDOUT: }
+// CHECK:STDOUT: specific @N.WithSelf(constants.%T, constants.%Self.e1f) {}
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%T, constants.%Self.e1f642.1) {
+// CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%T, constants.%Self.e1f) {
 // CHECK:STDOUT:   %T => constants.%T
 // CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.1
-// CHECK:STDOUT:   %Self => constants.%Self.e1f642.1
+// CHECK:STDOUT:   %Self => constants.%Self.e1f
 // CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type
 // CHECK:STDOUT:   %I.type => constants.%I.type.1ab
 // CHECK:STDOUT: }
@@ -1503,17 +1493,6 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @N(constants.%ptr) {
 // CHECK:STDOUT:   %T => constants.%ptr
-// CHECK:STDOUT:
-// CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.2
-// CHECK:STDOUT:   %Self => constants.%Self.e1f642.2
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: specific @N.WithSelf(constants.%ptr, constants.%Self.e1f642.1) {
-// CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %T => constants.%ptr
-// CHECK:STDOUT:   %I.type => constants.%I.type.e19
-// CHECK:STDOUT:   %require_complete => constants.%require_complete.ffd
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @N.WithSelf(constants.%ptr, constants.%C.type.facet) {
@@ -1755,11 +1734,11 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.e1f642.1 [symbolic]
 // CHECK:STDOUT:   %ptr.125: type = ptr_type %ptr.e8f [symbolic]
 // CHECK:STDOUT:   %N.type.d682d6.2: type = facet_type <@N, @N(%ptr.125)> [symbolic]
-// CHECK:STDOUT:   %Self.e1f642.2: %N.type.d682d6.2 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %C.type.facet: %type = facet_value %C, () [concrete]
 // CHECK:STDOUT:   %I.type.08a: type = facet_type <@I, @I(%ptr.125)> [symbolic]
 // CHECK:STDOUT:   %require_complete.ea6: <witness> = require_complete_type %I.type.08a [symbolic]
-// CHECK:STDOUT:   %C.type.facet: %type = facet_value %C, () [concrete]
 // CHECK:STDOUT:   %I.impl_witness.d57: <witness> = impl_witness @C.as.I.impl.c93.%I.impl_witness_table, @C.as.I.impl.c93(%T) [symbolic]
+// CHECK:STDOUT:   %Self.e1f642.2: %N.type.d682d6.2 = symbolic_binding Self, 1 [symbolic]
 // CHECK:STDOUT:   %require_complete.533: <witness> = require_complete_type %N.type.d682d6.2 [symbolic]
 // CHECK:STDOUT:   %I.facet.3e9: %I.type.08a = facet_value %C, (%I.impl_witness.d57) [symbolic]
 // CHECK:STDOUT: }
@@ -1989,7 +1968,7 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %Self => constants.%Self.e1f642.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @N.WithSelf(constants.%ptr.125, constants.%Self.e1f642.1) {
+// CHECK:STDOUT: specific @N.WithSelf(constants.%ptr.125, constants.%C.type.facet) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %T => constants.%ptr.125
 // CHECK:STDOUT:   %I.type => constants.%I.type.08a
@@ -2000,13 +1979,6 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %T => constants.%ptr.125
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @N.WithSelf(constants.%ptr.125, constants.%C.type.facet) {
-// CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %T => constants.%ptr.125
-// CHECK:STDOUT:   %I.type => constants.%I.type.08a
-// CHECK:STDOUT:   %require_complete => constants.%require_complete.ea6
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
 // CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%ptr.125, constants.%C.type.facet) {
 // CHECK:STDOUT:   %T => constants.%ptr.125
 // CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.2
@@ -2023,6 +1995,13 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %I.impl_witness.loc6_36.2 => constants.%I.impl_witness.d57
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: specific @N.WithSelf(constants.%ptr.125, constants.%Self.e1f642.1) {
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %T => constants.%ptr.125
+// CHECK:STDOUT:   %I.type => constants.%I.type.08a
+// CHECK:STDOUT:   %require_complete => constants.%require_complete.ea6
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
 // CHECK:STDOUT: specific @I.WithSelf(constants.%ptr.125, constants.%I.facet.3e9) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT: }
@@ -2259,12 +2238,11 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %N.type.b47: type = generic_named_constaint_type @N [concrete]
 // CHECK:STDOUT:   %empty_struct: %N.type.b47 = struct_value () [concrete]
 // CHECK:STDOUT:   %N.type.d682d6.1: type = facet_type <@N, @N(%T)> [symbolic]
-// CHECK:STDOUT:   %Self.e1f642.1: %N.type.d682d6.1 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %Self.e1f: %N.type.d682d6.1 = symbolic_binding Self, 1 [symbolic]
 // CHECK:STDOUT:   %require_complete.cc6: <witness> = require_complete_type %J.type.04e [symbolic]
-// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.e1f642.1 [symbolic]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.e1f [symbolic]
 // CHECK:STDOUT:   %D.type.facet: %type = facet_value %D, () [concrete]
 // CHECK:STDOUT:   %N.type.d682d6.2: type = facet_type <@N, @N(%ptr)> [symbolic]
-// CHECK:STDOUT:   %Self.e1f642.2: %N.type.d682d6.2 = symbolic_binding Self, 1 [symbolic]
 // CHECK:STDOUT:   %require_complete.19b: <witness> = require_complete_type %J.type.80f [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -2288,7 +2266,7 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %Main.import_ref.213: type = import_ref Main//import_generic_decl, loc8_18, loaded [symbolic = @N.WithSelf.Self.binding.as_type.impls.J.type.require.%Self.binding.as_type (constants.%Self.binding.as_type)]
 // CHECK:STDOUT:   %Main.import_ref.f2a55c.2: type = import_ref Main//import_generic_decl, loc8_27, loaded [symbolic = @N.WithSelf.Self.binding.as_type.impls.J.type.require.%J.type (constants.%J.type.04e)]
 // CHECK:STDOUT:   %Main.import_ref.b3bc94.6: type = import_ref Main//import_generic_decl, loc7_14, loaded [symbolic = @N.%T (constants.%T)]
-// CHECK:STDOUT:   %Main.import_ref.2fc394.2: @N.%N.type (%N.type.d682d6.1) = import_ref Main//import_generic_decl, loc7_24, loaded [symbolic = @N.%Self (constants.%Self.e1f642.1)]
+// CHECK:STDOUT:   %Main.import_ref.2fc394.2: @N.%N.type (%N.type.d682d6.1) = import_ref Main//import_generic_decl, loc7_24, loaded [symbolic = @N.%Self (constants.%Self.e1f)]
 // CHECK:STDOUT:   %Main.import_ref.830 = import_ref Main//import_generic_decl, loc7_24, unloaded
 // CHECK:STDOUT:   %Main.import_ref.b3bc94.7: type = import_ref Main//import_generic_decl, loc7_14, loaded [symbolic = @N.%T (constants.%T)]
 // CHECK:STDOUT: }
@@ -2405,7 +2383,7 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.d682d6.1)]
-// CHECK:STDOUT:   %Self: @N.%N.type (%N.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f642.1)]
+// CHECK:STDOUT:   %Self: @N.%N.type (%N.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   constraint {
 // CHECK:STDOUT:   !members:
@@ -2422,7 +2400,7 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT: generic require @N.WithSelf.Self.binding.as_type.impls.J.type.require(imports.%Main.import_ref.b3bc94.6: type, imports.%Main.import_ref.2fc394.2: @N.%N.type (%N.type.d682d6.1)) [from "fail_import_generic_decl.carbon"] {
 // CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]
 // CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.d682d6.1)]
-// CHECK:STDOUT:   %Self: @N.WithSelf.Self.binding.as_type.impls.J.type.require.%N.type (%N.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f642.1)]
+// CHECK:STDOUT:   %Self: @N.WithSelf.Self.binding.as_type.impls.J.type.require.%N.type (%N.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f)]
 // CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
 // CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.04e)]
 // CHECK:STDOUT: }
@@ -2569,23 +2547,14 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @N(constants.%T) {
 // CHECK:STDOUT:   %T => constants.%T
-// CHECK:STDOUT:
-// CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.1
-// CHECK:STDOUT:   %Self => constants.%Self.e1f642.1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @N.WithSelf(constants.%T, constants.%Self.e1f642.1) {
-// CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %T => constants.%T
-// CHECK:STDOUT:   %J.type => constants.%J.type.04e
-// CHECK:STDOUT:   %require_complete => constants.%require_complete.cc6
-// CHECK:STDOUT: }
+// CHECK:STDOUT: specific @N.WithSelf(constants.%T, constants.%Self.e1f) {}
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.J.type.require(constants.%T, constants.%Self.e1f642.1) {
+// CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.J.type.require(constants.%T, constants.%Self.e1f) {
 // CHECK:STDOUT:   %T => constants.%T
 // CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.1
-// CHECK:STDOUT:   %Self => constants.%Self.e1f642.1
+// CHECK:STDOUT:   %Self => constants.%Self.e1f
 // CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type
 // CHECK:STDOUT:   %J.type => constants.%J.type.04e
 // CHECK:STDOUT: }
@@ -2612,17 +2581,6 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @N(constants.%ptr) {
 // CHECK:STDOUT:   %T => constants.%ptr
-// CHECK:STDOUT:
-// CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.2
-// CHECK:STDOUT:   %Self => constants.%Self.e1f642.2
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: specific @N.WithSelf(constants.%ptr, constants.%Self.e1f642.1) {
-// CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %T => constants.%ptr
-// CHECK:STDOUT:   %J.type => constants.%J.type.80f
-// CHECK:STDOUT:   %require_complete => constants.%require_complete.19b
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @N.WithSelf(constants.%ptr, constants.%D.type.facet) {

+ 16 - 38
toolchain/check/testdata/impl/import_self_specific.carbon

@@ -93,9 +93,9 @@ impl forall [N:! E] D(N) as I where .Assoc = () {
 // CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %Self.ab9, @I [symbolic]
 // CHECK:STDOUT:   %impl.elem0: %Y.type = impl_witness_access %I.lookup_impl_witness, element0 [symbolic]
 // CHECK:STDOUT:   %as_type: type = facet_access_type %impl.elem0 [symbolic]
+// CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %impl.elem0, @Z [symbolic]
 // CHECK:STDOUT:   %Z.impl_witness.64d: <witness> = impl_witness @U.as.Z.impl.%Z.impl_witness_table, @U.as.Z.impl(%as_type) [symbolic]
 // CHECK:STDOUT:   %.bf4: require_specific_def_type = require_specific_def @U.as.Z.impl(%as_type) [symbolic]
-// CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %impl.elem0, @Z [symbolic]
 // CHECK:STDOUT:   %Z.facet.05b: %Z.type = facet_value %as_type, (%Z.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %C.6ff: type = class_type @C, @C(%Z.facet.05b) [symbolic]
 // CHECK:STDOUT:   %pattern_type.850: type = pattern_type %C.6ff [symbolic]
@@ -260,8 +260,8 @@ impl forall [N:! E] D(N) as I where .Assoc = () {
 // CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %Self, @I [symbolic = %I.lookup_impl_witness (constants.%I.lookup_impl_witness)]
 // CHECK:STDOUT:   %impl.elem0.loc24_13.1: %Y.type = impl_witness_access %I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc24_13.1 (constants.%impl.elem0)]
 // CHECK:STDOUT:   %as_type: type = facet_access_type %impl.elem0.loc24_13.1 [symbolic = %as_type (constants.%as_type)]
-// CHECK:STDOUT:   %.loc24_18.1: require_specific_def_type = require_specific_def @U.as.Z.impl(%as_type) [symbolic = %.loc24_18.1 (constants.%.bf4)]
 // CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %impl.elem0.loc24_13.1, @Z [symbolic = %Z.lookup_impl_witness (constants.%Z.lookup_impl_witness)]
+// CHECK:STDOUT:   %.loc24_18.1: require_specific_def_type = require_specific_def @U.as.Z.impl(%as_type) [symbolic = %.loc24_18.1 (constants.%.bf4)]
 // CHECK:STDOUT:   %Z.facet.loc24_18.1: %Z.type = facet_value %as_type, (%Z.lookup_impl_witness) [symbolic = %Z.facet.loc24_18.1 (constants.%Z.facet.05b)]
 // CHECK:STDOUT:   %C.loc24_18.1: type = class_type @C, @C(%Z.facet.loc24_18.1) [symbolic = %C.loc24_18.1 (constants.%C.6ff)]
 // CHECK:STDOUT:   %pattern_type: type = pattern_type %C.loc24_18.1 [symbolic = %pattern_type (constants.%pattern_type.850)]
@@ -317,8 +317,8 @@ impl forall [N:! E] D(N) as I where .Assoc = () {
 // CHECK:STDOUT:   %I.lookup_impl_witness => constants.%I.lookup_impl_witness
 // CHECK:STDOUT:   %impl.elem0.loc24_13.1 => constants.%impl.elem0
 // CHECK:STDOUT:   %as_type => constants.%as_type
-// CHECK:STDOUT:   %.loc24_18.1 => constants.%.bf4
 // CHECK:STDOUT:   %Z.lookup_impl_witness => constants.%Z.lookup_impl_witness
+// CHECK:STDOUT:   %.loc24_18.1 => constants.%.bf4
 // CHECK:STDOUT:   %Z.facet.loc24_18.1 => constants.%Z.facet.05b
 // CHECK:STDOUT:   %C.loc24_18.1 => constants.%C.6ff
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.850
@@ -349,8 +349,8 @@ impl forall [N:! E] D(N) as I where .Assoc = () {
 // CHECK:STDOUT:   %Self.d4d: %Y.type = symbolic_binding Self, 0 [symbolic]
 // CHECK:STDOUT:   %impl.elem0.37f: %Y.type = impl_witness_access %I.lookup_impl_witness.99c, element0 [symbolic]
 // CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %impl.elem0.37f, @Z [symbolic]
-// CHECK:STDOUT:   %as_type.124: type = facet_access_type %impl.elem0.37f [symbolic]
-// CHECK:STDOUT:   %Z.facet.fd6: %Z.type = facet_value %as_type.124, (%Z.lookup_impl_witness) [symbolic]
+// CHECK:STDOUT:   %as_type: type = facet_access_type %impl.elem0.37f [symbolic]
+// CHECK:STDOUT:   %Z.facet.fd6: %Z.type = facet_value %as_type, (%Z.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]
 // CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]
 // CHECK:STDOUT:   %complete_type.782: <witness> = complete_type_witness %empty_tuple.type [concrete]
@@ -359,19 +359,16 @@ impl forall [N:! E] D(N) as I where .Assoc = () {
 // CHECK:STDOUT:   %pattern_type.be3: type = pattern_type %C.ffe [symbolic]
 // CHECK:STDOUT:   %U: type = symbolic_binding U, 0 [symbolic]
 // CHECK:STDOUT:   %Z.impl_witness.856: <witness> = impl_witness imports.%Z.impl_witness_table, @U.as.Z.impl(%U) [symbolic]
-// CHECK:STDOUT:   %.3cb: require_specific_def_type = require_specific_def @U.as.Z.impl(%as_type.124) [symbolic]
-// CHECK:STDOUT:   %Z.impl_witness.907: <witness> = impl_witness imports.%Z.impl_witness_table, @U.as.Z.impl(%as_type.124) [symbolic]
+// CHECK:STDOUT:   %.3cb: require_specific_def_type = require_specific_def @U.as.Z.impl(%as_type) [symbolic]
+// CHECK:STDOUT:   %Z.impl_witness.907: <witness> = impl_witness imports.%Z.impl_witness_table, @U.as.Z.impl(%as_type) [symbolic]
 // CHECK:STDOUT:   %.Self.1dc: %I.type = symbolic_binding .Self [symbolic_self]
-// CHECK:STDOUT:   %I.lookup_impl_witness.c4b: <witness> = lookup_impl_witness %.Self.1dc, @I [symbolic_self]
-// CHECK:STDOUT:   %impl.elem0.66e: %Y.type = impl_witness_access %I.lookup_impl_witness.c4b, element0 [symbolic_self]
-// CHECK:STDOUT:   %as_type.ad8: type = facet_access_type %impl.elem0.66e [symbolic_self]
-// CHECK:STDOUT:   %Z.impl_witness.619: <witness> = impl_witness imports.%Z.impl_witness_table, @U.as.Z.impl(%as_type.ad8) [symbolic_self]
-// CHECK:STDOUT:   %.d02: require_specific_def_type = require_specific_def @U.as.Z.impl(%as_type.ad8) [symbolic_self]
 // CHECK:STDOUT:   %I.WithSelf.F.type.29d: type = fn_type @I.WithSelf.F, @I.WithSelf(%.Self.1dc) [symbolic_self]
 // CHECK:STDOUT:   %I.WithSelf.F.8ec: %I.WithSelf.F.type.29d = struct_value () [symbolic_self]
 // CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.1dc [symbolic_self]
 // CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]
 // CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.c8f [concrete]
+// CHECK:STDOUT:   %I.lookup_impl_witness.c4b: <witness> = lookup_impl_witness %.Self.1dc, @I [symbolic_self]
+// CHECK:STDOUT:   %impl.elem0.66e: %Y.type = impl_witness_access %I.lookup_impl_witness.c4b, element0 [symbolic_self]
 // CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
 // CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]
 // CHECK:STDOUT:   %Y.impl_witness.d43: <witness> = impl_witness imports.%Y.impl_witness_table, @T.as.Y.impl(%T) [symbolic]
@@ -593,9 +590,9 @@ impl forall [N:! E] D(N) as I where .Assoc = () {
 // CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self.651)]
 // CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %Self, @I [symbolic = %I.lookup_impl_witness (constants.%I.lookup_impl_witness.99c)]
 // CHECK:STDOUT:   %impl.elem0: %Y.type = impl_witness_access %I.lookup_impl_witness, element0 [symbolic = %impl.elem0 (constants.%impl.elem0.37f)]
-// CHECK:STDOUT:   %as_type: type = facet_access_type %impl.elem0 [symbolic = %as_type (constants.%as_type.124)]
-// CHECK:STDOUT:   %.1: require_specific_def_type = require_specific_def @U.as.Z.impl(%as_type) [symbolic = %.1 (constants.%.3cb)]
+// CHECK:STDOUT:   %as_type: type = facet_access_type %impl.elem0 [symbolic = %as_type (constants.%as_type)]
 // CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %impl.elem0, @Z [symbolic = %Z.lookup_impl_witness (constants.%Z.lookup_impl_witness)]
+// CHECK:STDOUT:   %.1: require_specific_def_type = require_specific_def @U.as.Z.impl(%as_type) [symbolic = %.1 (constants.%.3cb)]
 // CHECK:STDOUT:   %Z.facet: %Z.type = facet_value %as_type, (%Z.lookup_impl_witness) [symbolic = %Z.facet (constants.%Z.facet.fd6)]
 // CHECK:STDOUT:   %C: type = class_type @C, @C(%Z.facet) [symbolic = %C (constants.%C.ffe)]
 // CHECK:STDOUT:   %pattern_type: type = pattern_type %C [symbolic = %pattern_type (constants.%pattern_type.be3)]
@@ -619,10 +616,6 @@ impl forall [N:! E] D(N) as I where .Assoc = () {
 // CHECK:STDOUT: specific @I.WithSelf(constants.%Self.651) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %Self => constants.%Self.651
-// CHECK:STDOUT:   %I.lookup_impl_witness => constants.%I.lookup_impl_witness.99c
-// CHECK:STDOUT:   %impl.elem0 => constants.%impl.elem0.37f
-// CHECK:STDOUT:   %as_type => constants.%as_type.124
-// CHECK:STDOUT:   %.1 => constants.%.3cb
 // CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.a1f
 // CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.cc3
 // CHECK:STDOUT: }
@@ -648,8 +641,8 @@ impl forall [N:! E] D(N) as I where .Assoc = () {
 // CHECK:STDOUT:   %Z.impl_witness => constants.%Z.impl_witness.856
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @U.as.Z.impl(constants.%as_type.124) {
-// CHECK:STDOUT:   %U => constants.%as_type.124
+// CHECK:STDOUT: specific @U.as.Z.impl(constants.%as_type) {
+// CHECK:STDOUT:   %U => constants.%as_type
 // CHECK:STDOUT:   %Z.impl_witness => constants.%Z.impl_witness.907
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
@@ -659,9 +652,9 @@ impl forall [N:! E] D(N) as I where .Assoc = () {
 // CHECK:STDOUT:   %Self => constants.%Self.651
 // CHECK:STDOUT:   %I.lookup_impl_witness => constants.%I.lookup_impl_witness.99c
 // CHECK:STDOUT:   %impl.elem0 => constants.%impl.elem0.37f
-// CHECK:STDOUT:   %as_type => constants.%as_type.124
-// CHECK:STDOUT:   %.1 => constants.%.3cb
+// CHECK:STDOUT:   %as_type => constants.%as_type
 // CHECK:STDOUT:   %Z.lookup_impl_witness => constants.%Z.lookup_impl_witness
+// CHECK:STDOUT:   %.1 => constants.%.3cb
 // CHECK:STDOUT:   %Z.facet => constants.%Z.facet.fd6
 // CHECK:STDOUT:   %C => constants.%C.ffe
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.be3
@@ -670,21 +663,10 @@ impl forall [N:! E] D(N) as I where .Assoc = () {
 // CHECK:STDOUT: specific @I.WithSelf(constants.%.Self.1dc) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %Self => constants.%.Self.1dc
-// CHECK:STDOUT:   %I.lookup_impl_witness => constants.%I.lookup_impl_witness.c4b
-// CHECK:STDOUT:   %impl.elem0 => constants.%impl.elem0.66e
-// CHECK:STDOUT:   %as_type => constants.%as_type.ad8
-// CHECK:STDOUT:   %.1 => constants.%.d02
 // CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.29d
 // CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.8ec
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @U.as.Z.impl(constants.%as_type.ad8) {
-// CHECK:STDOUT:   %U => constants.%as_type.ad8
-// CHECK:STDOUT:   %Z.impl_witness => constants.%Z.impl_witness.619
-// CHECK:STDOUT:
-// CHECK:STDOUT: !definition:
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
 // CHECK:STDOUT: specific @T.as.Y.impl(constants.%T) {
 // CHECK:STDOUT:   %T => constants.%T
 // CHECK:STDOUT:   %Y.impl_witness => constants.%Y.impl_witness.d43
@@ -725,10 +707,6 @@ impl forall [N:! E] D(N) as I where .Assoc = () {
 // CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %Self => constants.%I.facet
-// CHECK:STDOUT:   %I.lookup_impl_witness => constants.%I.impl_witness
-// CHECK:STDOUT:   %impl.elem0 => constants.%Y.facet
-// CHECK:STDOUT:   %as_type => constants.%empty_tuple.type
-// CHECK:STDOUT:   %.1 => constants.%.194
 // CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.a33
 // CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.b0f
 // CHECK:STDOUT: }
@@ -738,8 +716,8 @@ impl forall [N:! E] D(N) as I where .Assoc = () {
 // CHECK:STDOUT:   %I.lookup_impl_witness => constants.%I.impl_witness
 // CHECK:STDOUT:   %impl.elem0 => constants.%Y.facet
 // CHECK:STDOUT:   %as_type => constants.%empty_tuple.type
-// CHECK:STDOUT:   %.1 => constants.%.194
 // CHECK:STDOUT:   %Z.lookup_impl_witness => constants.%Z.impl_witness.db1
+// CHECK:STDOUT:   %.1 => constants.%.194
 // CHECK:STDOUT:   %Z.facet => constants.%Z.facet.8bd
 // CHECK:STDOUT:   %C => constants.%C.a44
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.479

+ 1 - 3
toolchain/check/testdata/impl/incomplete.carbon

@@ -897,9 +897,7 @@ interface B {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @Y.WithSelf(constants.%Self.550) {
-// CHECK:STDOUT: !definition:
-// CHECK:STDOUT: }
+// CHECK:STDOUT: specific @Y.WithSelf(constants.%Self.550) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @Y.WithSelf.Self.binding.as_type.impls.Z.type.require(constants.%Self.550) {
 // CHECK:STDOUT:   %Self => constants.%Self.550

+ 3 - 3
toolchain/check/testdata/impl/lookup/generic.carbon

@@ -386,8 +386,8 @@ fn G(x: A) {
 // CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]
 // CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]
-// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr.e8f, @Copy [symbolic]
+// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.facet.c25: %Copy.type = facet_value %ptr.e8f, (%Copy.lookup_impl_witness.2e6) [symbolic]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.d82: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.c25) [symbolic]
 // CHECK:STDOUT:   %.299: type = fn_type_with_self_type %Copy.WithSelf.Op.type.d82, %Copy.facet.c25 [symbolic]
@@ -559,8 +559,8 @@ fn G(x: A) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr.loc9_14 [symbolic = %require_complete (constants.%require_complete.ef1)]
-// CHECK:STDOUT:   %.loc9_37.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T) [symbolic = %.loc9_37.1 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc9_14, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]
+// CHECK:STDOUT:   %.loc9_37.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T) [symbolic = %.loc9_37.1 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.loc9_14, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet.c25)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.d82)]
 // CHECK:STDOUT:   %.loc9_37.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc9_37.2 (constants.%.299)]
@@ -662,8 +662,8 @@ fn G(x: A) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete => constants.%complete_type
-// CHECK:STDOUT:   %.loc9_37.1 => constants.%.07c
 // CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.impl_witness.3fd
+// CHECK:STDOUT:   %.loc9_37.1 => constants.%.07c
 // CHECK:STDOUT:   %Copy.facet => constants.%Copy.facet.111
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.514
 // CHECK:STDOUT:   %.loc9_37.2 => constants.%.237

+ 5 - 5
toolchain/check/testdata/impl/lookup/impl_forall.carbon

@@ -70,8 +70,8 @@ fn TestSpecific(a: A({})*) -> {}* {
 // CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]
 // CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4455.1: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e93b.1: %ptr.as.Copy.impl.Op.type.2d4455.1 = struct_value () [symbolic]
-// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%V.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr.e8f8f9.2, @Copy [symbolic]
+// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%V.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.facet.c25: %Copy.type = facet_value %ptr.e8f8f9.2, (%Copy.lookup_impl_witness.2e6) [symbolic]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.d82: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.c25) [symbolic]
 // CHECK:STDOUT:   %.299: type = fn_type_with_self_type %Copy.WithSelf.Op.type.d82, %Copy.facet.c25 [symbolic]
@@ -88,11 +88,11 @@ fn TestSpecific(a: A({})*) -> {}* {
 // CHECK:STDOUT:   %I.assoc_type.76c031.3: type = assoc_entity_type @I, @I(%W) [symbolic]
 // CHECK:STDOUT:   %assoc0.203667.3: %I.assoc_type.76c031.3 = assoc_entity element0, @I.WithSelf.%I.WithSelf.F.decl [symbolic]
 // CHECK:STDOUT:   %require_complete.e360af.2: <witness> = require_complete_type %I.type.1ab3e4.3 [symbolic]
+// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %A.95c0c7.3, @I, @I(%W) [symbolic]
 // CHECK:STDOUT:   %I.impl_witness.f3f3bd.2: <witness> = impl_witness @A.as.I.impl.%I.impl_witness_table, @A.as.I.impl(%W) [symbolic]
 // CHECK:STDOUT:   %A.as.I.impl.F.type.58747b.2: type = fn_type @A.as.I.impl.F, @A.as.I.impl(%W) [symbolic]
 // CHECK:STDOUT:   %A.as.I.impl.F.afeb91.2: %A.as.I.impl.F.type.58747b.2 = struct_value () [symbolic]
 // CHECK:STDOUT:   %.0fe: require_specific_def_type = require_specific_def @A.as.I.impl(%W) [symbolic]
-// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %A.95c0c7.3, @I, @I(%W) [symbolic]
 // CHECK:STDOUT:   %I.facet.558: %I.type.1ab3e4.3 = facet_value %A.95c0c7.3, (%I.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %I.WithSelf.F.type.912: type = fn_type @I.WithSelf.F, @I.WithSelf(%W, %I.facet.558) [symbolic]
 // CHECK:STDOUT:   %.695: type = fn_type_with_self_type %I.WithSelf.F.type.912, %I.facet.558 [symbolic]
@@ -203,8 +203,8 @@ fn TestSpecific(a: A({})*) -> {}* {
 // CHECK:STDOUT:   %require_complete.loc13_16: <witness> = require_complete_type %A [symbolic = %require_complete.loc13_16 (constants.%require_complete.fd6)]
 // CHECK:STDOUT:   %require_complete.loc13_30: <witness> = require_complete_type %ptr.loc13_30.1 [symbolic = %require_complete.loc13_30 (constants.%require_complete.ef162c.1)]
 // CHECK:STDOUT:   %A.elem: type = unbound_element_type %A, %V [symbolic = %A.elem (constants.%A.elem.8a20fa.2)]
-// CHECK:STDOUT:   %.loc14_12.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%V) [symbolic = %.loc14_12.1 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc13_30.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]
+// CHECK:STDOUT:   %.loc14_12.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%V) [symbolic = %.loc14_12.1 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.loc13_30.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet.c25)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.d82)]
 // CHECK:STDOUT:   %.loc14_12.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc14_12.2 (constants.%.299)]
@@ -235,8 +235,8 @@ fn TestSpecific(a: A({})*) -> {}* {
 // CHECK:STDOUT:   %require_complete.loc21: <witness> = require_complete_type %I.type.loc21_17.2 [symbolic = %require_complete.loc21 (constants.%require_complete.e360af.2)]
 // CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I, @I(%W.loc19_16.1) [symbolic = %I.assoc_type (constants.%I.assoc_type.76c031.3)]
 // CHECK:STDOUT:   %assoc0: @TestGeneric.%I.assoc_type (%I.assoc_type.76c031.3) = assoc_entity element0, @I.WithSelf.%I.WithSelf.F.decl [symbolic = %assoc0 (constants.%assoc0.203667.3)]
-// CHECK:STDOUT:   %.loc21_11.2: require_specific_def_type = require_specific_def @A.as.I.impl(%W.loc19_16.1) [symbolic = %.loc21_11.2 (constants.%.0fe)]
 // CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %A.loc19_32.1, @I, @I(%W.loc19_16.1) [symbolic = %I.lookup_impl_witness (constants.%I.lookup_impl_witness)]
+// CHECK:STDOUT:   %.loc21_11.2: require_specific_def_type = require_specific_def @A.as.I.impl(%W.loc19_16.1) [symbolic = %.loc21_11.2 (constants.%.0fe)]
 // CHECK:STDOUT:   %I.facet: @TestGeneric.%I.type.loc21_17.2 (%I.type.1ab3e4.3) = facet_value %A.loc19_32.1, (%I.lookup_impl_witness) [symbolic = %I.facet (constants.%I.facet.558)]
 // CHECK:STDOUT:   %I.WithSelf.F.type: type = fn_type @I.WithSelf.F, @I.WithSelf(%W.loc19_16.1, %I.facet) [symbolic = %I.WithSelf.F.type (constants.%I.WithSelf.F.type.912)]
 // CHECK:STDOUT:   %.loc21_11.3: type = fn_type_with_self_type %I.WithSelf.F.type, %I.facet [symbolic = %.loc21_11.3 (constants.%.695)]
@@ -346,8 +346,8 @@ fn TestSpecific(a: A({})*) -> {}* {
 // CHECK:STDOUT:   %require_complete.loc13_16 => constants.%complete_type.0a6
 // CHECK:STDOUT:   %require_complete.loc13_30 => constants.%complete_type.38e
 // CHECK:STDOUT:   %A.elem => constants.%A.elem.599
-// CHECK:STDOUT:   %.loc14_12.1 => constants.%.07c
 // CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.impl_witness.3fd
+// CHECK:STDOUT:   %.loc14_12.1 => constants.%.07c
 // CHECK:STDOUT:   %Copy.facet => constants.%Copy.facet.111
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.514
 // CHECK:STDOUT:   %.loc14_12.2 => constants.%.237

+ 8 - 6
toolchain/check/testdata/impl/lookup/specialization_with_symbolic_rewrite.carbon

@@ -539,6 +539,7 @@ fn F[T:! Ptr](var t: T) -> T.(Ptr.Type) {
 // CHECK:STDOUT:   %assoc0.ae8: %ImplicitAs.assoc_type.ac6 = assoc_entity element0, imports.%Core.import_ref.201 [symbolic]
 // CHECK:STDOUT:   %require_complete.591: <witness> = require_complete_type %ImplicitAs.type.7e4 [symbolic]
 // CHECK:STDOUT:   %assoc0.843: %ImplicitAs.assoc_type.ff3 = assoc_entity element0, imports.%Core.import_ref.cc1 [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.lookup_impl_witness: <witness> = lookup_impl_witness %T.fe5, @ImplicitAs, @ImplicitAs(%impl.elem0.a5e) [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -756,6 +757,7 @@ fn F[T:! Ptr](var t: T) -> T.(Ptr.Type) {
 // CHECK:STDOUT:   %require_complete.loc22_23: <witness> = require_complete_type %ImplicitAs.type.loc22_23.2 [symbolic = %require_complete.loc22_23 (constants.%require_complete.591)]
 // CHECK:STDOUT:   %ImplicitAs.assoc_type: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%impl.elem0.loc22_18.2) [symbolic = %ImplicitAs.assoc_type (constants.%ImplicitAs.assoc_type.ac6)]
 // CHECK:STDOUT:   %assoc0: @F.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.ac6) = assoc_entity element0, imports.%Core.import_ref.201 [symbolic = %assoc0 (constants.%assoc0.ae8)]
+// CHECK:STDOUT:   %ImplicitAs.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc14_6.1, @ImplicitAs, @ImplicitAs(%impl.elem0.loc22_18.2) [symbolic = %ImplicitAs.lookup_impl_witness (constants.%ImplicitAs.lookup_impl_witness)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%t.param: @F.%T.binding.as_type (%T.binding.as_type)) {
 // CHECK:STDOUT:   !entry:
@@ -915,8 +917,8 @@ fn F[T:! Ptr](var t: T) -> T.(Ptr.Type) {
 // CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T.67d [symbolic]
 // CHECK:STDOUT:   %require_complete.ef1: <witness> = require_complete_type %ptr.e8f8f9.2 [symbolic]
 // CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]
-// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr.e8f8f9.2, @Copy [symbolic]
+// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.e8f8f9.2, (%Copy.lookup_impl_witness.2e6) [symbolic]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.d82: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic]
 // CHECK:STDOUT:   %.299: type = fn_type_with_self_type %Copy.WithSelf.Op.type.d82, %Copy.facet [symbolic]
@@ -1040,8 +1042,8 @@ fn F[T:! Ptr](var t: T) -> T.(Ptr.Type) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete.loc9_16: <witness> = require_complete_type %T.loc9_6.1 [symbolic = %require_complete.loc9_16 (constants.%require_complete.944)]
 // CHECK:STDOUT:   %require_complete.loc9_30: <witness> = require_complete_type %ptr [symbolic = %require_complete.loc9_30 (constants.%require_complete.ef1)]
-// CHECK:STDOUT:   %.loc10_10.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc9_6.1) [symbolic = %.loc10_10.1 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]
+// CHECK:STDOUT:   %.loc10_10.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc9_6.1) [symbolic = %.loc10_10.1 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.d82)]
 // CHECK:STDOUT:   %.loc10_10.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc10_10.2 (constants.%.299)]
@@ -1141,8 +1143,8 @@ fn F[T:! Ptr](var t: T) -> T.(Ptr.Type) {
 // CHECK:STDOUT:   %require_complete.552: <witness> = require_complete_type %T.binding.as_type.3dc [symbolic]
 // CHECK:STDOUT:   %require_complete.c1c: <witness> = require_complete_type %ptr.a86 [symbolic]
 // CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]
-// CHECK:STDOUT:   %.54b: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type.3dc) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.3c7: <witness> = lookup_impl_witness %ptr.a86, @Copy [symbolic]
+// CHECK:STDOUT:   %.54b: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type.3dc) [symbolic]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.a86, (%Copy.lookup_impl_witness.3c7) [symbolic]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.207: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic]
 // CHECK:STDOUT:   %.382: type = fn_type_with_self_type %Copy.WithSelf.Op.type.207, %Copy.facet [symbolic]
@@ -1269,8 +1271,8 @@ fn F[T:! Ptr](var t: T) -> T.(Ptr.Type) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete.loc9_15: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete.loc9_15 (constants.%require_complete.552)]
 // CHECK:STDOUT:   %require_complete.loc9_29: <witness> = require_complete_type %ptr [symbolic = %require_complete.loc9_29 (constants.%require_complete.c1c)]
-// CHECK:STDOUT:   %.loc10_10.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic = %.loc10_10.1 (constants.%.54b)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.3c7)]
+// CHECK:STDOUT:   %.loc10_10.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic = %.loc10_10.1 (constants.%.54b)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.207)]
 // CHECK:STDOUT:   %.loc10_10.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc10_10.2 (constants.%.382)]
@@ -1370,8 +1372,8 @@ fn F[T:! Ptr](var t: T) -> T.(Ptr.Type) {
 // CHECK:STDOUT:   %require_complete.552: <witness> = require_complete_type %T.binding.as_type.3dc [symbolic]
 // CHECK:STDOUT:   %require_complete.c1c: <witness> = require_complete_type %ptr.a86 [symbolic]
 // CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]
-// CHECK:STDOUT:   %.54b: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type.3dc) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.3c7: <witness> = lookup_impl_witness %ptr.a86, @Copy [symbolic]
+// CHECK:STDOUT:   %.54b: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type.3dc) [symbolic]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.a86, (%Copy.lookup_impl_witness.3c7) [symbolic]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.207: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic]
 // CHECK:STDOUT:   %.382: type = fn_type_with_self_type %Copy.WithSelf.Op.type.207, %Copy.facet [symbolic]
@@ -1497,8 +1499,8 @@ fn F[T:! Ptr](var t: T) -> T.(Ptr.Type) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete.loc9_15: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete.loc9_15 (constants.%require_complete.552)]
 // CHECK:STDOUT:   %require_complete.loc9_29: <witness> = require_complete_type %ptr [symbolic = %require_complete.loc9_29 (constants.%require_complete.c1c)]
-// CHECK:STDOUT:   %.loc10_10.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic = %.loc10_10.1 (constants.%.54b)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.3c7)]
+// CHECK:STDOUT:   %.loc10_10.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic = %.loc10_10.1 (constants.%.54b)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.207)]
 // CHECK:STDOUT:   %.loc10_10.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc10_10.2 (constants.%.382)]

+ 44 - 0
toolchain/check/testdata/impl/lookup/use_impl_from_definition.carbon

@@ -0,0 +1,44 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/lookup/use_impl_from_definition.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/lookup/use_impl_from_definition.carbon
+
+// --- construct_facet_value_inside_definition.carbon
+library "[[@TEST_NAME]]";
+
+interface I {
+  let U:! type;
+  fn F() -> U;
+}
+
+class C { adapt {}; }
+
+impl forall [T:! type] T as I where .U = C {
+  // `T as I` does an impl lookup to form a FacetValue, which must find the impl
+  // being defined and use that. The witness must be a final witness in order to
+  // know that `U` is `C`.
+  fn F() -> (T as I).U { return {} as C; }
+}
+
+// --- construct_facet_value_from_self_inside_definition.carbon
+library "[[@TEST_NAME]]";
+
+interface I {
+  let U:! type;
+  fn F() -> U;
+}
+
+class C { adapt {}; }
+
+impl forall [T:! type] T as I where .U = C {
+  // `Self as I` is a symbolic facet value specified in the interface-with-self
+  // specific, and then monomorphized with the self type of the impl.
+  fn F() -> (Self as I).U { return {} as C; }
+}

+ 31 - 0
toolchain/check/testdata/impl/name_lookup_in_impl_definition.carbon

@@ -0,0 +1,31 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/name_lookup_in_impl_definition.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/name_lookup_in_impl_definition.carbon
+
+// --- fail_todo_name_lookup_into_impl_as_target.carbon
+library "[[@TEST_NAME]]";
+
+interface I {
+  let U:! type;
+  fn F() -> U;
+}
+
+class C { adapt {}; }
+
+impl forall [T:! type] T as I where .U = C {
+  // TODO: We should do name lookup into `I` inside the body of an `impl as I`,
+  // where we would find `U`.
+  // CHECK:STDERR: fail_todo_name_lookup_into_impl_as_target.carbon:[[@LINE+4]]:13: error: name `U` not found [NameNotFound]
+  // CHECK:STDERR:   fn F() -> U { return {} as C; }
+  // CHECK:STDERR:             ^
+  // CHECK:STDERR:
+  fn F() -> U { return {} as C; }
+}

+ 2 - 2
toolchain/check/testdata/interface/as_type_of_type.carbon

@@ -44,8 +44,8 @@ fn F(T:! Empty) {
 // CHECK:STDOUT:   %require_complete.315: <witness> = require_complete_type %ptr [symbolic]
 // CHECK:STDOUT:   %pattern_type.fd9: type = pattern_type %ptr [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]
-// CHECK:STDOUT:   %.a5e: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%ptr) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness: <witness> = lookup_impl_witness %ptr, @DefaultOrUnformed [symbolic]
+// CHECK:STDOUT:   %.a5e: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%ptr) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %ptr, (%DefaultOrUnformed.lookup_impl_witness) [symbolic]
 // CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.478: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet) [symbolic]
 // CHECK:STDOUT:   %.fb3: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.478, %DefaultOrUnformed.facet [symbolic]
@@ -131,8 +131,8 @@ fn F(T:! Empty) {
 // CHECK:STDOUT:   %ptr.loc22_18.2: type = ptr_type %T.binding.as_type [symbolic = %ptr.loc22_18.2 (constants.%ptr)]
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr.loc22_18.2 [symbolic = %require_complete (constants.%require_complete.315)]
 // CHECK:STDOUT:   %pattern_type: type = pattern_type %ptr.loc22_18.2 [symbolic = %pattern_type (constants.%pattern_type.fd9)]
-// CHECK:STDOUT:   %.loc22_19.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%ptr.loc22_18.2) [symbolic = %.loc22_19.3 (constants.%.a5e)]
 // CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc22_18.2, @DefaultOrUnformed [symbolic = %DefaultOrUnformed.lookup_impl_witness (constants.%DefaultOrUnformed.lookup_impl_witness)]
+// CHECK:STDOUT:   %.loc22_19.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%ptr.loc22_18.2) [symbolic = %.loc22_19.3 (constants.%.a5e)]
 // CHECK:STDOUT:   %DefaultOrUnformed.facet.loc22_19.2: %DefaultOrUnformed.type = facet_value %ptr.loc22_18.2, (%DefaultOrUnformed.lookup_impl_witness) [symbolic = %DefaultOrUnformed.facet.loc22_19.2 (constants.%DefaultOrUnformed.facet)]
 // CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.loc22_19.2) [symbolic = %DefaultOrUnformed.WithSelf.Op.type (constants.%DefaultOrUnformed.WithSelf.Op.type.478)]
 // CHECK:STDOUT:   %.loc22_19.4: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type, %DefaultOrUnformed.facet.loc22_19.2 [symbolic = %.loc22_19.4 (constants.%.fb3)]

+ 8 - 6
toolchain/check/testdata/interface/compound_member_access.carbon

@@ -552,6 +552,7 @@ fn Works() {
 // CHECK:STDOUT:   %require_complete.57854f.2: <witness> = require_complete_type %V.binding.as_type [symbolic]
 // CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
 // CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.lookup_impl_witness: <witness> = lookup_impl_witness %V, @ImplicitAs, @ImplicitAs(%K2.type) [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -661,6 +662,7 @@ fn Works() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %V.binding.as_type [symbolic = %require_complete (constants.%require_complete.57854f.2)]
+// CHECK:STDOUT:   %ImplicitAs.lookup_impl_witness: <witness> = lookup_impl_witness %V.loc14_14.1, @ImplicitAs, @ImplicitAs(constants.%K2.type) [symbolic = %ImplicitAs.lookup_impl_witness (constants.%ImplicitAs.lookup_impl_witness)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%y.param: @Compound3.%V.binding.as_type (%V.binding.as_type)) {
 // CHECK:STDOUT:   !entry:
@@ -1082,13 +1084,13 @@ fn Works() {
 // CHECK:STDOUT:   %L2.WithSelf.S2.type.68b: type = fn_type @L2.WithSelf.S2, @L2.WithSelf(%T) [symbolic]
 // CHECK:STDOUT:   %L2.WithSelf.S2.470: %L2.WithSelf.S2.type.68b = struct_value () [symbolic]
 // CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic]
-// CHECK:STDOUT:   %L2.lookup_impl_witness: <witness> = lookup_impl_witness %T, @L2 [symbolic]
+// CHECK:STDOUT:   %L2.lookup_impl_witness.074: <witness> = lookup_impl_witness %T, @L2 [symbolic]
 // CHECK:STDOUT:   %.f8e: type = fn_type_with_self_type %L2.WithSelf.R2.type.ba3, %T [symbolic]
-// CHECK:STDOUT:   %impl.elem0: %.f8e = impl_witness_access %L2.lookup_impl_witness, element0 [symbolic]
+// CHECK:STDOUT:   %impl.elem0: %.f8e = impl_witness_access %L2.lookup_impl_witness.074, element0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.0fc: type = pattern_type %T.binding.as_type [symbolic]
 // CHECK:STDOUT:   %specific_impl_fn.b6c: <specific function> = specific_impl_function %impl.elem0, @L2.WithSelf.R2(%T) [symbolic]
 // CHECK:STDOUT:   %.b1c: type = fn_type_with_self_type %L2.WithSelf.S2.type.68b, %T [symbolic]
-// CHECK:STDOUT:   %impl.elem1: %.b1c = impl_witness_access %L2.lookup_impl_witness, element1 [symbolic]
+// CHECK:STDOUT:   %impl.elem1: %.b1c = impl_witness_access %L2.lookup_impl_witness.074, element1 [symbolic]
 // CHECK:STDOUT:   %specific_impl_fn.b67: <specific function> = specific_impl_function %impl.elem1, @L2.WithSelf.S2(%T) [symbolic]
 // CHECK:STDOUT:   %V: %L2.type = symbolic_binding V, 0 [symbolic]
 // CHECK:STDOUT:   %Compound5.type: type = fn_type @Compound5 [concrete]
@@ -1193,7 +1195,7 @@ fn Works() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc10_12.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]
-// CHECK:STDOUT:   %L2.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc10_12.1, @L2 [symbolic = %L2.lookup_impl_witness (constants.%L2.lookup_impl_witness)]
+// CHECK:STDOUT:   %L2.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc10_12.1, @L2 [symbolic = %L2.lookup_impl_witness (constants.%L2.lookup_impl_witness.074)]
 // CHECK:STDOUT:   %L2.WithSelf.R2.type: type = fn_type @L2.WithSelf.R2, @L2.WithSelf(%T.loc10_12.1) [symbolic = %L2.WithSelf.R2.type (constants.%L2.WithSelf.R2.type.ba3)]
 // CHECK:STDOUT:   %.loc18_4.2: type = fn_type_with_self_type %L2.WithSelf.R2.type, %T.loc10_12.1 [symbolic = %.loc18_4.2 (constants.%.f8e)]
 // CHECK:STDOUT:   %impl.elem0.loc18_4.2: @Simple5.%.loc18_4.2 (%.f8e) = impl_witness_access %L2.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc18_4.2 (constants.%impl.elem0)]
@@ -1209,14 +1211,14 @@ fn Works() {
 // CHECK:STDOUT:     %T.as_type.loc18: type = facet_access_type %T.ref.loc18 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]
 // CHECK:STDOUT:     %.loc18_4.1: type = converted %T.ref.loc18, %T.as_type.loc18 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]
 // CHECK:STDOUT:     %R2.ref: %L2.assoc_type = name_ref R2, @L2.WithSelf.%assoc0 [concrete = constants.%assoc0]
-// CHECK:STDOUT:     %impl.elem0.loc18_4.1: @Simple5.%.loc18_4.2 (%.f8e) = impl_witness_access constants.%L2.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc18_4.2 (constants.%impl.elem0)]
+// CHECK:STDOUT:     %impl.elem0.loc18_4.1: @Simple5.%.loc18_4.2 (%.f8e) = impl_witness_access constants.%L2.lookup_impl_witness.074, element0 [symbolic = %impl.elem0.loc18_4.2 (constants.%impl.elem0)]
 // CHECK:STDOUT:     %specific_impl_fn.loc18_4.1: <specific function> = specific_impl_function %impl.elem0.loc18_4.1, @L2.WithSelf.R2(constants.%T) [symbolic = %specific_impl_fn.loc18_4.2 (constants.%specific_impl_fn.b6c)]
 // CHECK:STDOUT:     %L2.WithSelf.R2.call: init %empty_tuple.type = call %specific_impl_fn.loc18_4.1(<error>)
 // CHECK:STDOUT:     %T.ref.loc26: %L2.type = name_ref T, %T.loc10_12.2 [symbolic = %T.loc10_12.1 (constants.%T)]
 // CHECK:STDOUT:     %T.as_type.loc26: type = facet_access_type %T.ref.loc26 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]
 // CHECK:STDOUT:     %.loc26_4.1: type = converted %T.ref.loc26, %T.as_type.loc26 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]
 // CHECK:STDOUT:     %S2.ref: %L2.assoc_type = name_ref S2, @L2.WithSelf.%assoc1 [concrete = constants.%assoc1]
-// CHECK:STDOUT:     %impl.elem1.loc26_4.1: @Simple5.%.loc26_4.2 (%.b1c) = impl_witness_access constants.%L2.lookup_impl_witness, element1 [symbolic = %impl.elem1.loc26_4.2 (constants.%impl.elem1)]
+// CHECK:STDOUT:     %impl.elem1.loc26_4.1: @Simple5.%.loc26_4.2 (%.b1c) = impl_witness_access constants.%L2.lookup_impl_witness.074, element1 [symbolic = %impl.elem1.loc26_4.2 (constants.%impl.elem1)]
 // CHECK:STDOUT:     %specific_impl_fn.loc26_4.1: <specific function> = specific_impl_function %impl.elem1.loc26_4.1, @L2.WithSelf.S2(constants.%T) [symbolic = %specific_impl_fn.loc26_4.2 (constants.%specific_impl_fn.b67)]
 // CHECK:STDOUT:     %L2.WithSelf.S2.call: init %empty_tuple.type = call %specific_impl_fn.loc26_4.1(<error>)
 // CHECK:STDOUT:     return

+ 3 - 3
toolchain/check/testdata/interface/fail_assoc_const_alias.carbon

@@ -82,8 +82,8 @@ interface C {
 // CHECK:STDOUT:   %J2.type: type = facet_type <@J2> [concrete]
 // CHECK:STDOUT:   %Self.4a7: %J2.type = symbolic_binding Self, 0 [symbolic]
 // CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self.4a7 [symbolic]
-// CHECK:STDOUT:   %.ef7: require_specific_def_type = require_specific_def @V.binding.as_type.as.I2.impl(%Self.4a7) [symbolic]
 // CHECK:STDOUT:   %I2.lookup_impl_witness.d97: <witness> = lookup_impl_witness %Self.4a7, @I2 [symbolic]
+// CHECK:STDOUT:   %.ef7: require_specific_def_type = require_specific_def @V.binding.as_type.as.I2.impl(%Self.4a7) [symbolic]
 // CHECK:STDOUT:   %I2.facet.7a5: %I2.type = facet_value %Self.binding.as_type, (%I2.lookup_impl_witness.d97) [symbolic]
 // CHECK:STDOUT:   %impl.elem0.006: type = impl_witness_access %I2.lookup_impl_witness.d97, element0 [symbolic]
 // CHECK:STDOUT:   %.805: Core.Form = init_form %impl.elem0.006 [symbolic]
@@ -135,8 +135,8 @@ interface C {
 // CHECK:STDOUT: generic fn @J2.WithSelf.F2(@J2.%Self: %J2.type) {
 // CHECK:STDOUT:   %Self: %J2.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self.4a7)]
 // CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
-// CHECK:STDOUT:   %.loc14_14.1: require_specific_def_type = require_specific_def @V.binding.as_type.as.I2.impl(%Self) [symbolic = %.loc14_14.1 (constants.%.ef7)]
 // CHECK:STDOUT:   %I2.lookup_impl_witness: <witness> = lookup_impl_witness %Self, @I2 [symbolic = %I2.lookup_impl_witness (constants.%I2.lookup_impl_witness.d97)]
+// CHECK:STDOUT:   %.loc14_14.1: require_specific_def_type = require_specific_def @V.binding.as_type.as.I2.impl(%Self) [symbolic = %.loc14_14.1 (constants.%.ef7)]
 // CHECK:STDOUT:   %I2.facet.loc14_14.1: %I2.type = facet_value %Self.binding.as_type, (%I2.lookup_impl_witness) [symbolic = %I2.facet.loc14_14.1 (constants.%I2.facet.7a5)]
 // CHECK:STDOUT:   %impl.elem0.loc14_14.1: type = impl_witness_access %I2.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc14_14.1 (constants.%impl.elem0.006)]
 // CHECK:STDOUT:   %.loc14_14.2: Core.Form = init_form %impl.elem0.loc14_14.1 [symbolic = %.loc14_14.2 (constants.%.805)]
@@ -150,8 +150,8 @@ interface C {
 // CHECK:STDOUT: specific @J2.WithSelf.F2(constants.%Self.4a7) {
 // CHECK:STDOUT:   %Self => constants.%Self.4a7
 // CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type
-// CHECK:STDOUT:   %.loc14_14.1 => constants.%.ef7
 // CHECK:STDOUT:   %I2.lookup_impl_witness => constants.%I2.lookup_impl_witness.d97
+// CHECK:STDOUT:   %.loc14_14.1 => constants.%.ef7
 // CHECK:STDOUT:   %I2.facet.loc14_14.1 => constants.%I2.facet.7a5
 // CHECK:STDOUT:   %impl.elem0.loc14_14.1 => constants.%impl.elem0.006
 // CHECK:STDOUT:   %.loc14_14.2 => constants.%.805

+ 3 - 0
toolchain/check/testdata/interface/fail_member_lookup.carbon

@@ -68,6 +68,7 @@ fn G(U:! Different) -> U.(Interface.T);
 // CHECK:STDOUT:   %pattern_type.cb4: type = pattern_type %Different.type [concrete]
 // CHECK:STDOUT:   %U: %Different.type = symbolic_binding U, 0 [symbolic]
 // CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 0, %U [symbolic]
+// CHECK:STDOUT:   %Interface.lookup_impl_witness: <witness> = lookup_impl_witness %U, @Interface [symbolic]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -167,6 +168,7 @@ fn G(U:! Different) -> U.(Interface.T);
 // CHECK:STDOUT: generic fn @G(%U.loc32_6.2: %Different.type) {
 // CHECK:STDOUT:   %U.loc32_6.1: %Different.type = symbolic_binding U, 0 [symbolic = %U.loc32_6.1 (constants.%U)]
 // CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 0, %U.loc32_6.1 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]
+// CHECK:STDOUT:   %Interface.lookup_impl_witness: <witness> = lookup_impl_witness %U.loc32_6.1, @Interface [symbolic = %Interface.lookup_impl_witness (constants.%Interface.lookup_impl_witness)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn() -> <error>;
 // CHECK:STDOUT: }
@@ -187,5 +189,6 @@ fn G(U:! Different) -> U.(Interface.T);
 // CHECK:STDOUT: specific @G(constants.%U) {
 // CHECK:STDOUT:   %U.loc32_6.1 => constants.%U
 // CHECK:STDOUT:   %U.binding.as_type => constants.%U.binding.as_type
+// CHECK:STDOUT:   %Interface.lookup_impl_witness => constants.%Interface.lookup_impl_witness
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/interface/fail_todo_define_default_fn_out_of_line.carbon

@@ -191,8 +191,8 @@ fn Interface.C.F[unused self: Self](U:! type, u: U*) -> U* { return u; }
 // CHECK:STDOUT:   %require_complete.a31: <witness> = require_complete_type %C [symbolic]
 // CHECK:STDOUT:   %require_complete.56d: <witness> = require_complete_type %ptr.18e [symbolic]
 // CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]
-// CHECK:STDOUT:   %.f1d: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%U.091) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.484: <witness> = lookup_impl_witness %ptr.18e, @Copy [symbolic]
+// CHECK:STDOUT:   %.f1d: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%U.091) [symbolic]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.18e, (%Copy.lookup_impl_witness.484) [symbolic]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.be8: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic]
 // CHECK:STDOUT:   %.e5c: type = fn_type_with_self_type %Copy.WithSelf.Op.type.be8, %Copy.facet [symbolic]
@@ -325,8 +325,8 @@ fn Interface.C.F[unused self: Self](U:! type, u: U*) -> U* { return u; }
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete.loc20_29: <witness> = require_complete_type %C [symbolic = %require_complete.loc20_29 (constants.%require_complete.a31)]
 // CHECK:STDOUT:   %require_complete.loc20_48: <witness> = require_complete_type %ptr.loc14_36.1 [symbolic = %require_complete.loc20_48 (constants.%require_complete.56d)]
-// CHECK:STDOUT:   %.loc20_69.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%U.loc14_22.1) [symbolic = %.loc20_69.1 (constants.%.f1d)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc14_36.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.484)]
+// CHECK:STDOUT:   %.loc20_69.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%U.loc14_22.1) [symbolic = %.loc20_69.1 (constants.%.f1d)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.loc14_36.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.be8)]
 // CHECK:STDOUT:   %.loc20_69.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc20_69.2 (constants.%.e5c)]

+ 2 - 0
toolchain/check/testdata/interface/generic.carbon

@@ -474,6 +474,7 @@ fn F(unused T:! Generic((), ())) {}
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %Self.b24: %Generic.type.cb7 = symbolic_binding Self, 1 [symbolic]
 // CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.3ee [symbolic]
+// CHECK:STDOUT:   %Generic.lookup_impl_witness: <witness> = lookup_impl_witness %T.3ee, @Generic, @Generic(%A) [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -565,6 +566,7 @@ fn F(unused T:! Generic((), ())) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc10_6.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]
+// CHECK:STDOUT:   %Generic.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc10_6.1, @Generic, @Generic(constants.%A) [symbolic = %Generic.lookup_impl_witness (constants.%Generic.lookup_impl_witness)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn() {
 // CHECK:STDOUT:   !entry:

+ 3 - 3
toolchain/check/testdata/interface/generic_method.carbon

@@ -144,8 +144,8 @@ fn CallIndirect() {
 // CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]
 // CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4455.1: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e93b.1: %ptr.as.Copy.impl.Op.type.2d4455.1 = struct_value () [symbolic]
-// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%U.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr.e8f8f9.1, @Copy [symbolic]
+// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%U.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.facet.c25: %Copy.type = facet_value %ptr.e8f8f9.1, (%Copy.lookup_impl_witness.2e6) [symbolic]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.d82: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.c25) [symbolic]
 // CHECK:STDOUT:   %.299: type = fn_type_with_self_type %Copy.WithSelf.Op.type.d82, %Copy.facet.c25 [symbolic]
@@ -429,8 +429,8 @@ fn CallIndirect() {
 // CHECK:STDOUT:   %require_complete.loc16_19: <witness> = require_complete_type %ptr.loc16_22.1 [symbolic = %require_complete.loc16_19 (constants.%require_complete.ef162c.1)]
 // CHECK:STDOUT:   %require_complete.loc16_37: <witness> = require_complete_type %tuple.type.loc16 [symbolic = %require_complete.loc16_37 (constants.%require_complete.034)]
 // CHECK:STDOUT:   %tuple.type.loc17: type = tuple_type (constants.%empty_struct_type, constants.%empty_struct_type, %ptr.loc16_22.1) [symbolic = %tuple.type.loc17 (constants.%tuple.type.dd2)]
-// CHECK:STDOUT:   %.loc17_21.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%U.loc16_8.1) [symbolic = %.loc17_21.1 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc16_22.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]
+// CHECK:STDOUT:   %.loc17_21.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%U.loc16_8.1) [symbolic = %.loc17_21.1 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.loc16_22.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet.c25)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.d82)]
 // CHECK:STDOUT:   %.loc17_21.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc17_21.2 (constants.%.299)]
@@ -668,8 +668,8 @@ fn CallIndirect() {
 // CHECK:STDOUT:   %require_complete.loc16_19 => constants.%complete_type.543
 // CHECK:STDOUT:   %require_complete.loc16_37 => constants.%complete_type.28e
 // CHECK:STDOUT:   %tuple.type.loc17 => constants.%tuple.type.0dd
-// CHECK:STDOUT:   %.loc17_21.1 => constants.%.157
 // CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.impl_witness.425
+// CHECK:STDOUT:   %.loc17_21.1 => constants.%.157
 // CHECK:STDOUT:   %Copy.facet => constants.%Copy.facet.26e
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.a8b
 // CHECK:STDOUT:   %.loc17_21.2 => constants.%.2ef

+ 2 - 2
toolchain/check/testdata/interface/member_lookup.carbon

@@ -80,8 +80,8 @@ fn AccessMissingConcrete(I:! Interface(i32)) -> i32 {
 // CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]
 // CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]
-// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr.e8f, @Copy [symbolic]
+// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]
 // CHECK:STDOUT:   %Copy.facet.c25: %Copy.type = facet_value %ptr.e8f, (%Copy.lookup_impl_witness.2e6) [symbolic]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type.d82: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.c25) [symbolic]
 // CHECK:STDOUT:   %.299: type = fn_type_with_self_type %Copy.WithSelf.Op.type.d82, %Copy.facet.c25 [symbolic]
@@ -236,8 +236,8 @@ fn AccessMissingConcrete(I:! Interface(i32)) -> i32 {
 // CHECK:STDOUT:   %assoc0: @AccessGeneric.%Interface.assoc_type (%Interface.assoc_type.5a2) = assoc_entity element0, @Interface.WithSelf.%X [symbolic = %assoc0 (constants.%assoc0.b59)]
 // CHECK:STDOUT:   %Interface.lookup_impl_witness: <witness> = lookup_impl_witness %I.loc8_28.1, @Interface, @Interface(%T.loc8_18.1) [symbolic = %Interface.lookup_impl_witness (constants.%Interface.lookup_impl_witness.9f1)]
 // CHECK:STDOUT:   %impl.elem0.loc9_11.3: @AccessGeneric.%ptr.loc8_50.1 (%ptr.e8f) = impl_witness_access %Interface.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc9_11.3 (constants.%impl.elem0.117)]
-// CHECK:STDOUT:   %.loc9_11.3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc8_18.1) [symbolic = %.loc9_11.3 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc8_50.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]
+// CHECK:STDOUT:   %.loc9_11.3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc8_18.1) [symbolic = %.loc9_11.3 (constants.%.2f2)]
 // CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.loc8_50.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet.c25)]
 // CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.d82)]
 // CHECK:STDOUT:   %.loc9_11.4: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc9_11.4 (constants.%.299)]

+ 5 - 5
toolchain/check/testdata/named_constraint/empty_generic.carbon

@@ -53,7 +53,6 @@ fn G(T:! Z, U:! Empty(T), V:! type) {
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
 // CHECK:STDOUT:   %empty_struct.a40: %empty_struct_type = struct_value () [concrete]
-// CHECK:STDOUT:   %Self.31c17c.2: %Empty.type.d682d6.2 = symbolic_binding Self, 1 [symbolic]
 // CHECK:STDOUT:   %empty_struct.type.facet: %type = facet_value %empty_struct_type, () [concrete]
 // CHECK:STDOUT:   %Empty.facet.76f: %Empty.type.d682d6.2 = facet_value %empty_struct_type, () [symbolic]
 // CHECK:STDOUT:   %F.specific_fn.5f9: <specific function> = specific_function %F, @F(%T.binding.as_type, %Empty.facet.76f) [symbolic]
@@ -62,6 +61,7 @@ fn G(T:! Z, U:! Empty(T), V:! type) {
 // CHECK:STDOUT:   %F.specific_fn.ff8: <specific function> = specific_function %F, @F(%T.binding.as_type, %Empty.facet.2cb) [symbolic]
 // CHECK:STDOUT:   %Empty.facet.4f8: %Empty.type.d682d6.2 = facet_value %T.binding.as_type, () [symbolic]
 // CHECK:STDOUT:   %F.specific_fn.55f: <specific function> = specific_function %F, @F(%T.binding.as_type, %Empty.facet.4f8) [symbolic]
+// CHECK:STDOUT:   %Self.31c17c.2: %Empty.type.d682d6.2 = symbolic_binding Self, 1 [symbolic]
 // CHECK:STDOUT:   %F.specific_fn.5c5: <specific function> = specific_function %F, @F(%T.binding.as_type, %U.e1f642.2) [symbolic]
 // CHECK:STDOUT:   %facet_value.ed5: %type = facet_value %V, () [symbolic]
 // CHECK:STDOUT:   %Empty.facet.ed5: %Empty.type.d682d6.2 = facet_value %V, () [symbolic]
@@ -255,10 +255,6 @@ fn G(T:! Z, U:! Empty(T), V:! type) {
 // CHECK:STDOUT:   %V.loc20_27.1 => constants.%V
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @Empty.WithSelf(constants.%T.binding.as_type, constants.%Self.31c17c.1) {
-// CHECK:STDOUT: !definition:
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
 // CHECK:STDOUT: specific @Empty.WithSelf(constants.%T.binding.as_type, constants.%empty_struct.type.facet) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT: }
@@ -298,6 +294,10 @@ fn G(T:! Z, U:! Empty(T), V:! type) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: specific @Empty.WithSelf(constants.%T.binding.as_type, constants.%Self.31c17c.1) {
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
 // CHECK:STDOUT: specific @F(constants.%T.binding.as_type, constants.%U.e1f642.2) {
 // CHECK:STDOUT:   %T.loc18_6.1 => constants.%T.binding.as_type
 // CHECK:STDOUT:   %Empty.type.loc18_34.1 => constants.%Empty.type.d682d6.2

+ 87 - 26
toolchain/check/testdata/named_constraint/incomplete.carbon

@@ -2,7 +2,7 @@
 // Exceptions. See /LICENSE for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
-// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon
 //
 // AUTOUPDATE
 // TIP: To test this file alone, run:
@@ -15,19 +15,10 @@ library "[[@TEST_NAME]]";
 
 interface Z {}
 
+// An incomplete constraint is a valid type for a symbolic facet, and is just
+// not able to provide any witness for an impl lookup on that facet.
 constraint N;
 fn F(T:! N) {
-  // TODO: The failed-to-identify error should be a note under the convert error
-  // instead of being a separate error. This can be done by making a top-level
-  // convert error as a Context for specific errors that happen during convert.
-  //
-  // CHECK:STDERR: fail_incomplete_constraint_in_impl_lookup.carbon:[[@LINE+11]]:3: error: facet type of value `T` can not be identified [ImplLookupInUnidentifiedFacetTypeOfQuerySelf]
-  // CHECK:STDERR:   T as Z;
-  // CHECK:STDERR:   ^~~~~~
-  // CHECK:STDERR: fail_incomplete_constraint_in_impl_lookup.carbon:[[@LINE-9]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
-  // CHECK:STDERR: constraint N;
-  // CHECK:STDERR: ^~~~~~~~~~~~~
-  // CHECK:STDERR:
   // CHECK:STDERR: fail_incomplete_constraint_in_impl_lookup.carbon:[[@LINE+4]]:3: error: cannot convert type `T` that implements `N` into type implementing `Z` [ConversionFailureFacetToFacet]
   // CHECK:STDERR:   T as Z;
   // CHECK:STDERR:   ^~~~~~
@@ -35,33 +26,103 @@ fn F(T:! N) {
   T as Z;
 }
 
-// --- fail_todo_does_not_diagnose_identify_failure_in_deduce.carbon
+// --- fail_does_not_diagnose_identify_failure_in_deduce.carbon
 library "[[@TEST_NAME]]";
 
 constraint N;
 
 interface Z {}
-// Since N is an incomplete constraint, it can not be identified for impl lookup
-// to determine if C implements N.
+// Since N is an incomplete constraint, it can not be identified as a target for
+// impl lookup to determine if C implements N. No diagnostic is attached to the
+// impl when the lookup fails, we simply fail to convert.
 impl forall [T:! N] T as Z {}
 
 class C;
 
 fn F() {
-  // TODO: The "can not be identified" diagnostic should not occur here. That
-  // diagnostic happened during deduction, which means to suppress diagnostics.
-  // Only the convert error should be emitted.
-  //
-  // CHECK:STDERR: fail_todo_does_not_diagnose_identify_failure_in_deduce.carbon:[[@LINE+11]]:3: error: facet type `N` can not be identified [ImplLookupInUnidentifiedFacetType]
+  // CHECK:STDERR: fail_does_not_diagnose_identify_failure_in_deduce.carbon:[[@LINE+4]]:3: error: cannot convert type `C` into type implementing `Z` [ConversionFailureTypeToFacet]
   // CHECK:STDERR:   C as Z;
   // CHECK:STDERR:   ^~~~~~
-  // CHECK:STDERR: fail_todo_does_not_diagnose_identify_failure_in_deduce.carbon:[[@LINE-17]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
-  // CHECK:STDERR: constraint N;
+  // CHECK:STDERR:
+  C as Z;
+}
+
+// --- constraint_completed_after_deducing_impl_refers_to_it.carbon
+library "[[@TEST_NAME]]";
+
+constraint N;
+
+interface Z {}
+// N is incomplete here, but that's okay. We don't need it to be identified
+// until a lookup tries to use this impl.
+impl forall [T:! N] T as Z {}
+
+class C;
+
+// N is now identified, so it can be the target of a convertion, such as for
+// deducing `T` in the impl above.
+constraint N {}
+
+fn F() {
+  C as Z;
+}
+
+// --- fail_impl_lookup_target_not_identified.carbon
+library "[[@TEST_NAME]]";
+
+constraint Z;
+
+fn AsZ(unused T:! Z) {}
+
+fn F() {
+  // Converting to facet type `Z` requires `Z` to be identified.
+  // CHECK:STDERR: fail_impl_lookup_target_not_identified.carbon:[[@LINE+10]]:3: error: facet type `Z` can not be identified [ImplLookupInUnidentifiedFacetType]
+  // CHECK:STDERR:   AsZ(());
+  // CHECK:STDERR:   ^~~~~~~
+  // CHECK:STDERR: fail_impl_lookup_target_not_identified.carbon:[[@LINE-9]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
+  // CHECK:STDERR: constraint Z;
   // CHECK:STDERR: ^~~~~~~~~~~~~
+  // CHECK:STDERR: fail_impl_lookup_target_not_identified.carbon:[[@LINE-10]]:15: note: initializing generic parameter `T` declared here [InitializingGenericParam]
+  // CHECK:STDERR: fn AsZ(unused T:! Z) {}
+  // CHECK:STDERR:               ^
   // CHECK:STDERR:
-  // CHECK:STDERR: fail_todo_does_not_diagnose_identify_failure_in_deduce.carbon:[[@LINE+4]]:3: error: cannot convert type `C` into type implementing `Z` [ConversionFailureTypeToFacet]
-  // CHECK:STDERR:   C as Z;
-  // CHECK:STDERR:   ^~~~~~
+  AsZ(());
+}
+
+// --- fail_incomplete_self.carbon
+library "[[@TEST_NAME]]";
+
+// Returning a facet of type `W` requires `W` to be complete, but it's currently
+// being defined where this is called. This causes an error diagnostic at the
+// call.
+//
+// TODO: Define the function to `return U` once we can write `T:! Core.Copy`.
+// Right now, due to #5750, facets are not seen to implement `Core.Copy`.
+eval fn ReturnFacet[T:! type](U:! T) -> T;
+
+interface Y { let YT:! type; }
+
+interface Z {}
+
+interface X { let XZ:! Z; }
+constraint W {
+  require impls Z;
+  // CHECK:STDERR: fail_incomplete_self.carbon:[[@LINE+17]]:31: error: function returns incomplete type `W` [IncompleteTypeInFunctionReturnType]
+  // CHECK:STDERR:   require impls X where .XZ = ReturnFacet(Self);
+  // CHECK:STDERR:                               ^~~~~~~~~~~~~~~~~
+  // CHECK:STDERR: fail_incomplete_self.carbon:[[@LINE-5]]:1: note: constraint is currently being defined [NamedConstraintIncompleteWithinDefinition]
+  // CHECK:STDERR: constraint W {
+  // CHECK:STDERR: ^~~~~~~~~~~~~~
+  // CHECK:STDERR: fail_incomplete_self.carbon:[[@LINE-15]]:41: note: return type declared here [IncompleteReturnTypeHere]
+  // CHECK:STDERR: eval fn ReturnFacet[T:! type](U:! T) -> T;
+  // CHECK:STDERR:                                         ^
   // CHECK:STDERR:
-  C as Z;
+  // CHECK:STDERR: fail_incomplete_self.carbon:[[@LINE+7]]:31: error: use of undefined generic function [MissingGenericFunctionDefinition]
+  // CHECK:STDERR:   require impls X where .XZ = ReturnFacet(Self);
+  // CHECK:STDERR:                               ^~~~~~~~~~~
+  // CHECK:STDERR: fail_incomplete_self.carbon:[[@LINE-22]]:1: note: generic function declared here [MissingGenericFunctionDefinitionHere]
+  // CHECK:STDERR: eval fn ReturnFacet[T:! type](U:! T) -> T;
+  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  // CHECK:STDERR:
+  require impls X where .XZ = ReturnFacet(Self);
 }

+ 85 - 36
toolchain/check/type_completion.cpp

@@ -19,6 +19,7 @@
 #include "toolchain/sem_ir/facet_type_info.h"
 #include "toolchain/sem_ir/generic.h"
 #include "toolchain/sem_ir/ids.h"
+#include "toolchain/sem_ir/named_constraint.h"
 #include "toolchain/sem_ir/specific_interface.h"
 #include "toolchain/sem_ir/specific_named_constraint.h"
 #include "toolchain/sem_ir/type_info.h"
@@ -855,17 +856,6 @@ auto RequireConcreteType(Context& context, SemIR::TypeId type_id,
   return false;
 }
 
-// Require all named constraints in the facet type are identified. For a named
-// constraint, this means the constraint definition is complete.
-static auto RequireCompleteNamedConstraint(
-    Context& context, SemIR::LocId loc_id,
-    SemIR::NamedConstraintId constraint_id, SemIR::SpecificId specific_id,
-    bool diagnose) -> bool {
-  auto facet_type =
-      FacetTypeFromNamedConstraint(context, constraint_id, specific_id);
-  return RequireCompleteFacetType(context, loc_id, facet_type, diagnose);
-}
-
 // Given a canonical facet value, or a type value, return a facet value.
 static auto GetSelfFacetValue(Context& context, SemIR::ConstantId self_const_id)
     -> SemIR::ConstantId {
@@ -885,14 +875,18 @@ static auto GetSelfFacetValue(Context& context, SemIR::ConstantId self_const_id)
       context, context.types().GetAsTypeInstId(self_inst_id));
 }
 
-auto RequireIdentifiedFacetType(Context& context, SemIR::LocId loc_id,
-                                SemIR::ConstantId self_const_id,
-                                const SemIR::FacetType& facet_type,
-                                DiagnosticContextFn diagnostic_context)
+static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
+                              SemIR::ConstantId self_const_id,
+                              const SemIR::FacetType& facet_type,
+                              bool allow_partially_identified, bool diagnose)
     -> SemIR::IdentifiedFacetTypeId {
-  CARBON_CHECK(diagnostic_context);
-  Diagnostics::ContextScope scope(&context.emitter(), diagnostic_context);
-
+  // While partially identified facet types end up in the store of
+  // IdentifiedFacetTypes, we don't try to construct a key to look for them
+  // here, so we will only early-out here for fully identified facet types. To
+  // construct the key for a partially identified facet type we need to know the
+  // set of required impls that it contains, which requires us to do most of the
+  // work of identifying the facet type (though we could skip the mapping of
+  // constant values into specifics).
   auto key =
       SemIR::IdentifiedFacetTypeKey{.facet_type_id = facet_type.facet_type_id,
                                     .self_const_id = self_const_id};
@@ -912,6 +906,7 @@ auto RequireIdentifiedFacetType(Context& context, SemIR::LocId loc_id,
       {true, self_const_id, facet_type.facet_type_id}};
 
   // Outputs for the IdentifiedFacetType.
+  bool partially_identified = false;
   llvm::SmallVector<SemIR::IdentifiedFacetType::RequiredImpl> extends;
   llvm::SmallVector<SemIR::IdentifiedFacetType::RequiredImpl> impls;
 
@@ -945,19 +940,6 @@ auto RequireIdentifiedFacetType(Context& context, SemIR::LocId loc_id,
       continue;
     }
 
-    // References to a named constraint require the constraint to be complete so
-    // that we can enumerate all the required interfaces within.
-    for (auto specific_constraint :
-         llvm::concat<const SemIR::SpecificNamedConstraint>(
-             facet_type_info.extend_named_constraints,
-             facet_type_info.self_impls_named_constraints)) {
-      if (!RequireCompleteNamedConstraint(
-              context, loc_id, specific_constraint.named_constraint_id,
-              specific_constraint.specific_id, true)) {
-        return SemIR::IdentifiedFacetTypeId::None;
-      }
-    }
-
     // The self may have type TypeType. But the `Self` in a generic require decl
     // has type FacetType, so we need something similar to replace it in the
     // specific.
@@ -966,12 +948,35 @@ auto RequireIdentifiedFacetType(Context& context, SemIR::LocId loc_id,
     for (auto extends : facet_type_info.extend_named_constraints) {
       const auto& constraint =
           context.named_constraints().Get(extends.named_constraint_id);
+
+      llvm::ArrayRef<SemIR::RequireImplsId> require_impls_ids;
+      if (constraint.is_complete()) {
+        require_impls_ids = context.require_impls_blocks().Get(
+            constraint.require_impls_block_id);
+      } else if (allow_partially_identified) {
+        partially_identified = true;
+        if (constraint.is_being_defined()) {
+          require_impls_ids = context.require_impls_stack().PeekForScope(
+              extends.named_constraint_id);
+        } else {
+          continue;
+        }
+      } else {
+        if (diagnose) {
+          DiagnoseIncompleteNamedConstraint(context,
+                                            extends.named_constraint_id);
+        }
+        return SemIR::IdentifiedFacetTypeId::None;
+      }
+
       auto constraint_with_self_specific_id = MakeSpecificWithInnerSelf(
           context, loc_id, constraint.generic_id,
           constraint.generic_with_self_id, extends.specific_id, self_facet);
+      if (SpecificContainsError(context, constraint_with_self_specific_id)) {
+        return SemIR::IdentifiedFacetTypeId::None;
+      }
 
-      for (auto require_impls_id : context.require_impls_blocks().Get(
-               constraint.require_impls_block_id)) {
+      for (auto require_impls_id : llvm::reverse(require_impls_ids)) {
         const auto& require = context.require_impls().Get(require_impls_id);
 
         // Each require is in its own generic, with no additional bindings and
@@ -1003,12 +1008,34 @@ auto RequireIdentifiedFacetType(Context& context, SemIR::LocId loc_id,
     for (auto impls : facet_type_info.self_impls_named_constraints) {
       const auto& constraint =
           context.named_constraints().Get(impls.named_constraint_id);
+
+      llvm::ArrayRef<SemIR::RequireImplsId> require_impls_ids;
+      if (constraint.is_complete()) {
+        require_impls_ids = context.require_impls_blocks().Get(
+            constraint.require_impls_block_id);
+      } else if (allow_partially_identified) {
+        partially_identified = true;
+        if (constraint.is_being_defined()) {
+          require_impls_ids = context.require_impls_stack().PeekForScope(
+              impls.named_constraint_id);
+        } else {
+          continue;
+        }
+      } else {
+        if (diagnose) {
+          DiagnoseIncompleteNamedConstraint(context, impls.named_constraint_id);
+        }
+        return SemIR::IdentifiedFacetTypeId::None;
+      }
+
       auto constraint_with_self_specific_id = MakeSpecificWithInnerSelf(
           context, loc_id, constraint.generic_id,
           constraint.generic_with_self_id, impls.specific_id, self_facet);
+      if (SpecificContainsError(context, constraint_with_self_specific_id)) {
+        return SemIR::IdentifiedFacetTypeId::None;
+      }
 
-      for (auto require_impls_id : context.require_impls_blocks().Get(
-               constraint.require_impls_block_id)) {
+      for (auto require_impls_id : llvm::reverse(require_impls_ids)) {
         const auto& require = context.require_impls().Get(require_impls_id);
 
         // Each require is in its own generic, with no additional bindings and
@@ -1038,7 +1065,29 @@ auto RequireIdentifiedFacetType(Context& context, SemIR::LocId loc_id,
   }
 
   // TODO: Process other kinds of requirements.
-  return context.identified_facet_types().Add({key, extends, impls});
+  return context.identified_facet_types().Add(
+      {key, partially_identified, extends, impls});
+}
+
+auto TryToIdentifyFacetType(Context& context, SemIR::LocId loc_id,
+                            SemIR::ConstantId self_const_id,
+                            const SemIR::FacetType& facet_type,
+                            bool allow_partially_identified)
+    -> SemIR::IdentifiedFacetTypeId {
+  return IdentifyFacetType(context, loc_id, self_const_id, facet_type,
+                           allow_partially_identified, /*diagnose=*/false);
+}
+
+auto RequireIdentifiedFacetType(Context& context, SemIR::LocId loc_id,
+                                SemIR::ConstantId self_const_id,
+                                const SemIR::FacetType& facet_type,
+                                DiagnosticContextFn diagnostic_context,
+                                bool diagnose) -> SemIR::IdentifiedFacetTypeId {
+  CARBON_CHECK(diagnostic_context);
+  Diagnostics::ContextScope scope(&context.emitter(), diagnostic_context);
+
+  return IdentifyFacetType(context, loc_id, self_const_id, facet_type,
+                           /*allow_partially_identified=*/false, diagnose);
 }
 
 }  // namespace Carbon::Check

+ 16 - 1
toolchain/check/type_completion.h

@@ -69,6 +69,18 @@ auto RequireConcreteType(Context& context, SemIR::TypeId type_id,
                          DiagnosticContextFn concrete_type_diagnostic_context)
     -> bool;
 
+// Performs `RequireIdentifiedFacetType`, but it is not an error if the facet
+// type is not identified.
+//
+// If `allow_partially_identified` is true, the facet type may be partially
+// identified, which can contain interfaces from a named constraint that is in
+// the middle of being defined.
+auto TryToIdentifyFacetType(Context& context, SemIR::LocId loc_id,
+                            SemIR::ConstantId self_const_id,
+                            const SemIR::FacetType& facet_type,
+                            bool allow_partially_identified)
+    -> SemIR::IdentifiedFacetTypeId;
+
 // Requires the named constraints in the facet type to be complete, so that the
 // set of interfaces the facet type requires is known. The `self_const_id` is a
 // type or facet type expression that is the self that the FacetType is
@@ -81,10 +93,13 @@ auto RequireConcreteType(Context& context, SemIR::TypeId type_id,
 // resulting IdentifiedFacetType. Comparing the `self_const_id` against the
 // output self values requires the caller to also canonicalize the
 // `self_const_id`.
+//
+// TODO: Remove `diagnose` and split into `TryIdentifyFacetType`.
 auto RequireIdentifiedFacetType(Context& context, SemIR::LocId loc_id,
                                 SemIR::ConstantId self_const_id,
                                 const SemIR::FacetType& facet_type,
-                                DiagnosticContextFn diagnostic_context)
+                                DiagnosticContextFn diagnostic_context,
+                                bool diagnose = true)
     -> SemIR::IdentifiedFacetTypeId;
 
 // Emits an error diagnostic explaining that a class is incomplete.

+ 0 - 1
toolchain/diagnostics/kind.def

@@ -372,7 +372,6 @@ CARBON_DIAGNOSTIC_KIND(MissingImplInMemberAccessInContext)
 CARBON_DIAGNOSTIC_KIND(ImplLookupCycle)
 CARBON_DIAGNOSTIC_KIND(ImplLookupCycleNote)
 CARBON_DIAGNOSTIC_KIND(ImplLookupInUnidentifiedFacetType)
-CARBON_DIAGNOSTIC_KIND(ImplLookupInUnidentifiedFacetTypeOfQuerySelf)
 
 // Require checking.
 CARBON_DIAGNOSTIC_KIND(RequireImplsExtendWithExplicitSelf)

+ 5 - 5
toolchain/lower/testdata/impl/import_facet.carbon

@@ -85,7 +85,7 @@ fn F(d: D(i32)) -> i32* {
 // CHECK:STDOUT: ; ModuleID = 'd.carbon'
 // CHECK:STDOUT: source_filename = "d.carbon"
 // CHECK:STDOUT:
-// CHECK:STDOUT: @C.val.7d8.anon = internal constant {} zeroinitializer
+// CHECK:STDOUT: @C.val.23a.anon = internal constant {} zeroinitializer
 // CHECK:STDOUT:
 // CHECK:STDOUT: ; Function Attrs: nounwind
 // CHECK:STDOUT: define ptr @_CF.Main(ptr %d) #0 !dbg !4 {
@@ -93,7 +93,7 @@ fn F(d: D(i32)) -> i32* {
 // CHECK:STDOUT:   %.loc5_21.1.temp = alloca {}, align 8, !dbg !10
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc5_21.1.temp), !dbg !10
 // CHECK:STDOUT:   call void @"_CGetI.D.eb057aa32837c84e.Main:I.Main.b88d1103f417c6d4"(ptr %.loc5_21.1.temp, ptr %d), !dbg !10
-// CHECK:STDOUT:   %C.GetC.call = call ptr @_CGetC.C.Main.65ad70c00874dfd2(ptr %.loc5_21.1.temp), !dbg !10
+// CHECK:STDOUT:   %C.GetC.call = call ptr @_CGetC.C.Main.541f3e0ecf5901d3(ptr %.loc5_21.1.temp), !dbg !10
 // CHECK:STDOUT:   ret ptr %C.GetC.call, !dbg !11
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -102,12 +102,12 @@ fn F(d: D(i32)) -> i32* {
 // CHECK:STDOUT:
 // CHECK:STDOUT: ; Function Attrs: nounwind
 // CHECK:STDOUT: define linkonce_odr void @"_CGetI.D.eb057aa32837c84e.Main:I.Main.b88d1103f417c6d4"(ptr sret({}) %return, ptr %self) #0 !dbg !12 {
-// CHECK:STDOUT:   call void @llvm.memcpy.p0.p0.i64(ptr align 1 %return, ptr align 1 @C.val.7d8.anon, i64 0, i1 false), !dbg !16
+// CHECK:STDOUT:   call void @llvm.memcpy.p0.p0.i64(ptr align 1 %return, ptr align 1 @C.val.23a.anon, i64 0, i1 false), !dbg !16
 // CHECK:STDOUT:   ret void, !dbg !16
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: ; Function Attrs: nounwind
-// CHECK:STDOUT: define linkonce_odr ptr @_CGetC.C.Main.65ad70c00874dfd2(ptr %self) #0 !dbg !17 {
+// CHECK:STDOUT: define linkonce_odr ptr @_CGetC.C.Main.541f3e0ecf5901d3(ptr %self) #0 !dbg !17 {
 // CHECK:STDOUT:   %1 = alloca ptr, align 8, !dbg !21
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %1), !dbg !21
 // CHECK:STDOUT:   store ptr poison, ptr %1, align 8, !dbg !21
@@ -142,7 +142,7 @@ fn F(d: D(i32)) -> i32* {
 // CHECK:STDOUT: !14 = !{!15}
 // CHECK:STDOUT: !15 = !DILocalVariable(arg: 1, scope: !12, type: !7)
 // CHECK:STDOUT: !16 = !DILocation(line: 7, column: 7, scope: !12)
-// CHECK:STDOUT: !17 = distinct !DISubprogram(name: "GetC", linkageName: "_CGetC.C.Main.65ad70c00874dfd2", scope: null, file: !18, line: 4, type: !5, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !19)
+// CHECK:STDOUT: !17 = distinct !DISubprogram(name: "GetC", linkageName: "_CGetC.C.Main.541f3e0ecf5901d3", scope: null, file: !18, line: 4, type: !5, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !19)
 // CHECK:STDOUT: !18 = !DIFile(filename: "a.carbon", directory: "")
 // CHECK:STDOUT: !19 = !{!20}
 // CHECK:STDOUT: !20 = !DILocalVariable(arg: 1, scope: !17, type: !7)

+ 10 - 1
toolchain/sem_ir/facet_type_info.cpp

@@ -212,7 +212,8 @@ auto FacetTypeInfo::Print(llvm::raw_ostream& out) const -> void {
 }
 
 IdentifiedFacetType::IdentifiedFacetType(
-    IdentifiedFacetTypeKey key, llvm::ArrayRef<RequiredImpl> extends,
+    IdentifiedFacetTypeKey key, bool partially_identified,
+    llvm::ArrayRef<RequiredImpl> extends,
     llvm::ArrayRef<RequiredImpl> self_impls)
     : key_(key) {
   required_impls_.reserve(extends.size() + self_impls.size());
@@ -231,6 +232,14 @@ IdentifiedFacetType::IdentifiedFacetType(
 
   llvm::append_range(required_impls_, self_impls);
   SortAndDeduplicate(required_impls_, RequiredLess);
+
+  if (partially_identified) {
+    // This marks the IdentifiedFacetType as being partially identified, and
+    // prevents the key from colliding with a fully identified facet type, or
+    // with other partially (but differently) identified facet types, with the
+    // same constituents but a more complete set of required interfaces.
+    key_.num_require_impls = required_impls_.size();
+  }
 }
 
 auto AddCanonicalWitnessesBlock(File& sem_ir,

+ 10 - 1
toolchain/sem_ir/facet_type_info.h

@@ -128,6 +128,11 @@ using FacetTypeInfoStore =
 struct IdentifiedFacetTypeKey {
   FacetTypeId facet_type_id;
   ConstantId self_const_id;
+  // Inside a named constraint, each identification of the `Self` facet type can
+  // be unique, as it can be modified by each require declaration seen so far.
+  // Uses -1 for identifying a facet type with a self-type from outside the
+  // definition of an named constraint.
+  int32_t num_require_impls = -1;
 
   friend auto operator==(const IdentifiedFacetTypeKey& lhs,
                          const IdentifiedFacetTypeKey& rhs) -> bool = default;
@@ -143,7 +148,7 @@ struct IdentifiedFacetType {
         -> bool = default;
   };
 
-  IdentifiedFacetType(IdentifiedFacetTypeKey key,
+  IdentifiedFacetType(IdentifiedFacetTypeKey key, bool partially_identified,
                       llvm::ArrayRef<RequiredImpl> extends,
                       llvm::ArrayRef<RequiredImpl> self_impls);
 
@@ -175,6 +180,10 @@ struct IdentifiedFacetType {
     }
   }
 
+  auto partially_identified() const -> bool {
+    return key_.num_require_impls >= 0;
+  }
+
   auto GetAsKey() const -> IdentifiedFacetTypeKey { return key_; }
 
  private:

+ 5 - 10
toolchain/sem_ir/typed_insts.h

@@ -1189,21 +1189,16 @@ struct IntValue {
   IntId int_id;
 };
 
-// A symbolic instruction that takes the place of an `ImplWitness` when the
-// result is not fully known. When evaluated it does an impl lookup query, based
-// on the stored query arguments, that a type implements an interface. The query
-// can be symbolic, and thus modified to be more concrete by applying a
-// specific. Once the query is concrete enough, or a final impl is found, the
-// instruction evaluates to an `ImplWitness`.
+// A non-final witness representing an impl lookup that did not yet find a final
+// witness.
 //
-// This instruction also represents a promise that an impl lookup query was
-// satisfied, like `ImplWitness`, but without providing which impl declaration
-// satisfies it.
+// When a final impl becomes available, or once the query and specific interface
+// are monomorphized to be concrete, this evaluates to that final witness.
 struct LookupImplWitness {
   static constexpr auto Kind =
       InstKind::LookupImplWitness.Define<Parse::NodeId>(
           {.ir_name = "lookup_impl_witness",
-           .constant_kind = InstConstantKind::SymbolicOnly,
+           .constant_kind = InstConstantKind::Conditional,
            .constant_needs_inst_id =
                InstConstantNeedsInstIdKind::DuringEvaluation,
            .is_lowered = false});