Browse Source

Properly diagnose ambiguous `.Self` in `T impls X where...` (#7132)

A `where` expression nested inside a `T impls X` constraint makes
`.Self` ambiguous on the right-hand side of the `where` if `T` is
anything other than `.Self`. After the `where`, the value of a `.Self`
could be `T` or could be the value of `.Self` before the `impls`
constraint: the so-called top-level value of `.Self`.

Implicit use of `.Self` in designators is always allowed, and they are
bound (and replaced by a reference) to the inner-most possible value of
`.Self`. On the right-hand side of the nested `where` above, they have
the value `T as X`.

`.Self impls ...` is also always allowed, since it acts more as a
keyword here, and it always refers to the inner-most possible value of
`.Self`.

Any other explicit use of `.Self` is diagnosed when ambiguous, in any
kind of constraint. This is done in the handling of `WhereExpr` since it
has enough context to allow `.Self impls` (which is an explicit use)
while disallowing other explicit uses. And because it has non-canonical
instructions to work with, so it is able to diagnose errors with precise
locations.

Since `.Self` is no longer going to be marked with depth modifiers, the
eval of `WhereExpr` does not need an input facet value instruction
representing `.Self` to compare with, as they are now going to all be
equivalent. So revert it back to just looking for the `PeriodSelf` name
id, through a shared helper being introduced as `IsPeriodSelf`. And drop
the period self InstId from the `WhereExpr` instruction. This causes
most of the formatted SemIR changes.

Move helpers for working with and replacing `.Self` to their own file,
out of the `facet_type.h` header/cpp files. These are working with
`.Self` facet values more than facet types, though `.Self` is a name
that only exists inside the scope of a facet type.
Dana Jansens 1 ngày trước cách đây
mục cha
commit
46bb0fecd4
46 tập tin đã thay đổi với 1008 bổ sung678 xóa
  1. 2 0
      toolchain/check/BUILD
  2. 11 56
      toolchain/check/eval.cpp
  3. 1 0
      toolchain/check/eval_inst.cpp
  4. 0 264
      toolchain/check/facet_type.cpp
  5. 0 61
      toolchain/check/facet_type.h
  6. 1 0
      toolchain/check/handle_binding_pattern.cpp
  7. 1 1
      toolchain/check/handle_require.cpp
  8. 19 17
      toolchain/check/handle_where.cpp
  9. 1 0
      toolchain/check/impl.cpp
  10. 1 1
      toolchain/check/impl_lookup.cpp
  11. 1 1
      toolchain/check/node_stack.h
  12. 609 0
      toolchain/check/period_self.cpp
  13. 95 0
      toolchain/check/period_self.h
  14. 2 2
      toolchain/check/testdata/deduce/binding_pattern.carbon
  15. 6 6
      toolchain/check/testdata/facet/access.carbon
  16. 10 10
      toolchain/check/testdata/facet/convert_facet_value_to_narrowed_facet_type.carbon
  17. 2 2
      toolchain/check/testdata/facet/facet_assoc_const.carbon
  18. 19 28
      toolchain/check/testdata/facet/period_self.carbon
  19. 2 2
      toolchain/check/testdata/facet/self_in_interface_param.carbon
  20. 2 2
      toolchain/check/testdata/for/actual.carbon
  21. 4 4
      toolchain/check/testdata/generic/dot_self_symbolic_type.carbon
  22. 12 12
      toolchain/check/testdata/impl/assoc_const_self.carbon
  23. 4 4
      toolchain/check/testdata/impl/fail_impl_bad_interface.carbon
  24. 28 28
      toolchain/check/testdata/impl/forward_decls.carbon
  25. 4 4
      toolchain/check/testdata/impl/impl_assoc_const.carbon
  26. 4 4
      toolchain/check/testdata/impl/impl_assoc_const_with_prelude.carbon
  27. 32 32
      toolchain/check/testdata/impl/import_interface_assoc_const.carbon
  28. 2 2
      toolchain/check/testdata/impl/import_self_specific.carbon
  29. 14 14
      toolchain/check/testdata/impl/incomplete.carbon
  30. 8 8
      toolchain/check/testdata/impl/lookup/lookup_interface_with_enclosing_generic_inside_rewrite_constraint.carbon
  31. 14 14
      toolchain/check/testdata/impl/lookup/specialization_with_symbolic_rewrite.carbon
  32. 30 30
      toolchain/check/testdata/impl/use_assoc_entity.carbon
  33. 2 2
      toolchain/check/testdata/interface/fail_lookup_in_type_type.carbon
  34. 2 2
      toolchain/check/testdata/interface/incomplete.carbon
  35. 4 4
      toolchain/check/testdata/interface/require.carbon
  36. 2 2
      toolchain/check/testdata/named_constraint/extend_name_lookup.carbon
  37. 8 8
      toolchain/check/testdata/named_constraint/require.carbon
  38. 6 6
      toolchain/check/testdata/operators/overloaded/index_with_prelude.carbon
  39. 16 16
      toolchain/check/testdata/where_expr/constraints.carbon
  40. 6 6
      toolchain/check/testdata/where_expr/designator.carbon
  41. 2 2
      toolchain/check/testdata/where_expr/dot_self_index.carbon
  42. 14 14
      toolchain/check/testdata/where_expr/equal_rewrite.carbon
  43. 2 2
      toolchain/check/testdata/where_expr/non_generic.carbon
  44. 1 0
      toolchain/check/type_completion.cpp
  45. 0 1
      toolchain/sem_ir/formatter.cpp
  46. 2 4
      toolchain/sem_ir/typed_insts.h

+ 2 - 0
toolchain/check/BUILD

@@ -66,6 +66,7 @@ cc_library(
         "operator.cpp",
         "pattern.cpp",
         "pattern_match.cpp",
+        "period_self.cpp",
         "pointer_dereference.cpp",
         "require_impls_stack.cpp",
         "return.cpp",
@@ -135,6 +136,7 @@ cc_library(
         "pattern.h",
         "pattern_match.h",
         "pending_block.h",
+        "period_self.h",
         "pointer_dereference.h",
         "region_stack.h",
         "require_impls_stack.h",

+ 11 - 56
toolchain/check/eval.cpp

@@ -22,6 +22,7 @@
 #include "toolchain/check/import_ref.h"
 #include "toolchain/check/inst.h"
 #include "toolchain/check/name_lookup.h"
+#include "toolchain/check/period_self.h"
 #include "toolchain/check/type.h"
 #include "toolchain/check/type_completion.h"
 #include "toolchain/diagnostics/diagnostic.h"
@@ -2487,17 +2488,6 @@ auto TryEvalTypedInst<SemIR::Temporary>(EvalContext& eval_context,
   return MakeConstantResult(eval_context.context(), temporary, phase);
 }
 
-// Returns whether `const_id` is the same constant facet value as
-// `facet_value_inst_id`.
-//
-// Compares with the canonical facet value of `const_id`, dropping any `as type`
-// conversions.
-static auto IsSameFacetValue(Context& context, SemIR::ConstantId const_id,
-                             SemIR::InstId facet_value_inst_id) -> bool {
-  auto canon_const_id = GetCanonicalFacetOrTypeValue(context, const_id);
-  return canon_const_id == context.constant_values().Get(facet_value_inst_id);
-}
-
 static auto AddRequirementBase(Context& context,
                                SemIR::RequirementBaseFacetType base,
                                SemIR::FacetTypeInfo* info, Phase* phase)
@@ -2569,7 +2559,6 @@ static auto AddRequirementRewrite(Context& context,
 
 static auto AddRequirementImpls(Context& context, SemIR::LocId loc_id,
                                 SemIR::RequirementImpls impls,
-                                SemIR::InstId period_self_id,
                                 SemIR::FacetTypeInfo* info, Phase* phase)
     -> void {
   auto lhs_id = context.constant_values().GetConstantInstId(impls.lhs_id);
@@ -2588,8 +2577,7 @@ static auto AddRequirementImpls(Context& context, SemIR::LocId loc_id,
   auto facet_type = context.insts().GetAs<SemIR::FacetType>(rhs_id);
   const auto& rhs = context.facet_types().Get(facet_type.facet_type_id);
 
-  if (IsSameFacetValue(context, context.constant_values().Get(lhs_id),
-                       period_self_id)) {
+  if (IsPeriodSelf(context, lhs_id)) {
     // A facet type with `.Self impls <RHS facet type>`. Whatever the RHS facet
     // type constrains for `.Self` gets forwarded to the output facet type to
     // also constrain `.Self`. Nothing on the RHS of `impls` can extend the
@@ -2646,35 +2634,6 @@ static auto AddRequirementImpls(Context& context, SemIR::LocId loc_id,
     // facet that it could possibly refer to, the `T as X` from the `impls`
     // constraint, which eliminates any ambiguity in the resulting facet type.
 
-    class SubstPeriodSelfDiagnoseExplicitCallbacks
-        : public SubstPeriodSelfCallbacks {
-     public:
-      explicit SubstPeriodSelfDiagnoseExplicitCallbacks(
-          Context* context, SemIR::LocId loc_id,
-          SemIR::ConstantId period_self_replacement_id, Phase* phase)
-          : SubstPeriodSelfCallbacks(context, loc_id,
-                                     period_self_replacement_id),
-            phase_(phase) {}
-
-      auto ShouldReplace(bool implicit) -> bool override {
-        if (!implicit && *phase_ != Phase::UnknownDueToError) {
-          CARBON_DIAGNOSTIC(
-              AmbiguousPeriodSelf, Error,
-              "`.Self` is ambiguous after nested `where` in `<type> "
-              "impls ...` clause.");
-          context().emitter().Emit(loc_id(), AmbiguousPeriodSelf);
-          *phase_ = Phase::UnknownDueToError;
-        }
-        return implicit;
-      }
-
-      Phase* phase_;
-    };
-    SubstPeriodSelfDiagnoseExplicitCallbacks
-        callbacks_should_replace_explicit_is_error(
-            &context, loc_id, context.constant_values().Get(lhs_facet_or_type),
-            phase);
-
     class SubstPeriodSelfImplicitOnlyCallbacks
         : public SubstPeriodSelfCallbacks {
      public:
@@ -2692,21 +2651,21 @@ static auto AddRequirementImpls(Context& context, SemIR::LocId loc_id,
         &context, loc_id, context.constant_values().Get(lhs_facet_or_type));
 
     auto self_impls_interface = [&](SemIR::SpecificInterface si) {
-      return SubstPeriodSelf(context,
-                             callbacks_should_replace_explicit_is_error, si);
+      return SubstPeriodSelf(context, callbacks_should_replace_implicit_only,
+                             si);
     };
     auto self_impls_constraint = [&](SemIR::SpecificNamedConstraint sc) {
-      return SubstPeriodSelf(context,
-                             callbacks_should_replace_explicit_is_error, sc);
+      return SubstPeriodSelf(context, callbacks_should_replace_implicit_only,
+                             sc);
     };
     auto type_impls_interface =
         [&](SemIR::FacetTypeInfo::TypeImplsInterface impls)
         -> SemIR::FacetTypeInfo::TypeImplsInterface {
       auto self =
-          SubstPeriodSelf(context, callbacks_should_replace_explicit_is_error,
+          SubstPeriodSelf(context, callbacks_should_replace_implicit_only,
                           context.constant_values().Get(impls.self_type));
       auto interface =
-          SubstPeriodSelf(context, callbacks_should_replace_explicit_is_error,
+          SubstPeriodSelf(context, callbacks_should_replace_implicit_only,
                           impls.specific_interface);
       return {context.constant_values().GetInstId(self), interface};
     };
@@ -2714,10 +2673,10 @@ static auto AddRequirementImpls(Context& context, SemIR::LocId loc_id,
         [&](SemIR::FacetTypeInfo::TypeImplsNamedConstraint impls)
         -> SemIR::FacetTypeInfo::TypeImplsNamedConstraint {
       auto self =
-          SubstPeriodSelf(context, callbacks_should_replace_explicit_is_error,
+          SubstPeriodSelf(context, callbacks_should_replace_implicit_only,
                           context.constant_values().Get(impls.self_type));
       auto constraint =
-          SubstPeriodSelf(context, callbacks_should_replace_explicit_is_error,
+          SubstPeriodSelf(context, callbacks_should_replace_implicit_only,
                           impls.specific_named_constraint);
       return {context.constant_values().GetInstId(self), constraint};
     };
@@ -2777,10 +2736,6 @@ auto TryEvalTypedInst<SemIR::WhereExpr>(EvalContext& eval_context,
   Phase phase = Phase::Concrete;
   SemIR::FacetTypeInfo info;
 
-  if (typed_inst.period_self_id == SemIR::ErrorInst::InstId) {
-    return SemIR::ErrorInst::ConstantId;
-  }
-
   // Note that these requirement instructions don't have a constant value. That
   // means we have to look for errors inside them, we can't just look to see if
   // their constant value is an error.
@@ -2803,7 +2758,7 @@ auto TryEvalTypedInst<SemIR::WhereExpr>(EvalContext& eval_context,
       }
       case CARBON_KIND(SemIR::RequirementImpls impls): {
         AddRequirementImpls(eval_context.context(), SemIR::LocId(inst_id),
-                            impls, typed_inst.period_self_id, &info, &phase);
+                            impls, &info, &phase);
         break;
       }
       case CARBON_KIND(SemIR::RequirementEquivalent _): {

+ 1 - 0
toolchain/check/eval_inst.cpp

@@ -17,6 +17,7 @@
 #include "toolchain/check/impl_lookup.h"
 #include "toolchain/check/import_ref.h"
 #include "toolchain/check/inst.h"
+#include "toolchain/check/period_self.h"
 #include "toolchain/check/type.h"
 #include "toolchain/check/type_completion.h"
 #include "toolchain/diagnostics/diagnostic.h"

+ 0 - 264
toolchain/check/facet_type.cpp

@@ -6,17 +6,12 @@
 
 #include "toolchain/base/kind_switch.h"
 #include "toolchain/check/context.h"
-#include "toolchain/check/control_flow.h"
-#include "toolchain/check/convert.h"
-#include "toolchain/check/generic.h"
 #include "toolchain/check/import_ref.h"
 #include "toolchain/check/inst.h"
 #include "toolchain/check/interface.h"
 #include "toolchain/check/subst.h"
 #include "toolchain/check/type.h"
-#include "toolchain/check/type_completion.h"
 #include "toolchain/sem_ir/generic.h"
-#include "toolchain/sem_ir/ids.h"
 #include "toolchain/sem_ir/typed_insts.h"
 
 namespace Carbon::Check {
@@ -402,29 +397,6 @@ auto ResolveFacetTypeRewriteConstraints(
   return true;
 }
 
-auto MakePeriodSelfFacetValue(Context& context, SemIR::TypeId self_type_id)
-    -> SemIR::InstId {
-  CARBON_CHECK(self_type_id == SemIR::ErrorInst::TypeId ||
-               context.types().Is<SemIR::FacetType>(self_type_id));
-  auto entity_name_id = context.entity_names().AddCanonical({
-      .name_id = SemIR::NameId::PeriodSelf,
-      .parent_scope_id = context.scope_stack().PeekNameScopeId(),
-  });
-  auto inst_id = AddInst(
-      context, SemIR::LocIdAndInst::NoLoc<SemIR::SymbolicBinding>({
-                   .type_id = self_type_id,
-                   .entity_name_id = entity_name_id,
-                   // `None` because there is no equivalent non-symbolic value.
-                   .value_id = SemIR::InstId::None,
-               }));
-  auto existing = context.scope_stack().LookupOrAddName(
-      SemIR::NameId::PeriodSelf, inst_id, ScopeIndex::None,
-      IsCurrentPositionReachable(context));
-  // Shouldn't have any names in newly created scope.
-  CARBON_CHECK(!existing.has_value());
-  return inst_id;
-}
-
 auto GetEmptyFacetType(Context& context) -> SemIR::TypeId {
   SemIR::FacetTypeId facet_type_id =
       context.facet_types().Add(SemIR::FacetTypeInfo{});
@@ -468,240 +440,4 @@ auto GetConstantFacetValueForTypeAndInterface(
   return self_value_const_id;
 }
 
-SubstPeriodSelfCallbacks::SubstPeriodSelfCallbacks(
-    Context* context, SemIR::LocId loc_id,
-    SemIR::ConstantId period_self_replacement_id)
-    : SubstInstCallbacks(context),
-      loc_id_(loc_id),
-      period_self_replacement_id_(period_self_replacement_id) {}
-
-auto SubstPeriodSelfCallbacks::Subst(SemIR::InstId& inst_id) -> SubstResult {
-  // FacetTypes are concrete even if they have `.Self` inside them, but we
-  // don't recurse into FacetTypes, so we can use this as a base case. This
-  // avoids infinite recursion on TypeType and ErrorInst.
-  if (context().constant_values().Get(inst_id).is_concrete()) {
-    return FullySubstituted;
-  }
-  // Don't recurse into nested facet types, even if they are symbolic. Leave
-  // their `.Self` as is.
-  if (context().insts().Is<SemIR::FacetType>(inst_id)) {
-    return FullySubstituted;
-  }
-
-  // For `.X` (which is `.Self.X`) replace the `.Self` in the query self
-  // position, and report it as `implicit`. Any `.Self` references in the
-  // specific interface would be replaced later and not treated as `implicit`.
-  //
-  // TODO: This all goes away when eval doesn't need to know about implicit
-  // .Self for diagnostics, once we diagnose invalid `.Self` in name lookup.
-  if (auto access =
-          context().insts().TryGetAs<SemIR::ImplWitnessAccess>(inst_id)) {
-    if (auto witness = context().insts().TryGetAs<SemIR::LookupImplWitness>(
-            access->witness_id)) {
-      if (auto bind = context().insts().TryGetAs<SemIR::SymbolicBinding>(
-              witness->query_self_inst_id)) {
-        const auto& entity_name =
-            context().entity_names().Get(bind->entity_name_id);
-        if (entity_name.name_id == SemIR::NameId::PeriodSelf) {
-          auto replacement_id =
-              GetReplacement(witness->query_self_inst_id, true);
-          auto new_witness =
-              Rebuild(access->witness_id,
-                      SemIR::LookupImplWitness{
-                          .type_id = witness->type_id,
-                          .query_self_inst_id = replacement_id,
-                          // Don't replace `.Self` in the interface specific
-                          // here. That is an explicit `.Self` use. We'll
-                          // revisit the instruction for that.
-                          .query_specific_interface_id =
-                              witness->query_specific_interface_id,
-                      });
-          auto new_access = Rebuild(inst_id, SemIR::ImplWitnessAccess{
-                                                 .type_id = access->type_id,
-                                                 .witness_id = new_witness,
-                                                 .index = access->index,
-                                             });
-          inst_id = new_access;
-          return SubstAgain;
-        }
-      }
-    }
-  }
-
-  if (auto bind = context().insts().TryGetAs<SemIR::SymbolicBinding>(inst_id)) {
-    const auto& entity_name =
-        context().entity_names().Get(bind->entity_name_id);
-    if (entity_name.name_id == SemIR::NameId::PeriodSelf) {
-      inst_id = GetReplacement(inst_id, false);
-      return FullySubstituted;
-    }
-  }
-
-  return SubstOperands;
-}
-
-auto SubstPeriodSelfCallbacks::Rebuild(SemIR::InstId orig_inst_id,
-                                       SemIR::Inst new_inst) -> SemIR::InstId {
-  return RebuildNewInst(SemIR::LocId(orig_inst_id), new_inst);
-}
-
-auto SubstPeriodSelfCallbacks::GetReplacement(SemIR::InstId period_self,
-                                              bool implicit) -> SemIR::InstId {
-  if (!ShouldReplace(implicit)) {
-    return period_self;
-  }
-
-  auto period_self_type_id = context().insts().Get(period_self).type_id();
-  CARBON_CHECK(context().types().Is<SemIR::FacetType>(period_self_type_id));
-
-  auto replacement_self_inst_id =
-      context().constant_values().GetInstId(period_self_replacement_id_);
-  auto replacement_type_id =
-      context().insts().Get(replacement_self_inst_id).type_id();
-  CARBON_CHECK(context().types().IsFacetType(replacement_type_id));
-
-  // If the replacement has the same type as `.Self`, use it directly.
-  if (replacement_type_id == period_self_type_id) {
-    return replacement_self_inst_id;
-  }
-
-  // If we have already converted the replacement to the type of `.Self`, use
-  // our previous conversion.
-  if (period_self_type_id == cached_replacement_type_id_) {
-    return cached_replacement_id_;
-  }
-
-  // Convert the replacement facet to the type of `.Self`.
-  cached_replacement_id_ = ConvertReplacement(
-      replacement_self_inst_id, replacement_type_id, period_self_type_id);
-  cached_replacement_type_id_ = period_self_type_id;
-  return cached_replacement_id_;
-}
-
-auto SubstPeriodSelfCallbacks::ConvertReplacement(
-    SemIR::InstId replacement_self_inst_id, SemIR::TypeId replacement_type_id,
-    SemIR::TypeId period_self_type_id) -> SemIR::InstId {
-  // TODO: Replace all empty facet types with TypeType.
-  if (period_self_type_id == GetEmptyFacetType(context())) {
-    // Convert to an empty facet type (representing TypeType); we don't need
-    // any witnesses.
-    return ConvertToValueOfType(context(), loc_id_, replacement_self_inst_id,
-                                period_self_type_id);
-  }
-
-  // We have a facet or a type, but we need more interfaces in the facet type.
-  // We will have to synthesize a symbolic witness for each interface.
-  //
-  // Why is this okay? The type of `.Self` comes from interfaces that are
-  // before it (to the left of it) in the facet type. The replacement for
-  // `.Self` will have to impl those interfaces in order to match the facet
-  // type, so we know that it is valid to construct these witnesses.
-
-  // Make the replacement into a type, which we will need for the FacetValue.
-  if (context().types().Is<SemIR::FacetType>(replacement_type_id)) {
-    replacement_self_inst_id = context().constant_values().GetInstId(
-        EvalOrAddInst<SemIR::FacetAccessType>(
-            context(), loc_id_,
-            {.type_id = SemIR::TypeType::TypeId,
-             .facet_value_inst_id = replacement_self_inst_id}));
-  }
-
-  auto period_self_facet_type =
-      context().types().GetAs<SemIR::FacetType>(period_self_type_id);
-  auto identified_period_self_type_id = RequireIdentifiedFacetType(
-      context(), loc_id_,
-      context().constant_values().Get(replacement_self_inst_id),
-      period_self_facet_type, [&](auto& /*builder*/) {
-        // The facet type containing this `.Self` should have already been
-        // identified, which would ensure that the type of `.Self` can be
-        // identified since it can only depend on things to the left of it
-        // inside the same facet type.
-        CARBON_FATAL("could not identify type of `.Self`");
-      });
-  const auto& identified_period_self_type =
-      context().identified_facet_types().Get(identified_period_self_type_id);
-  auto required_impls = identified_period_self_type.required_impls();
-  llvm::SmallVector<SemIR::InstId> witnesses;
-  witnesses.reserve(required_impls.size());
-  for (const auto& req : required_impls) {
-    witnesses.push_back(context().constant_values().GetInstId(
-        EvalOrAddInst<SemIR::LookupImplWitness>(
-            context(), loc_id_,
-            {.type_id =
-                 GetSingletonType(context(), SemIR::WitnessType::TypeInstId),
-             .query_self_inst_id =
-                 context().constant_values().GetInstId(req.self_facet_value),
-             .query_specific_interface_id = context().specific_interfaces().Add(
-                 req.specific_interface)})));
-  }
-  return context().constant_values().GetInstId(EvalOrAddInst<SemIR::FacetValue>(
-      context(), loc_id_,
-      {
-          .type_id = period_self_type_id,
-          .type_inst_id =
-              context().types().GetAsTypeInstId(replacement_self_inst_id),
-          .witnesses_block_id = context().inst_blocks().Add(witnesses),
-      }));
-}
-
-auto SubstPeriodSelf(Context& context, SubstPeriodSelfCallbacks& callbacks,
-                     SemIR::ConstantId const_id) -> SemIR::ConstantId {
-  // Don't replace `.Self` with itself; that is cyclical.
-  //
-  // If the types differ, we would try to convert the replacement to a `.Self`
-  // of the desired type in `const_id`, which is what we already have, so
-  // there's nothing we need to do. But trying to do that conversion recurses
-  // when the type of the `.Self` contains a `.Self`.
-  if (auto bind_type =
-          context.constant_values().TryGetInstAs<SemIR::SymbolicBinding>(
-              GetCanonicalFacetOrTypeValue(
-                  context, callbacks.period_self_replacement_id()))) {
-    if (context.entity_names().Get(bind_type->entity_name_id).name_id ==
-        SemIR::NameId::PeriodSelf) {
-      return const_id;
-    }
-  }
-
-  auto subst_id = SubstInst(
-      context, context.constant_values().GetInstId(const_id), callbacks);
-  return context.constant_values().Get(subst_id);
-}
-
-static auto SubstPeriodSelfInSpecific(Context& context,
-                                      SubstPeriodSelfCallbacks& callbacks,
-                                      SemIR::SpecificId specific_id)
-    -> SemIR::SpecificId {
-  if (!specific_id.has_value()) {
-    return specific_id;
-  }
-
-  const auto& specific = context.specifics().Get(specific_id);
-
-  // Substitute into the specific without having to construct a FacetType
-  // instruction just to hold the specific interface inside a constant id.
-  llvm::SmallVector<SemIR::InstId> args(
-      context.inst_blocks().Get(specific.args_id));
-  for (auto& arg_id : args) {
-    auto const_id = context.constant_values().Get(arg_id);
-    const_id = SubstPeriodSelf(context, callbacks, const_id);
-    arg_id = context.constant_values().GetInstId(const_id);
-  }
-  return MakeSpecific(context, callbacks.loc_id(), specific.generic_id, args);
-}
-
-auto SubstPeriodSelf(Context& context, SubstPeriodSelfCallbacks& callbacks,
-                     SemIR::SpecificInterface interface)
-    -> SemIR::SpecificInterface {
-  interface.specific_id =
-      SubstPeriodSelfInSpecific(context, callbacks, interface.specific_id);
-  return interface;
-}
-auto SubstPeriodSelf(Context& context, SubstPeriodSelfCallbacks& callbacks,
-                     SemIR::SpecificNamedConstraint constraint)
-    -> SemIR::SpecificNamedConstraint {
-  constraint.specific_id =
-      SubstPeriodSelfInSpecific(context, callbacks, constraint.specific_id);
-  return constraint;
-}
-
 }  // namespace Carbon::Check

+ 0 - 61
toolchain/check/facet_type.h

@@ -5,11 +5,7 @@
 #ifndef CARBON_TOOLCHAIN_CHECK_FACET_TYPE_H_
 #define CARBON_TOOLCHAIN_CHECK_FACET_TYPE_H_
 
-#include <compare>
-
 #include "toolchain/check/context.h"
-#include "toolchain/check/subst.h"
-#include "toolchain/sem_ir/entity_with_params_base.h"
 #include "toolchain/sem_ir/ids.h"
 
 namespace Carbon::Check {
@@ -62,16 +58,6 @@ auto ResolveFacetTypeRewriteConstraints(
     llvm::SmallVector<SemIR::FacetTypeInfo::RewriteConstraint>& rewrites)
     -> bool;
 
-// Introduce `.Self` as a symbolic binding into the current scope, and return
-// the `SymbolicBinding` instruction.
-//
-// The type of `.Self` must be a `FacetType`, so that it gets wrapped in
-// `FacetAccessType` when used in a type position, such as in `U:! I(.Self)`.
-// This allows substitution with other facet values without requiring an
-// additional `FacetAccessType` to be inserted.
-auto MakePeriodSelfFacetValue(Context& context, SemIR::TypeId self_type_id)
-    -> SemIR::InstId;
-
 // Get a FacetType instruction for an empty FacetType. This is the facet
 // equivalent to TypeType.
 //
@@ -90,53 +76,6 @@ auto GetConstantFacetValueForTypeAndInterface(
     SemIR::SpecificInterface specific_interface, SemIR::InstId witness_id)
     -> SemIR::ConstantId;
 
-class SubstPeriodSelfCallbacks : public SubstInstCallbacks {
- public:
-  explicit SubstPeriodSelfCallbacks(
-      Context* context, SemIR::LocId loc_id,
-      SemIR::ConstantId period_self_replacement_id);
-  auto Subst(SemIR::InstId& inst_id) -> SubstResult override;
-  auto Rebuild(SemIR::InstId orig_inst_id, SemIR::Inst new_inst)
-      -> SemIR::InstId override;
-
-  virtual auto ShouldReplace(bool /*implicit*/) -> bool { return true; }
-
-  auto loc_id() const -> SemIR::LocId { return loc_id_; }
-  auto period_self_replacement_id() const -> SemIR::ConstantId {
-    return period_self_replacement_id_;
-  }
-
- private:
-  auto GetReplacement(SemIR::InstId period_self, bool implicit)
-      -> SemIR::InstId;
-  auto ConvertReplacement(SemIR::InstId replacement_self_inst_id,
-                          SemIR::TypeId replacement_type_id,
-                          SemIR::TypeId period_self_type_id) -> SemIR::InstId;
-
-  SemIR::LocId loc_id_;
-  SemIR::ConstantId period_self_replacement_id_;
-
-  // The last output of GetReplacement().
-  SemIR::InstId cached_replacement_id_ = SemIR::InstId::None;
-  // The type of the last output of GetReplacement(). If the type of `.Self`
-  // matches, we can reuse the `cached_replacement_id_`.
-  SemIR::TypeId cached_replacement_type_id_ = SemIR::TypeId::None;
-};
-
-// Replace all `.Self` references in `const_id`. The `callbacks` specifies the
-// facet to replace them with.
-auto SubstPeriodSelf(Context& context, SubstPeriodSelfCallbacks& callbacks,
-                     SemIR::ConstantId const_id) -> SemIR::ConstantId;
-
-// Replace all `.Self` references in the specific of the interface or named
-// constraint. The `callbacks` specifies the facet to replace them with.
-auto SubstPeriodSelf(Context& context, SubstPeriodSelfCallbacks& callbacks,
-                     SemIR::SpecificInterface interface)
-    -> SemIR::SpecificInterface;
-auto SubstPeriodSelf(Context& context, SubstPeriodSelfCallbacks& callbacks,
-                     SemIR::SpecificNamedConstraint constraint)
-    -> SemIR::SpecificNamedConstraint;
-
 }  // namespace Carbon::Check
 
 #endif  // CARBON_TOOLCHAIN_CHECK_FACET_TYPE_H_

+ 1 - 0
toolchain/check/handle_binding_pattern.cpp

@@ -14,6 +14,7 @@
 #include "toolchain/check/interface.h"
 #include "toolchain/check/name_lookup.h"
 #include "toolchain/check/pattern.h"
+#include "toolchain/check/period_self.h"
 #include "toolchain/check/return.h"
 #include "toolchain/check/type.h"
 #include "toolchain/check/type_completion.h"

+ 1 - 1
toolchain/check/handle_require.cpp

@@ -5,12 +5,12 @@
 #include "toolchain/base/kind_switch.h"
 #include "toolchain/check/context.h"
 #include "toolchain/check/convert.h"
-#include "toolchain/check/facet_type.h"
 #include "toolchain/check/generic.h"
 #include "toolchain/check/handle.h"
 #include "toolchain/check/inst.h"
 #include "toolchain/check/modifiers.h"
 #include "toolchain/check/name_lookup.h"
+#include "toolchain/check/period_self.h"
 #include "toolchain/check/subst.h"
 #include "toolchain/check/type.h"
 #include "toolchain/check/type_completion.h"

+ 19 - 17
toolchain/check/handle_where.cpp

@@ -9,6 +9,7 @@
 #include "toolchain/check/generic.h"
 #include "toolchain/check/handle.h"
 #include "toolchain/check/inst.h"
+#include "toolchain/check/period_self.h"
 #include "toolchain/check/subst.h"
 #include "toolchain/check/type.h"
 #include "toolchain/check/unused.h"
@@ -33,6 +34,12 @@ auto HandleParseNode(Context& context, Parse::WhereOperandId node_id) -> bool {
     context.emitter().Emit(self_node, WhereOnNonFacetType);
     self_with_constraints_type_id = SemIR::ErrorInst::TypeId;
   }
+  if (self_with_constraints_type_id == SemIR::ErrorInst::TypeId) {
+    // Keep `self_id` in sync with `self_with_constraints_type_id`, if one is an
+    //  error they both are. Note that ExprAsType may have returned ErrorInst,
+    //  or we may have set it to ErrorInst in this function.
+    self_id = SemIR::ErrorInst::InstId;
+  }
 
   // Strip off any constraints provided by a `WhereExpr` from the `Self` facet
   // type. For a facet type like `I & J where .X = .Y`, this will reduce it down
@@ -62,12 +69,7 @@ auto HandleParseNode(Context& context, Parse::WhereOperandId node_id) -> bool {
   context.scope_stack().PushForSameRegion();
   // Introduce `.Self` as a symbolic binding. Its type is the value of the
   // expression to the left of `where`, so `MyInterface` in the example above.
-  auto period_self_inst_id =
-      MakePeriodSelfFacetValue(context, period_self_type_id);
-
-  // Save the `.Self` symbolic binding on the node stack. It will become the
-  // first argument to the `WhereExpr` instruction.
-  context.node_stack().Push(node_id, period_self_inst_id);
+  MakePeriodSelfFacetValue(context, period_self_type_id);
 
   // Going to put each requirement on `args_type_info_stack`, so we can have an
   // inst block with the varying number of requirements but keeping other
@@ -79,8 +81,7 @@ auto HandleParseNode(Context& context, Parse::WhereOperandId node_id) -> bool {
   context.args_type_info_stack().AddInstId(
       AddInstInNoBlock<SemIR::RequirementBaseFacetType>(
           context, SemIR::LocId(node_id),
-          {.base_type_inst_id =
-               context.types().GetTypeInstId(self_with_constraints_type_id)}));
+          {.base_type_inst_id = context.types().GetAsTypeInstId(self_id)}));
 
   // Add a context stack for tracking rewrite constraints, that will be used to
   // allow later constraints to read from them eagerly.
@@ -179,6 +180,11 @@ auto HandleParseNode(Context& context, Parse::RequirementImplsId node_id)
   // TODO: For things like `HashSet(.T) as type`, add an implied constraint
   // that `.T impls Hash`.
 
+  if (FindAndDiagnoseAmbiguousPeriodSelf(context, lhs_as_type.inst_id,
+                                         rhs_id)) {
+    rhs_as_type.inst_id = SemIR::ErrorInst::TypeInstId;
+  }
+
   // Build up the list of arguments for the `WhereExpr` inst.
   context.args_type_info_stack().AddInstId(
       AddInstInNoBlock<SemIR::RequirementImpls>(
@@ -202,8 +208,6 @@ static auto FindDesignator(Context& context,
   llvm::SmallVector<SemIR::InstId> requirements;
   requirements.reserve(block.size() * 2);
 
-  // These requirement instructions don't have a constant value, but they
-  // contain only canonical instructions.
   for (auto inst_id : block) {
     auto inst = context.insts().Get(inst_id);
     CARBON_KIND_SWITCH(inst) {
@@ -291,22 +295,20 @@ auto HandleParseNode(Context& context, Parse::WhereExprId node_id) -> bool {
   // Remove `PeriodSelf` from name lookup, undoing the `Push` done for the
   // `WhereOperand`.
   context.scope_stack().Pop(/*check_unused=*/true);
-  SemIR::InstId period_self_id =
-      context.node_stack().Pop<Parse::NodeKind::WhereOperand>();
   SemIR::InstBlockId requirements_id = context.args_type_info_stack().Pop();
 
+  auto type_id = SemIR::TypeType::TypeId;
   if (!FindDesignator(context, requirements_id)) {
     CARBON_DIAGNOSTIC(WhereWithoutDesignator, Error,
                       "`where` clause without a designator; expected `.Self` "
                       "to appear in a requirement, or a member of `.Self`");
     context.emitter().Emit(node_id, WhereWithoutDesignator);
-    period_self_id = SemIR::ErrorInst::InstId;
+    type_id = SemIR::ErrorInst::TypeId;
   }
 
-  AddInstAndPush<SemIR::WhereExpr>(context, node_id,
-                                   {.type_id = SemIR::TypeType::TypeId,
-                                    .period_self_id = period_self_id,
-                                    .requirements_id = requirements_id});
+  AddInstAndPush<SemIR::WhereExpr>(
+      context, node_id,
+      {.type_id = type_id, .requirements_id = requirements_id});
   return true;
 }
 

+ 1 - 0
toolchain/check/impl.cpp

@@ -19,6 +19,7 @@
 #include "toolchain/check/merge.h"
 #include "toolchain/check/name_lookup.h"
 #include "toolchain/check/name_scope.h"
+#include "toolchain/check/period_self.h"
 #include "toolchain/check/thunk.h"
 #include "toolchain/check/type.h"
 #include "toolchain/check/type_completion.h"

+ 1 - 1
toolchain/check/impl_lookup.cpp

@@ -15,11 +15,11 @@
 #include "toolchain/check/deduce.h"
 #include "toolchain/check/diagnostic_helpers.h"
 #include "toolchain/check/eval.h"
-#include "toolchain/check/facet_type.h"
 #include "toolchain/check/generic.h"
 #include "toolchain/check/impl.h"
 #include "toolchain/check/import_ref.h"
 #include "toolchain/check/inst.h"
+#include "toolchain/check/period_self.h"
 #include "toolchain/check/subst.h"
 #include "toolchain/check/type.h"
 #include "toolchain/check/type_completion.h"

+ 1 - 1
toolchain/check/node_stack.h

@@ -420,7 +420,6 @@ class NodeStack {
       case Parse::NodeKind::ShortCircuitOperandAnd:
       case Parse::NodeKind::ShortCircuitOperandOr:
       case Parse::NodeKind::StructLiteralField:
-      case Parse::NodeKind::WhereOperand:
         return Id::KindFor<SemIR::InstId>();
       case Parse::NodeKind::ExplicitParamList:
       case Parse::NodeKind::ForIn:
@@ -480,6 +479,7 @@ class NodeStack {
       case Parse::NodeKind::VariableIntroducer:
       case Parse::NodeKind::InlineImportBody:
       case Parse::NodeKind::InlineIntroducer:
+      case Parse::NodeKind::WhereOperand:
         return Id::Kind::None;
       case Parse::NodeKind::AdaptIntroducer:
       case Parse::NodeKind::AliasInitializer:

+ 609 - 0
toolchain/check/period_self.cpp

@@ -0,0 +1,609 @@
+// 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/period_self.h"
+
+#include "toolchain/base/kind_switch.h"
+#include "toolchain/check/control_flow.h"
+#include "toolchain/check/convert.h"
+#include "toolchain/check/facet_type.h"
+#include "toolchain/check/generic.h"
+#include "toolchain/check/inst.h"
+#include "toolchain/check/type.h"
+#include "toolchain/check/type_completion.h"
+#include "toolchain/sem_ir/typed_insts.h"
+
+namespace Carbon::Check {
+
+auto MakePeriodSelfFacetValue(Context& context, SemIR::TypeId self_type_id)
+    -> SemIR::InstId {
+  CARBON_CHECK(self_type_id == SemIR::ErrorInst::TypeId ||
+               context.types().Is<SemIR::FacetType>(self_type_id));
+  auto entity_name_id = context.entity_names().AddCanonical({
+      .name_id = SemIR::NameId::PeriodSelf,
+      .parent_scope_id = context.scope_stack().PeekNameScopeId(),
+  });
+  auto inst_id = AddInst(
+      context, SemIR::LocIdAndInst::NoLoc<SemIR::SymbolicBinding>({
+                   .type_id = self_type_id,
+                   .entity_name_id = entity_name_id,
+                   // `None` because there is no equivalent non-symbolic value.
+                   .value_id = SemIR::InstId::None,
+               }));
+  auto existing = context.scope_stack().LookupOrAddName(
+      SemIR::NameId::PeriodSelf, inst_id, ScopeIndex::None,
+      IsCurrentPositionReachable(context));
+  // Shouldn't have any names in newly created scope.
+  CARBON_CHECK(!existing.has_value());
+  return inst_id;
+}
+
+SubstPeriodSelfCallbacks::SubstPeriodSelfCallbacks(
+    Context* context, SemIR::LocId loc_id,
+    SemIR::ConstantId period_self_replacement_id)
+    : SubstInstCallbacks(context),
+      loc_id_(loc_id),
+      period_self_replacement_id_(period_self_replacement_id) {}
+
+auto SubstPeriodSelfCallbacks::Subst(SemIR::InstId& inst_id) -> SubstResult {
+  // FacetTypes are concrete even if they have `.Self` inside them, but we
+  // don't recurse into FacetTypes, so we can use this as a base case. This
+  // avoids infinite recursion on TypeType and ErrorInst.
+  if (context().constant_values().Get(inst_id).is_concrete()) {
+    return FullySubstituted;
+  }
+  // Don't recurse into nested facet types, even if they are symbolic. Leave
+  // their `.Self` as is.
+  if (context().insts().Is<SemIR::FacetType>(inst_id)) {
+    return FullySubstituted;
+  }
+
+  // For `.X` (which is `.Self.X`) replace the `.Self` in the query self
+  // position, and report it as `implicit`. Any `.Self` references in the
+  // specific interface would be replaced later and not treated as `implicit`.
+  //
+  // TODO: This all goes away when eval doesn't need to know about implicit
+  // .Self for diagnostics, once we diagnose invalid `.Self` in name lookup.
+  if (auto access =
+          context().insts().TryGetAs<SemIR::ImplWitnessAccess>(inst_id)) {
+    if (auto witness = context().insts().TryGetAs<SemIR::LookupImplWitness>(
+            access->witness_id)) {
+      if (auto bind = context().insts().TryGetAs<SemIR::SymbolicBinding>(
+              witness->query_self_inst_id)) {
+        const auto& entity_name =
+            context().entity_names().Get(bind->entity_name_id);
+        if (entity_name.name_id == SemIR::NameId::PeriodSelf) {
+          auto replacement_id =
+              GetReplacement(witness->query_self_inst_id, true);
+          auto new_witness =
+              Rebuild(access->witness_id,
+                      SemIR::LookupImplWitness{
+                          .type_id = witness->type_id,
+                          .query_self_inst_id = replacement_id,
+                          // Don't replace `.Self` in the interface specific
+                          // here. That is an explicit `.Self` use. We'll
+                          // revisit the instruction for that.
+                          .query_specific_interface_id =
+                              witness->query_specific_interface_id,
+                      });
+          auto new_access = Rebuild(inst_id, SemIR::ImplWitnessAccess{
+                                                 .type_id = access->type_id,
+                                                 .witness_id = new_witness,
+                                                 .index = access->index,
+                                             });
+          inst_id = new_access;
+          return SubstAgain;
+        }
+      }
+    }
+  }
+
+  if (auto bind = context().insts().TryGetAs<SemIR::SymbolicBinding>(inst_id)) {
+    const auto& entity_name =
+        context().entity_names().Get(bind->entity_name_id);
+    if (entity_name.name_id == SemIR::NameId::PeriodSelf) {
+      inst_id = GetReplacement(inst_id, false);
+      return FullySubstituted;
+    }
+  }
+
+  return SubstOperands;
+}
+
+auto SubstPeriodSelfCallbacks::Rebuild(SemIR::InstId orig_inst_id,
+                                       SemIR::Inst new_inst) -> SemIR::InstId {
+  return RebuildNewInst(SemIR::LocId(orig_inst_id), new_inst);
+}
+
+auto SubstPeriodSelfCallbacks::GetReplacement(SemIR::InstId period_self,
+                                              bool implicit) -> SemIR::InstId {
+  if (!ShouldReplace(implicit)) {
+    return period_self;
+  }
+
+  auto period_self_type_id = context().insts().Get(period_self).type_id();
+  CARBON_CHECK(context().types().Is<SemIR::FacetType>(period_self_type_id));
+
+  auto replacement_self_inst_id =
+      context().constant_values().GetInstId(period_self_replacement_id_);
+  auto replacement_type_id =
+      context().insts().Get(replacement_self_inst_id).type_id();
+  CARBON_CHECK(context().types().IsFacetType(replacement_type_id));
+
+  // If the replacement has the same type as `.Self`, use it directly.
+  if (replacement_type_id == period_self_type_id) {
+    return replacement_self_inst_id;
+  }
+
+  // If we have already converted the replacement to the type of `.Self`, use
+  // our previous conversion.
+  if (period_self_type_id == cached_replacement_type_id_) {
+    return cached_replacement_id_;
+  }
+
+  // Convert the replacement facet to the type of `.Self`.
+  cached_replacement_id_ = ConvertReplacement(
+      replacement_self_inst_id, replacement_type_id, period_self_type_id);
+  cached_replacement_type_id_ = period_self_type_id;
+  return cached_replacement_id_;
+}
+
+auto SubstPeriodSelfCallbacks::ConvertReplacement(
+    SemIR::InstId replacement_self_inst_id, SemIR::TypeId replacement_type_id,
+    SemIR::TypeId period_self_type_id) -> SemIR::InstId {
+  // TODO: Replace all empty facet types with TypeType.
+  if (period_self_type_id == GetEmptyFacetType(context())) {
+    // Convert to an empty facet type (representing TypeType); we don't need
+    // any witnesses.
+    return ConvertToValueOfType(context(), loc_id_, replacement_self_inst_id,
+                                period_self_type_id);
+  }
+
+  // We have a facet or a type, but we need more interfaces in the facet type.
+  // We will have to synthesize a symbolic witness for each interface.
+  //
+  // Why is this okay? The type of `.Self` comes from interfaces that are
+  // before it (to the left of it) in the facet type. The replacement for
+  // `.Self` will have to impl those interfaces in order to match the facet
+  // type, so we know that it is valid to construct these witnesses.
+
+  // Make the replacement into a type, which we will need for the FacetValue.
+  if (context().types().Is<SemIR::FacetType>(replacement_type_id)) {
+    replacement_self_inst_id = context().constant_values().GetInstId(
+        EvalOrAddInst<SemIR::FacetAccessType>(
+            context(), loc_id_,
+            {.type_id = SemIR::TypeType::TypeId,
+             .facet_value_inst_id = replacement_self_inst_id}));
+  }
+
+  auto period_self_facet_type =
+      context().types().GetAs<SemIR::FacetType>(period_self_type_id);
+  auto identified_period_self_type_id = RequireIdentifiedFacetType(
+      context(), loc_id_,
+      context().constant_values().Get(replacement_self_inst_id),
+      period_self_facet_type, [&](auto& /*builder*/) {
+        // The facet type containing this `.Self` should have already been
+        // identified, which would ensure that the type of `.Self` can be
+        // identified since it can only depend on things to the left of it
+        // inside the same facet type.
+        CARBON_FATAL("could not identify type of `.Self`");
+      });
+  const auto& identified_period_self_type =
+      context().identified_facet_types().Get(identified_period_self_type_id);
+  auto required_impls = identified_period_self_type.required_impls();
+  llvm::SmallVector<SemIR::InstId> witnesses;
+  witnesses.reserve(required_impls.size());
+  for (const auto& req : required_impls) {
+    witnesses.push_back(context().constant_values().GetInstId(
+        EvalOrAddInst<SemIR::LookupImplWitness>(
+            context(), loc_id_,
+            {.type_id =
+                 GetSingletonType(context(), SemIR::WitnessType::TypeInstId),
+             .query_self_inst_id =
+                 context().constant_values().GetInstId(req.self_facet_value),
+             .query_specific_interface_id = context().specific_interfaces().Add(
+                 req.specific_interface)})));
+  }
+  return context().constant_values().GetInstId(EvalOrAddInst<SemIR::FacetValue>(
+      context(), loc_id_,
+      {
+          .type_id = period_self_type_id,
+          .type_inst_id =
+              context().types().GetAsTypeInstId(replacement_self_inst_id),
+          .witnesses_block_id = context().inst_blocks().Add(witnesses),
+      }));
+}
+
+auto SubstPeriodSelf(Context& context, SubstPeriodSelfCallbacks& callbacks,
+                     SemIR::ConstantId const_id) -> SemIR::ConstantId {
+  // Don't replace `.Self` with itself; that is cyclical.
+  //
+  // If the types differ, we would try to convert the replacement to a `.Self`
+  // of the desired type in `const_id`, which is what we already have, so
+  // there's nothing we need to do. But trying to do that conversion recurses
+  // when the type of the `.Self` contains a `.Self`.
+  if (auto bind_type =
+          context.constant_values().TryGetInstAs<SemIR::SymbolicBinding>(
+              GetCanonicalFacetOrTypeValue(
+                  context, callbacks.period_self_replacement_id()))) {
+    if (context.entity_names().Get(bind_type->entity_name_id).name_id ==
+        SemIR::NameId::PeriodSelf) {
+      return const_id;
+    }
+  }
+
+  auto subst_id = SubstInst(
+      context, context.constant_values().GetInstId(const_id), callbacks);
+  return context.constant_values().Get(subst_id);
+}
+
+static auto SubstPeriodSelfInSpecific(Context& context,
+                                      SubstPeriodSelfCallbacks& callbacks,
+                                      SemIR::SpecificId specific_id)
+    -> SemIR::SpecificId {
+  if (!specific_id.has_value()) {
+    return specific_id;
+  }
+
+  const auto& specific = context.specifics().Get(specific_id);
+
+  // Substitute into the specific without having to construct a FacetType
+  // instruction just to hold the specific interface inside a constant id.
+  llvm::SmallVector<SemIR::InstId> args(
+      context.inst_blocks().Get(specific.args_id));
+  for (auto& arg_id : args) {
+    auto const_id = context.constant_values().Get(arg_id);
+    const_id = SubstPeriodSelf(context, callbacks, const_id);
+    arg_id = context.constant_values().GetInstId(const_id);
+  }
+  return MakeSpecific(context, callbacks.loc_id(), specific.generic_id, args);
+}
+
+auto SubstPeriodSelf(Context& context, SubstPeriodSelfCallbacks& callbacks,
+                     SemIR::SpecificInterface interface)
+    -> SemIR::SpecificInterface {
+  interface.specific_id =
+      SubstPeriodSelfInSpecific(context, callbacks, interface.specific_id);
+  return interface;
+}
+auto SubstPeriodSelf(Context& context, SubstPeriodSelfCallbacks& callbacks,
+                     SemIR::SpecificNamedConstraint constraint)
+    -> SemIR::SpecificNamedConstraint {
+  constraint.specific_id =
+      SubstPeriodSelfInSpecific(context, callbacks, constraint.specific_id);
+  return constraint;
+}
+
+auto IsPeriodSelf(Context& context, SemIR::InstId inst_id, bool canonicalize)
+    -> bool {
+  auto query_inst_id =
+      canonicalize
+          ? GetCanonicalFacetOrTypeValue(
+                context, context.constant_values().GetConstantInstId(inst_id))
+          : inst_id;
+  if (auto bind =
+          context.insts().TryGetAs<SemIR::SymbolicBinding>(query_inst_id)) {
+    const auto& entity_name = context.entity_names().Get(bind->entity_name_id);
+    return entity_name.name_id == SemIR::NameId::PeriodSelf;
+  }
+  return false;
+}
+
+class SearchNonCanonicalForExplicitPeriodSelf : public SubstInstCallbacks {
+ public:
+  explicit SearchNonCanonicalForExplicitPeriodSelf(Context* context,
+                                                   SemIR::LocId* found)
+      : SubstInstCallbacks(context), found_(found) {}
+
+  auto Subst(SemIR::InstId& inst_id) -> SubstResult override {
+    if (found_->has_value()) {
+      return FullySubstituted;
+    }
+
+    auto const_inst_id = context().constant_values().GetConstantInstId(inst_id);
+    if (const_inst_id == SemIR::TypeType::TypeInstId) {
+      // Recursion base case. TypeType has type TypeType.
+      return FullySubstituted;
+    }
+    if (context().insts().Is<SemIR::FacetType>(const_inst_id)) {
+      // Don't look for `.Self` in nested facet types, they aren't replaced
+      // with a facet value and just remain as abstract. WhereExprs evaluate
+      // to a FacetType but are handled outside of Subst.
+      return FullySubstituted;
+    }
+
+    if (auto name_ref = context().insts().TryGetAs<SemIR::NameRef>(inst_id)) {
+      // Canonicalization not necessary; NameRef contains the SymbolicBinding
+      // directly, not an `as type` conversion.
+      if (IsPeriodSelf(context(), name_ref->value_id,
+                       /*canonicalize=*/false)) {
+        // `.Self` does not have a location, the NameRef pointing to it does.
+        *found_ = SemIR::LocId(inst_id);
+        return FullySubstituted;
+      }
+    }
+
+    return SubstOperands;
+  }
+
+  auto Rebuild(SemIR::InstId /*orig_inst_id*/, SemIR::Inst /*new_inst*/)
+      -> SemIR::InstId override {
+    CARBON_FATAL();
+  }
+
+ private:
+  SemIR::LocId* found_;
+};
+
+class SearchCanonicalForExplicitPeriodSelf : public SubstInstCallbacks {
+ public:
+  explicit SearchCanonicalForExplicitPeriodSelf(Context* context, bool* found)
+      : SubstInstCallbacks(context), found_(found) {}
+
+  auto Subst(SemIR::InstId& inst_id) -> SubstResult override {
+    if (*found_) {
+      return FullySubstituted;
+    }
+
+    auto const_inst_id = context().constant_values().GetConstantInstId(inst_id);
+    if (const_inst_id == SemIR::TypeType::TypeInstId) {
+      // Recursion base case. TypeType has type TypeType.
+      return FullySubstituted;
+    }
+    if (context().insts().Is<SemIR::FacetType>(const_inst_id)) {
+      // Don't look for `.Self` in nested facet types, they aren't replaced
+      // with a facet value and just remain as abstract. WhereExprs evaluate
+      // to a FacetType but are handled outside of Subst.
+      return FullySubstituted;
+    }
+
+    if (auto access = context().insts().TryGetAs<SemIR::ImplWitnessAccess>(
+            const_inst_id)) {
+      if (auto lookup = context().insts().TryGetAs<SemIR::LookupImplWitness>(
+              access->witness_id)) {
+        // Canonicalization not necessary; We are working with the constant
+        // value already, and the query self in a witness is already
+        // canonicalized.
+        if (IsPeriodSelf(context(), lookup->query_self_inst_id,
+                         /*canonicalize=*/false)) {
+          // An implicit `.Self` in a member designator is always allowed.
+          return FullySubstituted;
+        }
+      }
+    }
+
+    // Canonicalization not necessary; Subst will recurse anyway, so avoid
+    // extra work for non-matches.
+    if (IsPeriodSelf(context(), const_inst_id, /*canonicalize=*/false)) {
+      *found_ = true;
+      return FullySubstituted;
+    }
+
+    return SubstOperands;
+  }
+
+  auto Rebuild(SemIR::InstId /*orig_inst_id*/, SemIR::Inst /*new_inst*/)
+      -> SemIR::InstId override {
+    CARBON_FATAL();
+  }
+
+ private:
+  bool* found_;
+};
+
+static auto ReportAmbiguousPeriodSelf(Context& context, SemIR::LocId loc_id)
+    -> void {
+  CARBON_DIAGNOSTIC(AmbiguousPeriodSelf, Error,
+                    "`.Self` is ambiguous after nested `where` in `<type> "
+                    "impls ...` clause.");
+  context.emitter().Emit(loc_id, AmbiguousPeriodSelf);
+}
+
+// Searches a type for a reference to `.Self`. Types are canonical, so they
+// only contain canonical values/inststructions, which have no location of
+// their own.
+//
+// The search excludes ImplWitnessAccess into `.Self`, which represents a
+// designator like `.X`.
+//
+// The search does not recurse into FacetTypes, as some can include valid
+// references to the top level `.Self`, or abstract `.Self` references that
+// are not replaced. FacetTypes are handled by the higher level search.
+//
+// Returns true if found, and diagnosed.
+static auto SearchTypeForPeriodSelf(Context& context, SemIR::LocId loc_id,
+                                    SemIR::TypeId type_id) -> bool {
+  bool found_canonical = false;
+  SearchCanonicalForExplicitPeriodSelf callbacks(&context, &found_canonical);
+
+  auto canonical_inst_id = context.types().GetTypeInstId(type_id);
+  SubstInst(context, canonical_inst_id, callbacks);
+
+  // The type has no locations internally, as it stores canonical
+  // instructions. If we find any `.Self` reference, we report the entire
+  // type.
+  if (found_canonical) {
+    ReportAmbiguousPeriodSelf(context, loc_id);
+    return true;
+  }
+  return false;
+}
+
+// Searches a facet type for a reference to `.Self`. FacetTypes are canonical,
+// so they only contain canonical values/inststructions, which have no
+// location of their own.
+//
+// The search excludes ImplWitnessAccess into `.Self`, which represents a
+// designator like `.X`.
+//
+// Returns true if found, and diagnosed.
+static auto SearchFacetTypeForPeriodSelf(Context& context, SemIR::LocId loc_id,
+                                         SemIR::FacetTypeId facet_type_id)
+    -> bool {
+  bool found_canonical = false;
+  SearchCanonicalForExplicitPeriodSelf callbacks(&context, &found_canonical);
+
+  const auto& info = context.facet_types().Get(facet_type_id);
+  // The LHS of a `WhereExpr` only has extend constraints.
+  for (auto extend : info.extend_constraints) {
+    auto block_id = context.specifics().GetArgsOrEmpty(extend.specific_id);
+    for (auto inst_id : context.inst_blocks().GetOrEmpty(block_id)) {
+      SubstInst(context, inst_id, callbacks);
+    }
+  }
+  for (auto extend : info.extend_named_constraints) {
+    auto block_id = context.specifics().GetArgsOrEmpty(extend.specific_id);
+    for (auto inst_id : context.inst_blocks().GetOrEmpty(block_id)) {
+      SubstInst(context, inst_id, callbacks);
+    }
+  }
+  // The facet type has no locations internally, as it stores canonical
+  // instructions. If we find any `.Self` reference, we report the entire
+  // facet type.
+  if (found_canonical) {
+    ReportAmbiguousPeriodSelf(context, loc_id);
+    return true;
+  }
+  return false;
+}
+
+// Searches a non-canonical instruction for an explicitly written use of
+// `.Self`, which is represented as a NameRef instruction.
+//
+// Returns true if found, and diagnosed.
+static auto SearchNonCanonicalInstForPeriodSelf(Context& context,
+                                                SemIR::InstId inst_id) -> bool {
+  auto found = SemIR::LocId::None;
+  SearchNonCanonicalForExplicitPeriodSelf callbacks(&context, &found);
+  SubstInst(context, inst_id, callbacks);
+  if (found.has_value()) {
+    ReportAmbiguousPeriodSelf(context, found);
+    return true;
+  }
+  return false;
+}
+
+auto FindAndDiagnoseAmbiguousPeriodSelf(Context& context,
+                                        SemIR::InstId impls_lhs_id,
+                                        SemIR::InstId impls_rhs_id) -> bool {
+  // Look for errors up front. We don't need to look for them in the rest of
+  // the function.
+  if (context.constant_values().Get(impls_lhs_id) ==
+          SemIR::ErrorInst::ConstantId ||
+      context.constant_values().Get(impls_rhs_id) ==
+          SemIR::ErrorInst::ConstantId) {
+    return false;
+  }
+
+  if (IsPeriodSelf(context, impls_lhs_id)) {
+    // `.Self impls X where ...` does not restrict any use of `.Self` on the
+    // RHS of the `where` since the `.Self` on the LHS of `where` did not
+    // introduce any ambiguity. A `.Self` on the RHS of the `where` applies to
+    // the same thing as on the LHS of the `impls`.
+    return false;
+  }
+
+  struct WorkItem {
+    SemIR::WhereExpr where_expr;
+    bool search_lhs;
+  };
+
+  llvm::SmallVector<WorkItem> work;
+  if (auto where_expr =
+          context.insts().TryGetAs<SemIR::WhereExpr>(impls_rhs_id)) {
+    work.push_back({.where_expr = *where_expr, .search_lhs = false});
+  }
+
+  while (!work.empty()) {
+    auto work_item = work.pop_back_val();
+
+    // Look in the non-canonical WhereExpr for explicit references to `.Self`,
+    // which will be considered as ambiguous.
+    for (auto inst_id : context.inst_blocks().GetOrEmpty(
+             work_item.where_expr.requirements_id)) {
+      auto inst = context.insts().Get(inst_id);
+      CARBON_KIND_SWITCH(inst) {
+        case CARBON_KIND(SemIR::RequirementBaseFacetType base): {
+          if (work_item.search_lhs) {
+            // If the base type is more than a reference to an interface or
+            // constraint, such as having specific arguments, it will be a
+            // FacetType instruction.
+            if (auto facet_type = context.insts().TryGetAs<SemIR::FacetType>(
+                    base.base_type_inst_id)) {
+              if (SearchFacetTypeForPeriodSelf(
+                      context, SemIR::LocId(base.base_type_inst_id),
+                      facet_type->facet_type_id)) {
+                return true;
+              }
+            }
+          }
+          break;
+        }
+        case CARBON_KIND(SemIR::RequirementRewrite rewrite): {
+          if (SearchNonCanonicalInstForPeriodSelf(context, rewrite.lhs_id)) {
+            return true;
+          }
+          if (SearchNonCanonicalInstForPeriodSelf(context, rewrite.rhs_id)) {
+            return true;
+          }
+          break;
+        }
+        case CARBON_KIND(SemIR::RequirementEquivalent equiv): {
+          if (SearchNonCanonicalInstForPeriodSelf(context, equiv.lhs_id)) {
+            return true;
+          }
+          if (SearchNonCanonicalInstForPeriodSelf(context, equiv.rhs_id)) {
+            return true;
+          }
+          break;
+        }
+        case CARBON_KIND(SemIR::RequirementImpls impls): {
+          if (!IsPeriodSelf(context, impls.lhs_id)) {
+            if (SearchTypeForPeriodSelf(
+                    context, SemIR::LocId(impls.lhs_id),
+                    context.types().GetTypeIdForTypeInstId(impls.lhs_id))) {
+              return true;
+            }
+          }
+
+          CARBON_KIND_SWITCH(context.insts().Get(impls.rhs_id)) {
+            case CARBON_KIND(SemIR::FacetType facet_type): {
+              // If the RHS of the `impls` is a complex facet type (such as
+              // when it has specific arguments) but has no `where`, then it
+              // will be a FacetType instruction.
+              if (SearchFacetTypeForPeriodSelf(context,
+                                               SemIR::LocId(impls.rhs_id),
+                                               facet_type.facet_type_id)) {
+                return true;
+              }
+              break;
+            }
+            case CARBON_KIND(SemIR::WhereExpr rhs_where_expr): {
+              // If the RHS of the `impls` contains a `where`, then it will be
+              // a WhereExpr instruction.
+              work.push_back(
+                  {.where_expr = rhs_where_expr, .search_lhs = true});
+              break;
+            }
+            default:
+              // Otherwise, it's a simple facet type, which is just a
+              // reference to an interface or constraint. There's nowhere to
+              // look for a
+              // `.Self`.
+              break;
+          }
+
+          break;
+        }
+        default:
+          CARBON_FATAL("unexpected inst {0} in WhereExpr requirements block",
+                       inst);
+      }
+    }
+  }
+
+  return false;
+}
+
+}  // namespace Carbon::Check

+ 95 - 0
toolchain/check/period_self.h

@@ -0,0 +1,95 @@
+// 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_PERIOD_SELF_H_
+#define CARBON_TOOLCHAIN_CHECK_PERIOD_SELF_H_
+
+#include "toolchain/check/context.h"
+#include "toolchain/check/subst.h"
+#include "toolchain/sem_ir/ids.h"
+
+namespace Carbon::Check {
+
+// Introduce `.Self` as a symbolic binding into the current scope, and return
+// the `SymbolicBinding` instruction.
+//
+// The type of `.Self` must be a `FacetType`, so that it gets wrapped in
+// `FacetAccessType` when used in a type position, such as in `U:! I(.Self)`.
+// This allows substitution with other facet values without requiring an
+// additional `FacetAccessType` to be inserted.
+auto MakePeriodSelfFacetValue(Context& context, SemIR::TypeId self_type_id)
+    -> SemIR::InstId;
+
+class SubstPeriodSelfCallbacks : public SubstInstCallbacks {
+ public:
+  explicit SubstPeriodSelfCallbacks(
+      Context* context, SemIR::LocId loc_id,
+      SemIR::ConstantId period_self_replacement_id);
+  auto Subst(SemIR::InstId& inst_id) -> SubstResult override;
+  auto Rebuild(SemIR::InstId orig_inst_id, SemIR::Inst new_inst)
+      -> SemIR::InstId override;
+
+  virtual auto ShouldReplace(bool /*implicit*/) -> bool { return true; }
+
+  auto loc_id() const -> SemIR::LocId { return loc_id_; }
+  auto period_self_replacement_id() const -> SemIR::ConstantId {
+    return period_self_replacement_id_;
+  }
+
+ private:
+  auto GetReplacement(SemIR::InstId period_self, bool implicit)
+      -> SemIR::InstId;
+  auto ConvertReplacement(SemIR::InstId replacement_self_inst_id,
+                          SemIR::TypeId replacement_type_id,
+                          SemIR::TypeId period_self_type_id) -> SemIR::InstId;
+
+  SemIR::LocId loc_id_;
+  SemIR::ConstantId period_self_replacement_id_;
+
+  // The last output of GetReplacement().
+  SemIR::InstId cached_replacement_id_ = SemIR::InstId::None;
+  // The type of the last output of GetReplacement(). If the type of `.Self`
+  // matches, we can reuse the `cached_replacement_id_`.
+  SemIR::TypeId cached_replacement_type_id_ = SemIR::TypeId::None;
+};
+
+// Replace all `.Self` references in `const_id`. The `callbacks` specifies the
+// facet to replace them with.
+auto SubstPeriodSelf(Context& context, SubstPeriodSelfCallbacks& callbacks,
+                     SemIR::ConstantId const_id) -> SemIR::ConstantId;
+
+// Replace all `.Self` references in the specific of the interface or named
+// constraint. The `callbacks` specifies the facet to replace them with.
+auto SubstPeriodSelf(Context& context, SubstPeriodSelfCallbacks& callbacks,
+                     SemIR::SpecificInterface interface)
+    -> SemIR::SpecificInterface;
+auto SubstPeriodSelf(Context& context, SubstPeriodSelfCallbacks& callbacks,
+                     SemIR::SpecificNamedConstraint constraint)
+    -> SemIR::SpecificNamedConstraint;
+
+// Returns whether the constant value of `inst_id` is a reference to `.Self`.
+//
+// If `canonicalize` is true, look at the constant value of `inst_id` and get
+// the canonicalized facet or type to look through FacetAccessType.
+auto IsPeriodSelf(Context& context, SemIR::InstId inst_id,
+                  bool canonicalize = true) -> bool;
+
+// Look for ambiguous `.Self` in a `T impls X where ...` statement. The given
+// inst ids are the non-canonical insts for the LHS and RHS of the `impls`
+// inside a `where` expression.
+//
+// If the LHS is not `.Self` and RHS contains a nested `where` expression, the
+// value of `.Self` becomes ambiguous on the RHS of the `where` (it could mean
+// either the original value or new value given by the LHS of the `impls`). Note
+// that implicit `.Self` references are never ambiguous, they always refer to
+// the innermost value that `.Self` could refer to.
+//
+// Returns true if an error was diagnosed.
+auto FindAndDiagnoseAmbiguousPeriodSelf(Context& context,
+                                        SemIR::InstId impls_lhs_id,
+                                        SemIR::InstId impls_rhs_id) -> bool;
+
+}  // namespace Carbon::Check
+
+#endif  // CARBON_TOOLCHAIN_CHECK_PERIOD_SELF_H_

+ 2 - 2
toolchain/check/testdata/deduce/binding_pattern.carbon

@@ -351,8 +351,8 @@ fn F(unused U:! type, V:! type where {} impls Core.ImplicitAs(.Self)) {
 // CHECK:STDOUT:       %.loc9_68: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:       %ImplicitAs.type.loc9: type = facet_type <@ImplicitAs, @ImplicitAs(constants.%.Self.as_type)> [symbolic_self = constants.%ImplicitAs.type.9fd]
 // CHECK:STDOUT:       %.loc9_39.2: type = converted %.loc9_39.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:       %.loc9_32.2: type = where_expr %.Self.2 [symbolic_self = constants.%type_where] {
-// CHECK:STDOUT:         requirement_base_facet_type type
+// CHECK:STDOUT:       %.loc9_32.2: type = where_expr [symbolic_self = constants.%type_where] {
+// CHECK:STDOUT:         requirement_base_facet_type %.loc9_27
 // CHECK:STDOUT:         requirement_impls %.loc9_39.2, %ImplicitAs.type.loc9
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }

+ 6 - 6
toolchain/check/testdata/facet/access.carbon

@@ -671,8 +671,8 @@ fn F2(U:! Z) {
 // CHECK:STDOUT:       %impl.elem0.loc6_19: type = impl_witness_access constants.%A.lookup_impl_witness.6a5, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:       %.loc6_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:       %.loc6_25.2: type = converted %.loc6_25.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:       %.loc6_13.2: type = where_expr %.Self.2 [concrete = constants.%A_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%A.type
+// CHECK:STDOUT:       %.loc6_13.2: type = where_expr [concrete = constants.%A_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %A.ref
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc6_19, %.loc6_25.2
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -820,8 +820,8 @@ fn F2(U:! Z) {
 // CHECK:STDOUT:       %impl.elem0.loc14_35: type = impl_witness_access constants.%B.lookup_impl_witness.d4f, element0 [symbolic_self = constants.%impl.elem0.11d]
 // CHECK:STDOUT:       %.loc14_41.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:       %.loc14_41.2: type = converted %.loc14_41.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:       %.loc14_17.2: type = where_expr %.Self.2 [concrete = constants.%facet_type.82c] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%facet_type.9bb
+// CHECK:STDOUT:       %.loc14_17.2: type = where_expr [concrete = constants.%facet_type.82c] {
+// CHECK:STDOUT:         requirement_base_facet_type %type.as.BitAndWith.impl.Op.call
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc14_23, %.loc14_29.2
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc14_35, %.loc14_41.2
 // CHECK:STDOUT:       }
@@ -865,8 +865,8 @@ fn F2(U:! Z) {
 // CHECK:STDOUT:       %impl.elem0.loc18_35: type = impl_witness_access constants.%B.lookup_impl_witness.d4f, element0 [symbolic_self = constants.%impl.elem0.11d]
 // CHECK:STDOUT:       %.loc18_41.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:       %.loc18_41.2: type = converted %.loc18_41.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:       %.loc18_17.2: type = where_expr %.Self.2 [concrete = constants.%facet_type.82c] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%facet_type.9bb
+// CHECK:STDOUT:       %.loc18_17.2: type = where_expr [concrete = constants.%facet_type.82c] {
+// CHECK:STDOUT:         requirement_base_facet_type %type.as.BitAndWith.impl.Op.call
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc18_23, %.loc18_29.2
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc18_35, %.loc18_41.2
 // CHECK:STDOUT:       }

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

@@ -869,8 +869,8 @@ fn CallsWithTypeExplicit(U:! type) {
 // CHECK:STDOUT:       %.loc9_43: type = type_literal type [concrete = type]
 // CHECK:STDOUT:       %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:       %.loc9_31: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
-// CHECK:STDOUT:       %.loc9_25.2: type = where_expr %.Self.2 [concrete = constants.%A.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%A.type
+// CHECK:STDOUT:       %.loc9_25.2: type = where_expr [concrete = constants.%A.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %A.ref
 // CHECK:STDOUT:         requirement_impls %.loc9_31, %.loc9_43
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -1027,8 +1027,8 @@ fn CallsWithTypeExplicit(U:! type) {
 // CHECK:STDOUT:       %.loc4_51: type = type_literal type [concrete = type]
 // CHECK:STDOUT:       %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:       %.loc4_39: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
-// CHECK:STDOUT:       %.loc4_33.2: type = where_expr %.Self.2 [concrete = constants.%type] {
-// CHECK:STDOUT:         requirement_base_facet_type type
+// CHECK:STDOUT:       %.loc4_33.2: type = where_expr [concrete = constants.%type] {
+// CHECK:STDOUT:         requirement_base_facet_type %.loc4_28
 // CHECK:STDOUT:         requirement_impls %.loc4_39, %.loc4_51
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -1061,8 +1061,8 @@ fn CallsWithTypeExplicit(U:! type) {
 // CHECK:STDOUT:       %.loc9_59: type = type_literal type [concrete = type]
 // CHECK:STDOUT:       %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:       %.loc9_47: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
-// CHECK:STDOUT:       %.loc9_41.2: type = where_expr %.Self.2 [concrete = constants.%type] {
-// CHECK:STDOUT:         requirement_base_facet_type type
+// CHECK:STDOUT:       %.loc9_41.2: type = where_expr [concrete = constants.%type] {
+// CHECK:STDOUT:         requirement_base_facet_type %.loc9_36
 // CHECK:STDOUT:         requirement_impls %.loc9_47, %.loc9_59
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -1227,8 +1227,8 @@ fn CallsWithTypeExplicit(U:! type) {
 // CHECK:STDOUT:       %.loc3_54: type = type_literal type [concrete = type]
 // CHECK:STDOUT:       %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:       %.loc3_42: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
-// CHECK:STDOUT:       %.loc3_36.2: type = where_expr %.Self.2 [concrete = constants.%type] {
-// CHECK:STDOUT:         requirement_base_facet_type type
+// CHECK:STDOUT:       %.loc3_36.2: type = where_expr [concrete = constants.%type] {
+// CHECK:STDOUT:         requirement_base_facet_type %.loc3_31
 // CHECK:STDOUT:         requirement_impls %.loc3_42, %.loc3_54
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -1266,8 +1266,8 @@ fn CallsWithTypeExplicit(U:! type) {
 // CHECK:STDOUT:       %.loc8_62: type = type_literal type [concrete = type]
 // CHECK:STDOUT:       %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:       %.loc8_50: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
-// CHECK:STDOUT:       %.loc8_44.2: type = where_expr %.Self.2 [concrete = constants.%type] {
-// CHECK:STDOUT:         requirement_base_facet_type type
+// CHECK:STDOUT:       %.loc8_44.2: type = where_expr [concrete = constants.%type] {
+// CHECK:STDOUT:         requirement_base_facet_type %.loc8_39
 // CHECK:STDOUT:         requirement_impls %.loc8_50, %.loc8_62
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }

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

@@ -695,8 +695,8 @@ fn F(unused T:! I & J where .I1 = .J1.I2) {}
 // CHECK:STDOUT:       %impl.elem2: type = impl_witness_access constants.%M.lookup_impl_witness, element2 [symbolic_self = constants.%impl.elem2]
 // CHECK:STDOUT:       %.loc13_55.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:       %.loc13_55.2: type = converted %.loc13_55.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:       %.loc13_19.2: type = where_expr %.Self.2 [concrete = <error>] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%M.type
+// CHECK:STDOUT:       %.loc13_19.2: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:         requirement_base_facet_type %M.ref
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc13_25, %impl.elem1.loc13_30
 // CHECK:STDOUT:         requirement_rewrite %impl.elem1.loc13_37, %impl.elem0.subst
 // CHECK:STDOUT:         requirement_rewrite %impl.elem2, %.loc13_55.2

+ 19 - 28
toolchain/check/testdata/facet/period_self.carbon

@@ -356,24 +356,11 @@ fn E(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where .Y1 = .Y2)) {}
 //                ^T as type     ^T as Z(T)      ^T as Z(T)   ^R(T as Z(T)) as Y(T as Z(T))
 //                                                                  ^R(T as Z(T)) as Y(T as Z(T))
 
-// --- fail_todo_period_self_impls_ambiguous_period_self_access_argument.carbon
-library "[[@TEST_NAME]]";
-
-interface Z(T:! type) {}
-interface Y(T:! type) {
-  let Y1:! type;
-}
-interface X(T:! type) {}
-
-class R(T:! type);
-
-// CHECK:STDERR: fail_todo_period_self_impls_ambiguous_period_self_access_argument.carbon:[[@LINE+4]]:32: error: `.Self` is ambiguous after nested `where` in `<type> impls ...` clause. [AmbiguousPeriodSelf]
-// CHECK:STDERR: fn C(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where .Self impls X(.Y1))) {}
-// CHECK:STDERR:                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// CHECK:STDERR:
-fn C(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where .Self impls X(.Y1))) {}
+// Member designators have an implicit `.Self` which is always allowed. It binds
+// to the innermost facet value rather than being ambiguous.
+fn F(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where .Self impls X(.Y1))) {}
 //                ^T as type     ^T as Z(T)      ^T as Z(T)   ^R(T as Z(T)) as Y(T as Z(T))
-//                                                                          ^ERROR: R(T as Z(T)) as Y(T as Z(T))
+//                                                                          ^Implicit: R(T as Z(T)) as Y(T as Z(T))
 
 // --- fail_type_impls_ambiguous_period_self_argument.carbon
 library "[[@TEST_NAME]]";
@@ -387,9 +374,9 @@ class P;
 class Q(T:! type);
 class R(T:! type);
 
-// CHECK:STDERR: fail_type_impls_ambiguous_period_self_argument.carbon:[[@LINE+4]]:32: error: `.Self` is ambiguous after nested `where` in `<type> impls ...` clause. [AmbiguousPeriodSelf]
+// CHECK:STDERR: fail_type_impls_ambiguous_period_self_argument.carbon:[[@LINE+4]]:71: error: `.Self` is ambiguous after nested `where` in `<type> impls ...` clause. [AmbiguousPeriodSelf]
 // CHECK:STDERR: fn A(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where P impls X(.Self))) {}
-// CHECK:STDERR:                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:                                                                       ^~~~~~~~
 // CHECK:STDERR:
 fn A(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where P impls X(.Self))) {}
 //                ^T as type     ^T as Z(T)      ^T as Z(T)             ^ERROR: R(T as Z(T)) as Y(T as Z(T))
@@ -404,9 +391,9 @@ interface X {}
 class Q(T:! type);
 class R(T:! type);
 
-// CHECK:STDERR: fail_ambiguous_period_self_argument_impls.carbon:[[@LINE+4]]:32: error: `.Self` is ambiguous after nested `where` in `<type> impls ...` clause. [AmbiguousPeriodSelf]
+// CHECK:STDERR: fail_ambiguous_period_self_argument_impls.carbon:[[@LINE+4]]:63: error: `.Self` is ambiguous after nested `where` in `<type> impls ...` clause. [AmbiguousPeriodSelf]
 // CHECK:STDERR: fn B(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where Q(.Self) impls X)) {}
-// CHECK:STDERR:                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:                                                               ^~~~~~~~
 // CHECK:STDERR:
 fn B(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where Q(.Self) impls X)) {}
 //                ^T as type     ^T as Z(T)      ^T as Z(T)     ^ERROR: R(T as Z(T)) as Y(T as Z(T))
@@ -420,15 +407,15 @@ interface X(T:! type) {}
 
 class R(T:! type);
 
-// CHECK:STDERR: fail_period_self_impls_ambiguous_period_self_argument.carbon:[[@LINE+4]]:32: error: `.Self` is ambiguous after nested `where` in `<type> impls ...` clause. [AmbiguousPeriodSelf]
+// CHECK:STDERR: fail_period_self_impls_ambiguous_period_self_argument.carbon:[[@LINE+4]]:75: error: `.Self` is ambiguous after nested `where` in `<type> impls ...` clause. [AmbiguousPeriodSelf]
 // CHECK:STDERR: fn C(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where .Self impls X(.Self))) {}
-// CHECK:STDERR:                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:                                                                           ^~~~~~~~
 // CHECK:STDERR:
 fn C(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where .Self impls X(.Self))) {}
 //                ^T as type     ^T as Z(T)      ^T as Z(T)   ^R(T as Z(T)) as Y(T as Z(T))
 //                                                                          ^ERROR: R(T as Z(T)) as Y(T as Z(T))
 
-// --- todo_fail_rewrite_rhs_ambiguous_period_self.carbon
+// --- fail_rewrite_rhs_ambiguous_period_self.carbon
 library "[[@TEST_NAME]]";
 
 interface Z(T:! type) {}
@@ -438,6 +425,10 @@ interface Y(T:! type) {
 
 class R(T:! type);
 
+// CHECK:STDERR: fail_rewrite_rhs_ambiguous_period_self.carbon:[[@LINE+4]]:69: error: `.Self` is ambiguous after nested `where` in `<type> impls ...` clause. [AmbiguousPeriodSelf]
+// CHECK:STDERR: fn D(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where .Y1 = .Self)) {}
+// CHECK:STDERR:                                                                     ^~~~~
+// CHECK:STDERR:
 fn D(unused T:! Z(.Self) where R(.Self) impls (Y(.Self) where .Y1 = .Self)) {}
 //                ^T as type     ^T as Z(T)      ^T as Z(T)   ^R(T as Z(T)) as Y(T as Z(T))
 //                                                                  ^ERROR: R(T as Z(T)) as Y(T as Z(T))
@@ -557,8 +548,8 @@ fn F() {
 // CHECK:STDOUT:       %impl.elem0.loc8_25: type = impl_witness_access constants.%I.lookup_impl_witness.42f, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:       %.loc8_32.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:       %.loc8_32.2: type = converted %.loc8_32.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:       %.loc8_19.2: type = where_expr %.Self.2 [symbolic_self = constants.%I_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type.6e7
+// CHECK:STDOUT:       %.loc8_19.2: type = where_expr [symbolic_self = constants.%I_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %I.type
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc8_25, %.loc8_32.2
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -598,8 +589,8 @@ fn F() {
 // CHECK:STDOUT:       %impl.elem0.loc12_33: type = impl_witness_access constants.%I.lookup_impl_witness.42f, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:       %.loc12_40.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:       %.loc12_40.2: type = converted %.loc12_40.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:       %.loc12_27.2: type = where_expr %.Self.2 [symbolic_self = constants.%I_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type.6e7
+// CHECK:STDOUT:       %.loc12_27.2: type = where_expr [symbolic_self = constants.%I_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %I.type
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc12_33, %.loc12_40.2
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }

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

@@ -88,8 +88,8 @@ fn G(_:! I(.Self) where .I1 = ()) {}
 // CHECK:STDOUT:       %impl.elem0.loc18_25: type = impl_witness_access constants.%I.lookup_impl_witness.42f, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:       %.loc18_32.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:       %.loc18_32.2: type = converted %.loc18_32.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:       %.loc18_19.2: type = where_expr %.Self.2 [symbolic_self = constants.%I_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type.6e7
+// CHECK:STDOUT:       %.loc18_19.2: type = where_expr [symbolic_self = constants.%I_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %I.type
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc18_25, %.loc18_32.2
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }

+ 2 - 2
toolchain/check/testdata/for/actual.carbon

@@ -450,8 +450,8 @@ fn Read(y:! Core.IntLiteral()) {
 // CHECK:STDOUT:       %Int.loc9_85: type = class_type @Int, @Int(constants.%N) [symbolic = %Int.loc9_54.1 (constants.%Int.fc6021.1)]
 // CHECK:STDOUT:       %facet_value.loc9_85.2: %facet_type.7e2 = facet_value %Int.loc9_85, (constants.%Destroy.lookup_impl_witness.93c, constants.%Copy.lookup_impl_witness.7a8) [symbolic = %facet_value.loc9_85.1 (constants.%facet_value)]
 // CHECK:STDOUT:       %.loc9_85.2: %facet_type.7e2 = converted %Int.loc9_85, %facet_value.loc9_85.2 [symbolic = %facet_value.loc9_85.1 (constants.%facet_value)]
-// CHECK:STDOUT:       %.loc9_24: type = where_expr %.Self [symbolic = %Iterate_where.type (constants.%Iterate_where.type)] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%Iterate.type
+// CHECK:STDOUT:       %.loc9_24: type = where_expr [symbolic = %Iterate_where.type (constants.%Iterate_where.type)] {
+// CHECK:STDOUT:         requirement_base_facet_type %Iterate.ref
 // CHECK:STDOUT:         requirement_rewrite %impl.elem1, %Int.loc9_54.2
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0, %.loc9_85.2
 // CHECK:STDOUT:       }

+ 4 - 4
toolchain/check/testdata/generic/dot_self_symbolic_type.carbon

@@ -139,8 +139,8 @@ fn H(T:! type) {
 // CHECK:STDOUT:         %X.ref: @C.F.%A.assoc_type (%A.assoc_type.9f4820.2) = name_ref X, %.loc11_31.2 [symbolic = %assoc0 (constants.%assoc0.9fa860.2)]
 // CHECK:STDOUT:         %impl.elem0.loc11_31.2: type = impl_witness_access constants.%A.lookup_impl_witness.04abbb.1, element0 [symbolic = %impl.elem0.loc11_31.1 (constants.%impl.elem0.f51d29.1)]
 // CHECK:STDOUT:         %CC.ref.loc11_36: type = name_ref CC, @C.%CC.loc6_11.2 [symbolic = %CC (constants.%CC)]
-// CHECK:STDOUT:         %.loc11_25.2: type = where_expr %.Self.3 [symbolic = %A_where.type (constants.%A_where.type.4028e0.1)] {
-// CHECK:STDOUT:           requirement_base_facet_type constants.%A.type.ade3d9.2
+// CHECK:STDOUT:         %.loc11_25.2: type = where_expr [symbolic = %A_where.type (constants.%A_where.type.4028e0.1)] {
+// CHECK:STDOUT:           requirement_base_facet_type %A.type.loc11_23.2
 // CHECK:STDOUT:           requirement_rewrite %impl.elem0.loc11_31.2, %CC.ref.loc11_36
 // CHECK:STDOUT:         }
 // CHECK:STDOUT:       }
@@ -368,8 +368,8 @@ fn H(T:! type) {
 // CHECK:STDOUT:       %impl.elem0.loc9_42.1: type = impl_witness_access constants.%A.lookup_impl_witness.04abbb.1, element0 [symbolic = %impl.elem0.loc9_42.2 (constants.%impl.elem0.f51d29.1)]
 // CHECK:STDOUT:       %.loc9_48.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:       %.loc9_48.2: type = converted %.loc9_48.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:       %.loc9_36.2: type = where_expr %.Self.2 [symbolic = %A_where.type (constants.%A_where.type.29f165.1)] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%A.type.ade3d9.1
+// CHECK:STDOUT:       %.loc9_36.2: type = where_expr [symbolic = %A_where.type (constants.%A_where.type.29f165.1)] {
+// CHECK:STDOUT:         requirement_base_facet_type %A.type.loc9_34.1
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc9_42.1, %.loc9_48.2
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }

+ 12 - 12
toolchain/check/testdata/impl/assoc_const_self.carbon

@@ -179,8 +179,8 @@ fn CallF() {
 // CHECK:STDOUT:     %.loc8_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:     %empty_struct: %empty_struct_type = struct_value () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:     %.loc8_26.2: %empty_struct_type = converted %.loc8_26.1, %empty_struct [concrete = constants.%empty_struct]
-// CHECK:STDOUT:     %.loc8_14: type = where_expr %.Self [concrete = constants.%I_where.type.2d8] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc8_14: type = where_expr [concrete = constants.%I_where.type.2d8] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc8_26.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -194,8 +194,8 @@ fn CallF() {
 // CHECK:STDOUT:     %V.ref: %I.assoc_type = name_ref V, @V.%assoc0 [concrete = constants.%assoc0.f13]
 // CHECK:STDOUT:     %impl.elem0.loc10_21: %.Self.as_type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
-// CHECK:STDOUT:     %.loc10_15.1: type = where_expr %.Self [concrete = constants.%I_where.type.1f4] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc10_15.1: type = where_expr [concrete = constants.%I_where.type.1f4] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc10_21, %int_0
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -330,8 +330,8 @@ fn CallF() {
 // CHECK:STDOUT:     %V.ref: %I.assoc_type = name_ref V, @V.%assoc0 [concrete = constants.%assoc0.f13]
 // CHECK:STDOUT:     %impl.elem0: %.Self.as_type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]
-// CHECK:STDOUT:     %.loc15_14.1: type = where_expr %.Self [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc15_14.1: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %int_0
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -465,8 +465,8 @@ fn CallF() {
 // CHECK:STDOUT:     %.loc18_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %empty_tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc18_25.2: %empty_tuple.type = converted %.loc18_25.1, %empty_tuple [concrete = constants.%empty_tuple]
-// CHECK:STDOUT:     %.loc18_13.1: type = where_expr %.Self [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc18_13.1: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc18_19, %.loc18_25.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -661,8 +661,8 @@ fn CallF() {
 // CHECK:STDOUT:     %.loc15_24: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:     %V.ref: <error> = name_ref V, <error> [concrete = <error>]
 // CHECK:STDOUT:     %.loc15_30: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
-// CHECK:STDOUT:     %.loc15_18: type = where_expr %.Self [concrete = <error>] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type.54b
+// CHECK:STDOUT:     %.loc15_18: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.type
 // CHECK:STDOUT:       requirement_rewrite %V.ref, <error>
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -794,8 +794,8 @@ fn CallF() {
 // CHECK:STDOUT:       %.loc8_60.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:       %empty_struct: %empty_struct_type = struct_value () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:       %.loc8_60.2: %empty_struct_type = converted %.loc8_60.1, %empty_struct [concrete = constants.%empty_struct]
-// CHECK:STDOUT:       %.loc8_12.2: type = where_expr %.Self.2 [symbolic_self = constants.%I_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:       %.loc8_12.2: type = where_expr [symbolic_self = constants.%I_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %I.ref
 // CHECK:STDOUT:         requirement_impls %.loc8_19.2, %ImplicitAs.type
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0, %.loc8_60.2
 // CHECK:STDOUT:       }

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

@@ -163,8 +163,8 @@ impl {.a: bool} as type where .Self impls I {}
 // CHECK:STDOUT:     %.loc8_36: type = type_literal type [concrete = type]
 // CHECK:STDOUT:     %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:     %.loc8_24: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
-// CHECK:STDOUT:     %.loc8_18: type = where_expr %.Self [concrete = constants.%type] {
-// CHECK:STDOUT:       requirement_base_facet_type type
+// CHECK:STDOUT:     %.loc8_18: type = where_expr [concrete = constants.%type] {
+// CHECK:STDOUT:       requirement_base_facet_type %.loc8_13
 // CHECK:STDOUT:       requirement_impls %.loc8_24, %.loc8_36
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -214,8 +214,8 @@ impl {.a: bool} as type where .Self impls I {}
 // CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
 // CHECK:STDOUT:     %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:     %.loc10_31: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
-// CHECK:STDOUT:     %.loc10_25: type = where_expr %.Self [concrete = constants.%type_where] {
-// CHECK:STDOUT:       requirement_base_facet_type type
+// CHECK:STDOUT:     %.loc10_25: type = where_expr [concrete = constants.%type_where] {
+// CHECK:STDOUT:       requirement_base_facet_type %.loc10_20
 // CHECK:STDOUT:       requirement_impls %.loc10_31, %I.ref
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }

+ 28 - 28
toolchain/check/testdata/impl/forward_decls.carbon

@@ -580,8 +580,8 @@ interface I {
 // CHECK:STDOUT:     %impl.elem0.loc6: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc6_26.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc6_26.2: type = converted %.loc6_26.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc6_14: type = where_expr %.Self.2 [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc6_14: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref.loc6
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc6, %.loc6_26.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -597,8 +597,8 @@ interface I {
 // CHECK:STDOUT:     %impl.elem0.loc8: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc8_26.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc8_26.2: type = converted %.loc8_26.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc8_14: type = where_expr %.Self.1 [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc8_14: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref.loc8
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc8, %.loc8_26.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -692,8 +692,8 @@ interface I {
 // CHECK:STDOUT:     %impl.elem0.loc7: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc7_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc7_25.2: type = converted %.loc7_25.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc7_13: type = where_expr %.Self.2 [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc7_13: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref.loc7
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc7, %.loc7_25.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -722,8 +722,8 @@ interface I {
 // CHECK:STDOUT:     %impl.elem0.loc11: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc11_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc11_25.2: type = converted %.loc11_25.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc11_13: type = where_expr %.Self.1 [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc11_13: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref.loc11
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc11, %.loc11_25.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -831,8 +831,8 @@ interface I {
 // CHECK:STDOUT:     %impl.elem0.loc7: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc7_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc7_25.2: type = converted %.loc7_25.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc7_13: type = where_expr %.Self.2 [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc7_13: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref.loc7
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc7, %.loc7_25.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -863,8 +863,8 @@ interface I {
 // CHECK:STDOUT:     %impl.elem0.loc11: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc11_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc11_25.2: type = converted %.loc11_25.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc11_13: type = where_expr %.Self.1 [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc11_13: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref.loc11
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc11, %.loc11_25.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -1066,8 +1066,8 @@ interface I {
 // CHECK:STDOUT:     %.loc13_19: type = converted %.Self.ref.loc13, %.Self.as_type.loc13 [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:     %T.ref.loc13: <error> = name_ref T, <error> [concrete = <error>]
 // CHECK:STDOUT:     %C.ref.loc13: type = name_ref C, file.%C.decl.loc4 [concrete = constants.%C]
-// CHECK:STDOUT:     %.loc13_13: type = where_expr %.Self.2 [concrete = <error>] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc13_13: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref.loc13
 // CHECK:STDOUT:       requirement_rewrite %T.ref.loc13, <error>
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -1082,8 +1082,8 @@ interface I {
 // CHECK:STDOUT:     %.loc21_19: type = converted %.Self.ref.loc21, %.Self.as_type.loc21 [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:     %T.ref.loc21: <error> = name_ref T, <error> [concrete = <error>]
 // CHECK:STDOUT:     %C.ref.loc21: type = name_ref C, file.%C.decl.loc4 [concrete = constants.%C]
-// CHECK:STDOUT:     %.loc21_13: type = where_expr %.Self.1 [concrete = <error>] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc21_13: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref.loc21
 // CHECK:STDOUT:       requirement_rewrite %T.ref.loc21, <error>
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -1199,8 +1199,8 @@ interface I {
 // CHECK:STDOUT:     %T.ref.loc8: %I.assoc_type.2e0 = name_ref T, %.loc8_22.2 [concrete = constants.%assoc0.501]
 // CHECK:STDOUT:     %impl.elem0.loc8: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %C.ref.loc8_27: type = name_ref C, file.%C.decl.loc6 [concrete = constants.%C]
-// CHECK:STDOUT:     %.loc8_16: type = where_expr %.Self.2 [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type.807
+// CHECK:STDOUT:     %.loc8_16: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.type.loc8
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc8, %C.ref.loc8_27
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -1218,8 +1218,8 @@ interface I {
 // CHECK:STDOUT:     %T.ref.loc11: %I.assoc_type.2e0 = name_ref T, %.loc11_22.2 [concrete = constants.%assoc0.501]
 // CHECK:STDOUT:     %impl.elem0.loc11: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %C.ref.loc11_27: type = name_ref C, file.%C.decl.loc6 [concrete = constants.%C]
-// CHECK:STDOUT:     %.loc11_16: type = where_expr %.Self.1 [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type.807
+// CHECK:STDOUT:     %.loc11_16: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.type.loc11
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc11, %C.ref.loc11_27
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -1606,8 +1606,8 @@ interface I {
 // CHECK:STDOUT:     %impl.elem0.loc9: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc9_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc9_25.2: type = converted %.loc9_25.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc9_13: type = where_expr %.Self.2 [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc9_13: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref.loc9
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc9, %.loc9_25.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -1622,8 +1622,8 @@ interface I {
 // CHECK:STDOUT:     %impl.elem0.loc18: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc18_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc18_25.2: type = converted %.loc18_25.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc18_13: type = where_expr %.Self.1 [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc18_13: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref.loc18
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc18, %.loc18_25.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -2186,8 +2186,8 @@ interface I {
 // CHECK:STDOUT:       %U.ref.loc12: %I.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0]
 // CHECK:STDOUT:       %impl.elem0.loc12: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:       %C.ref.loc12_28: type = name_ref C, @I.WithSelf.F.%C.decl [symbolic = %C (constants.%C)]
-// CHECK:STDOUT:       %.loc12_17: type = where_expr %.Self.2 [symbolic = %I_where.type (constants.%I_where.type)] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:       %.loc12_17: type = where_expr [symbolic = %I_where.type (constants.%I_where.type)] {
+// CHECK:STDOUT:         requirement_base_facet_type %I.ref.loc12
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc12, %C.ref.loc12_28
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -2201,8 +2201,8 @@ interface I {
 // CHECK:STDOUT:       %U.ref.loc21: %I.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0]
 // CHECK:STDOUT:       %impl.elem0.loc21: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:       %C.ref.loc21_28: type = name_ref C, @I.WithSelf.F.%C.decl [symbolic = %C (constants.%C)]
-// CHECK:STDOUT:       %.loc21_17: type = where_expr %.Self.1 [symbolic = %I_where.type (constants.%I_where.type)] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:       %.loc21_17: type = where_expr [symbolic = %I_where.type (constants.%I_where.type)] {
+// CHECK:STDOUT:         requirement_base_facet_type %I.ref.loc21
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc21, %C.ref.loc21_28
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }

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

@@ -482,8 +482,8 @@ fn G() {
 // CHECK:STDOUT:     %.loc13_102.3: type = converted constants.%empty_tuple, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
 // CHECK:STDOUT:     %.loc13_102.4: type = converted constants.%empty_struct, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
 // CHECK:STDOUT:     %.loc13_102.5: type = converted %.loc13_102.1, constants.%tuple.type.bd8 [concrete = constants.%tuple.type.bd8]
-// CHECK:STDOUT:     %.loc13_14: type = where_expr %.Self [concrete = <error>] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%L.type
+// CHECK:STDOUT:     %.loc13_14: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type %L.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc13_20, %.loc13_36.5
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.subst.loc13_42, %.loc13_58.5
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.subst.loc13_64, %.loc13_80.5
@@ -549,8 +549,8 @@ fn G() {
 // CHECK:STDOUT:     %impl.elem2: type = impl_witness_access constants.%M.lookup_impl_witness, element2 [symbolic_self = constants.%impl.elem2]
 // CHECK:STDOUT:     %.loc13_50.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc13_50.2: type = converted %.loc13_50.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc13_14: type = where_expr %.Self [concrete = <error>] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%M.type
+// CHECK:STDOUT:     %.loc13_14: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type %M.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc13_20, %impl.elem1.loc13_25
 // CHECK:STDOUT:       requirement_rewrite %impl.elem1.loc13_32, %impl.elem0.subst
 // CHECK:STDOUT:       requirement_rewrite %impl.elem2, %.loc13_50.2

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

@@ -216,8 +216,8 @@ impl () as I where .X = {.a = true, .b = (1, 2)} and .X = {.a = false, .b = (3,
 // CHECK:STDOUT:     %.loc6_95.2: %tuple.type.d07 = converted %.loc6_94.1, %tuple.loc6_94 [concrete = constants.%tuple.21c]
 // CHECK:STDOUT:     %struct.loc6_95: %struct_type.a.b.fe2 = struct_value (%.loc6_65, %.loc6_95.2) [concrete = constants.%struct.682]
 // CHECK:STDOUT:     %.loc6_95.3: %struct_type.a.b.fe2 = converted %.loc6_95.1, %struct.loc6_95 [concrete = constants.%struct.682]
-// CHECK:STDOUT:     %.loc6_14: type = where_expr %.Self [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc6_14: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc6_20, %.loc6_48.3
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.subst, %.loc6_95.3
 // CHECK:STDOUT:     }
@@ -410,8 +410,8 @@ impl () as I where .X = {.a = true, .b = (1, 2)} and .X = {.a = false, .b = (3,
 // CHECK:STDOUT:     %.loc10_83.2: %tuple.type.d07 = converted %.loc10_82.1, %tuple.loc10_82 [concrete = constants.%tuple.ffd]
 // CHECK:STDOUT:     %struct.loc10_83: %struct_type.a.b.fe2 = struct_value (%false, %.loc10_83.2) [concrete = constants.%struct.68c]
 // CHECK:STDOUT:     %.loc10_83.3: %struct_type.a.b.fe2 = converted %.loc10_83.1, %struct.loc10_83 [concrete = constants.%struct.68c]
-// CHECK:STDOUT:     %.loc10_14: type = where_expr %.Self [concrete = <error>] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc10_14: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc10_20, %.loc10_48.3
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.subst, %.loc10_83.3
 // CHECK:STDOUT:     }

+ 32 - 32
toolchain/check/testdata/impl/import_interface_assoc_const.carbon

@@ -350,8 +350,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc5_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:     %.loc5_26.2: type = converted %.loc5_26.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:     %.loc5_14: type = where_expr %.Self [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc5_14: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc5_26.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -446,8 +446,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %impl.elem0.loc5: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc5_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:     %.loc5_26.2: type = converted %.loc5_26.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:     %.loc5_14: type = where_expr %.Self.2 [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc5_14: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref.loc5
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc5, %.loc5_26.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -462,8 +462,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %impl.elem0.loc6: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc6_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:     %.loc6_26.2: type = converted %.loc6_26.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:     %.loc6_14: type = where_expr %.Self.1 [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc6_14: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref.loc6
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc6, %.loc6_26.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -562,8 +562,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc10_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:     %.loc10_26.2: type = converted %.loc10_26.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:     %.loc10_14: type = where_expr %.Self [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc10_14: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc10_26.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -663,8 +663,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc9_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:     %.loc9_26.2: type = converted %.loc9_26.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:     %.loc9_14: type = where_expr %.Self [concrete = constants.%I_where.type.1c0] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc9_14: type = where_expr [concrete = constants.%I_where.type.1c0] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc9_26.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -679,8 +679,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc10_26.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc10_26.2: type = converted %.loc10_26.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc10_14: type = where_expr %.Self [concrete = constants.%I_where.type.0f9] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc10_14: type = where_expr [concrete = constants.%I_where.type.0f9] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc10_26.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -805,8 +805,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %T3.ref: %I3.assoc_type = name_ref T3, imports.%Main.import_ref.4cd [concrete = constants.%assoc2]
 // CHECK:STDOUT:     %impl.elem2: type = impl_witness_access constants.%I3.lookup_impl_witness, element2 [symbolic_self = constants.%impl.elem2]
 // CHECK:STDOUT:     %BAD2.ref: <error> = name_ref BAD2, <error> [concrete = <error>]
-// CHECK:STDOUT:     %.loc17_15: type = where_expr %.Self [concrete = <error>] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I3.type
+// CHECK:STDOUT:     %.loc17_15: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type %I3.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, <error>
 // CHECK:STDOUT:       requirement_rewrite %impl.elem1, %struct_type.a
 // CHECK:STDOUT:       requirement_rewrite %impl.elem2, <error>
@@ -836,8 +836,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %T3.ref: %I3.assoc_type = name_ref T3, imports.%Main.import_ref.4cd [concrete = constants.%assoc2]
 // CHECK:STDOUT:     %impl.elem2: type = impl_witness_access constants.%I3.lookup_impl_witness, element2 [symbolic_self = constants.%impl.elem2]
 // CHECK:STDOUT:     %BAD4.ref: <error> = name_ref BAD4, <error> [concrete = <error>]
-// CHECK:STDOUT:     %.loc27_15: type = where_expr %.Self [concrete = <error>] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I3.type
+// CHECK:STDOUT:     %.loc27_15: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type %I3.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %struct_type.b
 // CHECK:STDOUT:       requirement_rewrite %impl.elem1, <error>
 // CHECK:STDOUT:       requirement_rewrite %impl.elem2, <error>
@@ -930,8 +930,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc5_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:     %.loc5_26.2: type = converted %.loc5_26.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:     %.loc5_14: type = where_expr %.Self [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc5_14: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc5_26.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -1038,8 +1038,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %impl.elem0.subst: type = impl_witness_access_substituted %impl.elem0.loc10_32, %.loc10_26.2 [concrete = constants.%empty_struct_type]
 // CHECK:STDOUT:     %.loc10_38.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc10_38.2: type = converted %.loc10_38.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc10_14: type = where_expr %.Self [concrete = <error>] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc10_14: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc10_20, %.loc10_26.2
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.subst, %.loc10_38.2
 // CHECK:STDOUT:     }
@@ -1133,8 +1133,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %impl.elem0.subst: type = impl_witness_access_substituted %impl.elem0.loc10_34, <error> [concrete = <error>]
 // CHECK:STDOUT:     %.loc10_40.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc10_40.2: type = converted %.loc10_40.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc10_14: type = where_expr %.Self [concrete = <error>] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc10_14: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc10_20, <error>
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.subst, %.loc10_40.2
 // CHECK:STDOUT:     }
@@ -1227,8 +1227,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %impl.elem0.loc10_32: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %impl.elem0.subst: type = impl_witness_access_substituted %impl.elem0.loc10_32, %.loc10_26.2 [concrete = constants.%empty_struct_type]
 // CHECK:STDOUT:     %BAD6.ref: <error> = name_ref BAD6, <error> [concrete = <error>]
-// CHECK:STDOUT:     %.loc10_14: type = where_expr %.Self [concrete = <error>] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc10_14: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc10_20, %.loc10_26.2
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.subst, <error>
 // CHECK:STDOUT:     }
@@ -1320,8 +1320,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %impl.elem0.loc14_34: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %impl.elem0.subst: type = impl_witness_access_substituted %impl.elem0.loc14_34, <error> [concrete = <error>]
 // CHECK:STDOUT:     %BAD8.ref: <error> = name_ref BAD8, <error> [concrete = <error>]
-// CHECK:STDOUT:     %.loc14_14: type = where_expr %.Self [concrete = <error>] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc14_14: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc14_20, <error>
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.subst, <error>
 // CHECK:STDOUT:     }
@@ -1417,8 +1417,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %impl.elem0.subst: type = impl_witness_access_substituted %impl.elem0.loc6_32, %.loc6_26.2 [concrete = constants.%empty_struct_type]
 // CHECK:STDOUT:     %.loc6_38.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:     %.loc6_38.2: type = converted %.loc6_38.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:     %.loc6_14: type = where_expr %.Self [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc6_14: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc6_20, %.loc6_26.2
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.subst, %.loc6_38.2
 // CHECK:STDOUT:     }
@@ -1520,8 +1520,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %.loc6_39.2: %empty_struct_type = converted %.loc6_38, %empty_struct [concrete = constants.%empty_struct]
 // CHECK:STDOUT:     %struct: %struct_type.a.225 = struct_value (%.loc6_39.2) [concrete = constants.%struct]
 // CHECK:STDOUT:     %.loc6_39.3: %struct_type.a.225 = converted %.loc6_39.1, %struct [concrete = constants.%struct]
-// CHECK:STDOUT:     %.loc6_20: type = where_expr %.Self [concrete = constants.%NonType_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%NonType.type
+// CHECK:STDOUT:     %.loc6_20: type = where_expr [concrete = constants.%NonType_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %NonType.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc6_39.3
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -1662,8 +1662,8 @@ impl CD as IF where .F = 0 {
 // CHECK:STDOUT:     %F.ref: %IF.assoc_type = name_ref F, imports.%Main.import_ref.82a [concrete = constants.%assoc0]
 // CHECK:STDOUT:     %impl.elem0: %.8a4 = impl_witness_access constants.%IF.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]
-// CHECK:STDOUT:     %.loc10_15: type = where_expr %.Self [concrete = constants.%IF_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%IF.type
+// CHECK:STDOUT:     %.loc10_15: type = where_expr [concrete = constants.%IF_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %IF.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %int_0
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }

+ 2 - 2
toolchain/check/testdata/impl/import_self_specific.carbon

@@ -454,8 +454,8 @@ impl forall [N:! E] D(N) as I where .Assoc = () {
 // CHECK:STDOUT:     %.loc20_47.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %Y.facet: %Y.type = facet_value constants.%empty_tuple.type, (constants.%Y.impl_witness.980) [concrete = constants.%Y.facet]
 // CHECK:STDOUT:     %.loc20_47.2: %Y.type = converted %.loc20_47.1, %Y.facet [concrete = constants.%Y.facet]
-// CHECK:STDOUT:     %.loc20_31: type = where_expr %.Self.1 [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc20_31: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc20_47.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %.loc20_18: type = splice_block %E.ref [concrete = constants.%E] {

+ 14 - 14
toolchain/check/testdata/impl/incomplete.carbon

@@ -364,8 +364,8 @@ interface B {
 // CHECK:STDOUT:     %.loc13_19: type = converted %.Self.ref.loc13, %.Self.as_type.loc13 [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:     %X.ref.loc13: <error> = name_ref X, <error> [concrete = <error>]
 // CHECK:STDOUT:     %.loc13_25: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
-// CHECK:STDOUT:     %.loc13_13: type = where_expr %.Self.2 [concrete = <error>] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:     %.loc13_13: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type %J.ref.loc13
 // CHECK:STDOUT:       requirement_rewrite %X.ref.loc13, <error>
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -378,8 +378,8 @@ interface B {
 // CHECK:STDOUT:     %.loc22_19: type = converted %.Self.ref.loc22, %.Self.as_type.loc22 [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:     %X.ref.loc22: <error> = name_ref X, <error> [concrete = <error>]
 // CHECK:STDOUT:     %.loc22_25: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
-// CHECK:STDOUT:     %.loc22_13: type = where_expr %.Self.1 [concrete = <error>] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:     %.loc22_13: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type %J.ref.loc22
 // CHECK:STDOUT:       requirement_rewrite %X.ref.loc22, <error>
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -474,8 +474,8 @@ interface B {
 // CHECK:STDOUT:     %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type]
 // CHECK:STDOUT:     %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:     %.loc8_19: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
-// CHECK:STDOUT:     %.loc8_13: type = where_expr %.Self [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc8_13: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_impls %.loc8_19, %Incomplete.ref
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -564,8 +564,8 @@ interface B {
 // CHECK:STDOUT:     %impl.elem0.loc8: type = impl_witness_access constants.%J.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc8_52.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc8_52.2: type = converted %.loc8_52.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc8_13: type = where_expr %.Self.2 [concrete = constants.%J_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:     %.loc8_13: type = where_expr [concrete = constants.%J_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %J.ref.loc8
 // CHECK:STDOUT:       requirement_impls %.loc8_19, %Incomplete.ref.loc8
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc8, %.loc8_52.2
 // CHECK:STDOUT:     }
@@ -585,8 +585,8 @@ interface B {
 // CHECK:STDOUT:     %impl.elem0.loc10: type = impl_witness_access constants.%J.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc10_52.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc10_52.2: type = converted %.loc10_52.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc10_13: type = where_expr %.Self.1 [concrete = constants.%J_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:     %.loc10_13: type = where_expr [concrete = constants.%J_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %J.ref.loc10
 // CHECK:STDOUT:       requirement_impls %.loc10_19, %Incomplete.ref.loc10
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc10, %.loc10_52.2
 // CHECK:STDOUT:     }
@@ -676,8 +676,8 @@ interface B {
 // CHECK:STDOUT:     %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type]
 // CHECK:STDOUT:     %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:     %.loc8_19: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
-// CHECK:STDOUT:     %.loc8_13: type = where_expr %.Self [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc8_13: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_impls %.loc8_19, %Incomplete.ref
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -817,8 +817,8 @@ interface B {
 // CHECK:STDOUT:       %impl.elem0: type = impl_witness_access constants.%X.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:       %.loc16_32.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:       %.loc16_32.2: type = converted %.loc16_32.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:       %.loc16_19.2: type = where_expr %.Self.2 [concrete = constants.%X_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%X.type
+// CHECK:STDOUT:       %.loc16_19.2: type = where_expr [concrete = constants.%X_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %X.ref
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0, %.loc16_32.2
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }

+ 8 - 8
toolchain/check/testdata/impl/lookup/lookup_interface_with_enclosing_generic_inside_rewrite_constraint.carbon

@@ -193,8 +193,8 @@ fn F() {
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%Y.lookup_impl_witness.b08, element0 [symbolic_self = constants.%impl.elem0.48b]
 // CHECK:STDOUT:     %.loc58_35.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc58_35.2: type = converted %.loc58_35.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc58_23: type = where_expr %.Self [concrete = constants.%Y_where.type.ad5] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%Y.type.5e1
+// CHECK:STDOUT:     %.loc58_23: type = where_expr [concrete = constants.%Y_where.type.ad5] {
+// CHECK:STDOUT:       requirement_base_facet_type %Y.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc58_35.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -260,8 +260,8 @@ fn F() {
 // CHECK:STDOUT:         %impl.elem0.loc54_27.2: type = impl_witness_access constants.%Y.lookup_impl_witness.3b9, element0 [symbolic = %impl.elem0.loc54_27.1 (constants.%impl.elem0.284)]
 // CHECK:STDOUT:         %.loc54_33.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:         %.loc54_33.2: type = converted %.loc54_33.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:         %.loc54_21.2: type = where_expr %.Self.3 [symbolic = %Y_where.type (constants.%Y_where.type.7c7)] {
-// CHECK:STDOUT:           requirement_base_facet_type constants.%Y.type.6b3
+// CHECK:STDOUT:         %.loc54_21.2: type = where_expr [symbolic = %Y_where.type (constants.%Y_where.type.7c7)] {
+// CHECK:STDOUT:           requirement_base_facet_type %Y.ref
 // CHECK:STDOUT:           requirement_rewrite %impl.elem0.loc54_27.2, %.loc54_33.2
 // CHECK:STDOUT:         }
 // CHECK:STDOUT:       }
@@ -651,8 +651,8 @@ fn F() {
 // CHECK:STDOUT:         %impl.elem0.loc11_27.2: type = impl_witness_access constants.%Y.lookup_impl_witness.5bf, element0 [symbolic = %impl.elem0.loc11_27.1 (constants.%impl.elem0.63e)]
 // CHECK:STDOUT:         %.loc11_33.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:         %.loc11_33.2: type = converted %.loc11_33.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:         %.loc11_21.2: type = where_expr %.Self.3 [symbolic = %Y_where.type (constants.%Y_where.type.b0f)] {
-// CHECK:STDOUT:           requirement_base_facet_type constants.%Y.type.6ae
+// CHECK:STDOUT:         %.loc11_21.2: type = where_expr [symbolic = %Y_where.type (constants.%Y_where.type.b0f)] {
+// CHECK:STDOUT:           requirement_base_facet_type %Y.ref
 // CHECK:STDOUT:           requirement_rewrite %impl.elem0.loc11_27.2, %.loc11_33.2
 // CHECK:STDOUT:         }
 // CHECK:STDOUT:       }
@@ -673,8 +673,8 @@ fn F() {
 // CHECK:STDOUT:       %impl.elem0.loc14_21.1: type = impl_witness_access constants.%Y.lookup_impl_witness.5bf, element0 [symbolic = %impl.elem0.loc14_21.2 (constants.%impl.elem0.63e)]
 // CHECK:STDOUT:       %.loc14_27.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:       %.loc14_27.2: type = converted %.loc14_27.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:       %.loc14_15: type = where_expr %.Self.1 [symbolic = %Y_where.type (constants.%Y_where.type.b0f)] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%Y.type.6ae
+// CHECK:STDOUT:       %.loc14_15: type = where_expr [symbolic = %Y_where.type (constants.%Y_where.type.b0f)] {
+// CHECK:STDOUT:         requirement_base_facet_type %Y.ref
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc14_21.1, %.loc14_27.2
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }

+ 14 - 14
toolchain/check/testdata/impl/lookup/specialization_with_symbolic_rewrite.carbon

@@ -193,8 +193,8 @@ fn F[T:! Ptr](var t: T) -> T.(Ptr.Type) {
 // CHECK:STDOUT:     %impl.elem0.loc9_50.1: type = impl_witness_access constants.%Z.lookup_impl_witness.7d6, element0 [symbolic = %impl.elem0.loc9_50.2 (constants.%impl.elem0.e5e)]
 // CHECK:STDOUT:     %.loc9_56.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc9_56.2: type = converted %.loc9_56.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc9_44: type = where_expr %.Self.1 [symbolic = %Z_where.type (constants.%Z_where.type.a76)] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%Z.type.4d0
+// CHECK:STDOUT:     %.loc9_44: type = where_expr [symbolic = %Z_where.type (constants.%Z_where.type.a76)] {
+// CHECK:STDOUT:       requirement_base_facet_type %Z.type.loc9_42.1
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc9_50.1, %.loc9_56.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %.loc9_18.1: type = splice_block %.loc9_18.2 [concrete = type] {
@@ -223,8 +223,8 @@ fn F[T:! Ptr](var t: T) -> T.(Ptr.Type) {
 // CHECK:STDOUT:     %X.ref: %Z.assoc_type.553 = name_ref X, %.loc11_46.2 [concrete = constants.%assoc0.1e0]
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%Z.lookup_impl_witness.c06, element0 [symbolic_self = constants.%impl.elem0.2cd]
 // CHECK:STDOUT:     %T.ref.loc11_51: type = name_ref T, %T.loc11_21.1 [symbolic = %T.loc11_21.2 (constants.%T.67d)]
-// CHECK:STDOUT:     %.loc11_40: type = where_expr %.Self.1 [symbolic = %Z_where.type (constants.%Z_where.type.c3e)] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%Z.type.be4
+// CHECK:STDOUT:     %.loc11_40: type = where_expr [symbolic = %Z_where.type (constants.%Z_where.type.c3e)] {
+// CHECK:STDOUT:       requirement_base_facet_type %Z.type
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %T.ref.loc11_51
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %.loc11_24.1: type = splice_block %.loc11_24.2 [concrete = type] {
@@ -589,8 +589,8 @@ fn F[T:! Ptr](var t: T) -> T.(Ptr.Type) {
 // CHECK:STDOUT:     %impl.elem0.loc10_50.1: type = impl_witness_access constants.%Z.lookup_impl_witness.7d6, element0 [symbolic = %impl.elem0.loc10_50.2 (constants.%impl.elem0.e5e)]
 // CHECK:STDOUT:     %.loc10_56.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc10_56.2: type = converted %.loc10_56.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc10_44: type = where_expr %.Self.1 [symbolic = %Z_where.type (constants.%Z_where.type.a76)] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%Z.type.4d0
+// CHECK:STDOUT:     %.loc10_44: type = where_expr [symbolic = %Z_where.type (constants.%Z_where.type.a76)] {
+// CHECK:STDOUT:       requirement_base_facet_type %Z.type.loc10_42.1
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc10_50.1, %.loc10_56.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %.loc10_18.1: type = splice_block %.loc10_18.2 [concrete = type] {
@@ -619,8 +619,8 @@ fn F[T:! Ptr](var t: T) -> T.(Ptr.Type) {
 // CHECK:STDOUT:     %X.ref: %Z.assoc_type.553 = name_ref X, %.loc12_40.2 [concrete = constants.%assoc0.1e0]
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%Z.lookup_impl_witness.c06, element0 [symbolic_self = constants.%impl.elem0.2cd]
 // CHECK:STDOUT:     %T.ref.loc12_45: type = name_ref T, %T.loc12_15.1 [symbolic = %T.loc12_15.2 (constants.%T.67d)]
-// CHECK:STDOUT:     %.loc12_34: type = where_expr %.Self.1 [symbolic = %Z_where.type (constants.%Z_where.type.c3e)] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%Z.type.be4
+// CHECK:STDOUT:     %.loc12_34: type = where_expr [symbolic = %Z_where.type (constants.%Z_where.type.c3e)] {
+// CHECK:STDOUT:       requirement_base_facet_type %Z.type
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %T.ref.loc12_45
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %.loc12_18.1: type = splice_block %.loc12_18.2 [concrete = type] {
@@ -953,8 +953,8 @@ fn F[T:! Ptr](var t: T) -> T.(Ptr.Type) {
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%Ptr.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0.4ac]
 // CHECK:STDOUT:     %U.ref.loc7_53: type = name_ref U, %U.loc7_21.1 [symbolic = %U.loc7_21.2 (constants.%U.67d)]
 // CHECK:STDOUT:     %ptr.loc7_54.1: type = ptr_type %U.ref.loc7_53 [symbolic = %ptr.loc7_54.2 (constants.%ptr.e8f8f9.1)]
-// CHECK:STDOUT:     %.loc7_39: type = where_expr %.Self.1 [symbolic = %Ptr_where.type (constants.%Ptr_where.type.3963c5.1)] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%Ptr.type
+// CHECK:STDOUT:     %.loc7_39: type = where_expr [symbolic = %Ptr_where.type (constants.%Ptr_where.type.3963c5.1)] {
+// CHECK:STDOUT:       requirement_base_facet_type %Ptr.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %ptr.loc7_54.1
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %.loc7_24.1: type = splice_block %.loc7_24.2 [concrete = type] {
@@ -1179,8 +1179,8 @@ fn F[T:! Ptr](var t: T) -> T.(Ptr.Type) {
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%Ptr.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0.4ac]
 // CHECK:STDOUT:     %U.ref.loc7_53: type = name_ref U, %U.loc7_21.1 [symbolic = %U.loc7_21.2 (constants.%U.67d)]
 // CHECK:STDOUT:     %ptr.loc7_54.1: type = ptr_type %U.ref.loc7_53 [symbolic = %ptr.loc7_54.2 (constants.%ptr.e8f8f9.1)]
-// CHECK:STDOUT:     %.loc7_39: type = where_expr %.Self.1 [symbolic = %Ptr_where.type (constants.%Ptr_where.type.396)] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%Ptr.type
+// CHECK:STDOUT:     %.loc7_39: type = where_expr [symbolic = %Ptr_where.type (constants.%Ptr_where.type.396)] {
+// CHECK:STDOUT:       requirement_base_facet_type %Ptr.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %ptr.loc7_54.1
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %.loc7_24.1: type = splice_block %.loc7_24.2 [concrete = type] {
@@ -1406,8 +1406,8 @@ fn F[T:! Ptr](var t: T) -> T.(Ptr.Type) {
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%Ptr.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0.4ac]
 // CHECK:STDOUT:     %U.ref.loc7_53: type = name_ref U, %U.loc7_21.1 [symbolic = %U.loc7_21.2 (constants.%U.67d)]
 // CHECK:STDOUT:     %ptr.loc7_54.1: type = ptr_type %U.ref.loc7_53 [symbolic = %ptr.loc7_54.2 (constants.%ptr.e8f8f9.1)]
-// CHECK:STDOUT:     %.loc7_39: type = where_expr %.Self.1 [symbolic = %Ptr_where.type (constants.%Ptr_where.type.396)] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%Ptr.type
+// CHECK:STDOUT:     %.loc7_39: type = where_expr [symbolic = %Ptr_where.type (constants.%Ptr_where.type.396)] {
+// CHECK:STDOUT:       requirement_base_facet_type %Ptr.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %ptr.loc7_54.1
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %.loc7_24.1: type = splice_block %.loc7_24.2 [concrete = type] {

+ 30 - 30
toolchain/check/testdata/impl/use_assoc_entity.carbon

@@ -469,8 +469,8 @@ fn F() {
 // CHECK:STDOUT:     %U.ref: %J.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0.ebd]
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%J.lookup_impl_witness.46a, element0 [symbolic_self = constants.%impl.elem0.a58]
 // CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]
-// CHECK:STDOUT:     %.loc8_14: type = where_expr %.Self [concrete = constants.%J_where.type.928] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:     %.loc8_14: type = where_expr [concrete = constants.%J_where.type.928] {
+// CHECK:STDOUT:       requirement_base_facet_type %J.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %i32
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -502,8 +502,8 @@ fn F() {
 // CHECK:STDOUT:     %U.ref: %J.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0.ebd]
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%J.lookup_impl_witness.46a, element0 [symbolic_self = constants.%impl.elem0.a58]
 // CHECK:STDOUT:     %C.ref.loc21_24: type = name_ref C, file.%C.decl [concrete = constants.%C]
-// CHECK:STDOUT:     %.loc21_13: type = where_expr %.Self [concrete = constants.%J_where.type.d0e] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:     %.loc21_13: type = where_expr [concrete = constants.%J_where.type.d0e] {
+// CHECK:STDOUT:       requirement_base_facet_type %J.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %C.ref.loc21_24
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -842,8 +842,8 @@ fn F() {
 // CHECK:STDOUT:     %U.ref: %J.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0.ebd]
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%J.lookup_impl_witness.46a, element0 [symbolic_self = constants.%impl.elem0.a58]
 // CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]
-// CHECK:STDOUT:     %.loc10_13: type = where_expr %.Self [concrete = constants.%J_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:     %.loc10_13: type = where_expr [concrete = constants.%J_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %J.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %i32
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -1348,8 +1348,8 @@ fn F() {
 // CHECK:STDOUT:     %U.ref: %J.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0.ebd]
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%J.lookup_impl_witness.46a, element0 [symbolic_self = constants.%impl.elem0.a58]
 // CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]
-// CHECK:STDOUT:     %.loc10_20: type = where_expr %.Self [concrete = constants.%J_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:     %.loc10_20: type = where_expr [concrete = constants.%J_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %J.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %i32
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -2397,8 +2397,8 @@ fn F() {
 // CHECK:STDOUT:       %U.ref: %J.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0.ebd]
 // CHECK:STDOUT:       %impl.elem0.loc8: type = impl_witness_access constants.%J.lookup_impl_witness.46a, element0 [symbolic_self = constants.%impl.elem0.a58]
 // CHECK:STDOUT:       %i32.loc8_37: type = type_literal constants.%i32 [concrete = constants.%i32]
-// CHECK:STDOUT:       %.loc8_26.2: type = where_expr %.Self.2 [concrete = constants.%J_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:       %.loc8_26.2: type = where_expr [concrete = constants.%J_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %J.ref
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc8, %i32.loc8_37
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -2696,8 +2696,8 @@ fn F() {
 // CHECK:STDOUT:     %U.ref: %J.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0.ebd]
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%J.lookup_impl_witness.46a, element0 [symbolic_self = constants.%impl.elem0.a58]
 // CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]
-// CHECK:STDOUT:     %.loc9_20: type = where_expr %.Self [concrete = constants.%J_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:     %.loc9_20: type = where_expr [concrete = constants.%J_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %J.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %i32
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -3155,8 +3155,8 @@ fn F() {
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%J.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc8_32.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc8_32.2: type = converted %.loc8_32.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc8_20: type = where_expr %.Self [concrete = constants.%J_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:     %.loc8_20: type = where_expr [concrete = constants.%J_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %J.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc8_32.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -3273,8 +3273,8 @@ fn F() {
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%J2.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc22_28.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:     %.loc22_28.2: type = converted %.loc22_28.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:     %.loc22_15: type = where_expr %.Self [concrete = constants.%J2_where.type.1ad] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%J2.type
+// CHECK:STDOUT:     %.loc22_15: type = where_expr [concrete = constants.%J2_where.type.1ad] {
+// CHECK:STDOUT:       requirement_base_facet_type %J2.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc22_28.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -3289,8 +3289,8 @@ fn F() {
 // CHECK:STDOUT:     %U2.ref: %J2.assoc_type = name_ref U2, @U2.%assoc0 [concrete = constants.%assoc0]
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%J2.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %C2.ref.loc31_27: type = name_ref C2, file.%C2.decl [concrete = constants.%C2]
-// CHECK:STDOUT:     %.loc31_15: type = where_expr %.Self [concrete = constants.%J2_where.type.de0] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%J2.type
+// CHECK:STDOUT:     %.loc31_15: type = where_expr [concrete = constants.%J2_where.type.de0] {
+// CHECK:STDOUT:       requirement_base_facet_type %J2.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %C2.ref.loc31_27
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -3602,8 +3602,8 @@ fn F() {
 // CHECK:STDOUT:     %.loc11_31.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc11_31.2: type = converted %.loc11_31.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
 // CHECK:STDOUT:     %struct_type.a: type = struct_type {.a: %empty_tuple.type} [concrete = constants.%struct_type.a]
-// CHECK:STDOUT:     %.loc11_14: type = where_expr %.Self [concrete = constants.%K_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%K.type
+// CHECK:STDOUT:     %.loc11_14: type = where_expr [concrete = constants.%K_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %K.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %struct_type.a
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -3853,8 +3853,8 @@ fn F() {
 // CHECK:STDOUT:     %.loc8_33.2: %empty_struct_type = converted %.loc8_32, %empty_struct [concrete = constants.%empty_struct]
 // CHECK:STDOUT:     %struct: %struct_type.b.347 = struct_value (%.loc8_33.2) [concrete = constants.%struct]
 // CHECK:STDOUT:     %.loc8_33.3: %struct_type.b.347 = converted %.loc8_33.1, %struct [concrete = constants.%struct]
-// CHECK:STDOUT:     %.loc8_14: type = where_expr %.Self [concrete = constants.%M_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%M.type
+// CHECK:STDOUT:     %.loc8_14: type = where_expr [concrete = constants.%M_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %M.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc8_33.3
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -4063,8 +4063,8 @@ fn F() {
 // CHECK:STDOUT:     %.loc10_36.2: type = converted %.loc10_35, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
 // CHECK:STDOUT:     %struct: %struct_type.b.86f = struct_value (%.loc10_36.2) [concrete = constants.%struct.0f3]
 // CHECK:STDOUT:     %.loc10_36.3: %struct_type.b.86f = converted %.loc10_36.1, %struct [concrete = constants.%struct.0f3]
-// CHECK:STDOUT:     %.loc10_17: type = where_expr %.Self [concrete = constants.%M_where.type.2ad] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%M.type
+// CHECK:STDOUT:     %.loc10_17: type = where_expr [concrete = constants.%M_where.type.2ad] {
+// CHECK:STDOUT:       requirement_base_facet_type %M.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc10_36.3
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -4085,8 +4085,8 @@ fn F() {
 // CHECK:STDOUT:     %.loc16_36.2: type = converted %.loc16_35, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
 // CHECK:STDOUT:     %struct: %struct_type.b.86f = struct_value (%.loc16_36.2) [concrete = constants.%struct.c94]
 // CHECK:STDOUT:     %.loc16_36.3: %struct_type.b.86f = converted %.loc16_36.1, %struct [concrete = constants.%struct.c94]
-// CHECK:STDOUT:     %.loc16_17: type = where_expr %.Self [concrete = constants.%M_where.type.bf5] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%M.type
+// CHECK:STDOUT:     %.loc16_17: type = where_expr [concrete = constants.%M_where.type.bf5] {
+// CHECK:STDOUT:       requirement_base_facet_type %M.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc16_36.3
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -4397,8 +4397,8 @@ fn F() {
 // CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc8_25.2(%int_2) [concrete = constants.%int_2.ef8]
 // CHECK:STDOUT:     %.loc8_25.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_2.ef8]
 // CHECK:STDOUT:     %.loc8_25.2: %i32 = converted %int_2, %.loc8_25.1 [concrete = constants.%int_2.ef8]
-// CHECK:STDOUT:     %.loc8_14: type = where_expr %.Self [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc8_14: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc8_20, %.loc8_25.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -4650,8 +4650,8 @@ fn F() {
 // CHECK:STDOUT:     %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]
 // CHECK:STDOUT:     %T.ref.loc9_44: type = name_ref T, %T.loc9_15.1 [symbolic = %T.loc9_15.2 (constants.%T)]
 // CHECK:STDOUT:     %C.loc9_45.1: type = class_type @C, @C(constants.%T) [symbolic = %C.loc9_45.2 (constants.%C.5a3)]
-// CHECK:STDOUT:     %.loc9_31: type = where_expr %.Self.1 [symbolic = %Z_where.type (constants.%Z_where.type.ea1)] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%Z.type
+// CHECK:STDOUT:     %.loc9_31: type = where_expr [symbolic = %Z_where.type (constants.%Z_where.type.ea1)] {
+// CHECK:STDOUT:       requirement_base_facet_type %Z.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %C.loc9_45.1
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %.loc9_18.1: type = splice_block %.loc9_18.2 [concrete = type] {

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

@@ -80,8 +80,8 @@ let U: (type where .Self impls type).missing = {};
 // CHECK:STDOUT:     %.loc8_32: type = type_literal type [concrete = type]
 // CHECK:STDOUT:     %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:     %.loc8_20: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
-// CHECK:STDOUT:     %.loc8_14: type = where_expr %.Self [concrete = constants.%type] {
-// CHECK:STDOUT:       requirement_base_facet_type type
+// CHECK:STDOUT:     %.loc8_14: type = where_expr [concrete = constants.%type] {
+// CHECK:STDOUT:       requirement_base_facet_type %.loc8_9
 // CHECK:STDOUT:       requirement_impls %.loc8_20, %.loc8_32
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %missing.ref: <error> = name_ref missing, <error> [concrete = <error>]

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

@@ -174,8 +174,8 @@ interface A(T:! type) {
 // CHECK:STDOUT:     %impl.elem0: %C = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc16_27: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
-// CHECK:STDOUT:     %.loc16_14: type = where_expr %.Self [concrete = <error>] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:     %.loc16_14: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type %I.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, <error>
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }

+ 4 - 4
toolchain/check/testdata/interface/require.carbon

@@ -714,8 +714,8 @@ interface Z(T:! type) {
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%Y.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc7_32.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc7_32.2: type = converted %.loc7_32.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc7_19: type = where_expr %.Self [concrete = constants.%Y_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%Y.type
+// CHECK:STDOUT:     %.loc7_19: type = where_expr [concrete = constants.%Y_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %Y.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc7_32.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -873,8 +873,8 @@ interface Z(T:! type) {
 // CHECK:STDOUT:     %Self.ref: %Z.type = name_ref Self, @Z.%Self [symbolic = %Self (constants.%Self.c59)]
 // CHECK:STDOUT:     %Self.as_type.loc10_31: type = facet_access_type %Self.ref [symbolic = %Self.as_type.loc10_11.2 (constants.%Self.as_type)]
 // CHECK:STDOUT:     %.loc10_31: type = converted %Self.ref, %Self.as_type.loc10_31 [symbolic = %Self.as_type.loc10_11.2 (constants.%Self.as_type)]
-// CHECK:STDOUT:     %.loc10_19: type = where_expr %.Self [symbolic = %Y_where.type (constants.%Y_where.type)] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%Y.type
+// CHECK:STDOUT:     %.loc10_19: type = where_expr [symbolic = %Y_where.type (constants.%Y_where.type)] {
+// CHECK:STDOUT:       requirement_base_facet_type %Y.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc10_31
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }

+ 2 - 2
toolchain/check/testdata/named_constraint/extend_name_lookup.carbon

@@ -227,8 +227,8 @@ fn F(T:! type where .Self impls W) {
 // CHECK:STDOUT:       %W.ref: type = name_ref W, file.%W.decl [concrete = constants.%W.type]
 // CHECK:STDOUT:       %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:       %.loc12_21: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
-// CHECK:STDOUT:       %.loc12_15.2: type = where_expr %.Self.2 [concrete = constants.%type_where] {
-// CHECK:STDOUT:         requirement_base_facet_type type
+// CHECK:STDOUT:       %.loc12_15.2: type = where_expr [concrete = constants.%type_where] {
+// CHECK:STDOUT:         requirement_base_facet_type %.loc12_10
 // CHECK:STDOUT:         requirement_impls %.loc12_21, %W.ref
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }

+ 8 - 8
toolchain/check/testdata/named_constraint/require.carbon

@@ -1194,8 +1194,8 @@ fn G(T:! Z) {
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%Y.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:     %.loc7_32.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc7_32.2: type = converted %.loc7_32.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc7_19: type = where_expr %.Self [concrete = constants.%Y_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%Y.type
+// CHECK:STDOUT:     %.loc7_19: type = where_expr [concrete = constants.%Y_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %Y.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc7_32.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -1338,8 +1338,8 @@ fn G(T:! Z) {
 // CHECK:STDOUT:     %Self.ref: %Z.type = name_ref Self, @Z.%Self [symbolic = %Self (constants.%Self.550)]
 // CHECK:STDOUT:     %Self.as_type.loc10_31: type = facet_access_type %Self.ref [symbolic = %Self.as_type.loc10_11.2 (constants.%Self.as_type)]
 // CHECK:STDOUT:     %.loc10_31: type = converted %Self.ref, %Self.as_type.loc10_31 [symbolic = %Self.as_type.loc10_11.2 (constants.%Self.as_type)]
-// CHECK:STDOUT:     %.loc10_19: type = where_expr %.Self [symbolic = %Y_where.type (constants.%Y_where.type)] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%Y.type
+// CHECK:STDOUT:     %.loc10_19: type = where_expr [symbolic = %Y_where.type (constants.%Y_where.type)] {
+// CHECK:STDOUT:       requirement_base_facet_type %Y.ref
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc10_31
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -1415,8 +1415,8 @@ fn G(T:! Z) {
 // CHECK:STDOUT:     %Y.type: type = facet_type <@Y, @Y(constants.%.Self.as_type.2e2)> [symbolic_self = constants.%Y.type.9b9]
 // CHECK:STDOUT:     %.Self.as_type.loc10_25: type = facet_access_type %.Self.ref.loc10_25 [symbolic_self = constants.%.Self.as_type.2e2]
 // CHECK:STDOUT:     %.loc10_25: type = converted %.Self.ref.loc10_25, %.Self.as_type.loc10_25 [symbolic_self = constants.%.Self.as_type.2e2]
-// CHECK:STDOUT:     %.loc10_19: type = where_expr %.Self [symbolic_self = constants.%Z_where.type.3f0] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%Z.type
+// CHECK:STDOUT:     %.loc10_19: type = where_expr [symbolic_self = constants.%Z_where.type.3f0] {
+// CHECK:STDOUT:       requirement_base_facet_type %Z.ref
 // CHECK:STDOUT:       requirement_impls %.loc10_25, %Y.type
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %Z_where.type.loc10_19.1: type = facet_type <@Z where .Self impls @Y, @Y(constants.%Self.as_type.92a)> [symbolic = %Z_where.type.loc10_19.2 (constants.%Z_where.type.862)]
@@ -1510,8 +1510,8 @@ fn G(T:! Z) {
 // CHECK:STDOUT:     %.Self.as_type.loc10_47: type = facet_access_type %.Self.ref.loc10_42 [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:     %.loc10_47: type = converted %.Self.ref.loc10_42, %.Self.as_type.loc10_47 [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:     %Y.type: type = facet_type <@Y, @Y(constants.%.Self.as_type)> [symbolic_self = constants.%Y.type.9b9]
-// CHECK:STDOUT:     %.loc10_19: type = where_expr %.Self [symbolic_self = constants.%Z_where.type.a6d533.1] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%Z.type
+// CHECK:STDOUT:     %.loc10_19: type = where_expr [symbolic_self = constants.%Z_where.type.a6d533.1] {
+// CHECK:STDOUT:       requirement_base_facet_type %Z.ref
 // CHECK:STDOUT:       requirement_impls %C.loc10_32, %Y.type
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %Z_where.type.loc10_19.1: type = facet_type <@Z where constants.%C.6c0 impls @Y, @Y(constants.%Self.as_type)> [symbolic = %Z_where.type.loc10_19.2 (constants.%Z_where.type.a6d533.2)]

+ 6 - 6
toolchain/check/testdata/operators/overloaded/index_with_prelude.carbon

@@ -162,8 +162,8 @@ let x: i32 = c[0];
 // CHECK:STDOUT:     %ElementType.ref.loc8_47: %IndexWith.assoc_type.b14 = name_ref ElementType, %.loc8_47.2 [concrete = constants.%assoc0.ab8]
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%IndexWith.lookup_impl_witness.407, element0 [symbolic_self = constants.%impl.elem0.9d3]
 // CHECK:STDOUT:     %ElementType.ref.loc8_62: type = name_ref ElementType, file.%ElementType.decl [concrete = constants.%ElementType]
-// CHECK:STDOUT:     %.loc8_41: type = where_expr %.Self [concrete = constants.%IndexWith_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%IndexWith.type.bbe
+// CHECK:STDOUT:     %.loc8_41: type = where_expr [concrete = constants.%IndexWith_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %IndexWith.type
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %ElementType.ref.loc8_62
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -357,8 +357,8 @@ let x: i32 = c[0];
 // CHECK:STDOUT:     %ElementType.ref: %IndexWith.assoc_type.972 = name_ref ElementType, %.loc8_56.2 [concrete = constants.%assoc0.b00]
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%IndexWith.lookup_impl_witness.6f5, element0 [symbolic_self = constants.%impl.elem0.d7c]
 // CHECK:STDOUT:     %C.ref.loc8_71: type = name_ref C, file.%C.decl [concrete = constants.%C]
-// CHECK:STDOUT:     %.loc8_50: type = where_expr %.Self [concrete = constants.%IndexWith_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%IndexWith.type.d54
+// CHECK:STDOUT:     %.loc8_50: type = where_expr [concrete = constants.%IndexWith_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %IndexWith.type
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %C.ref.loc8_71
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
@@ -542,8 +542,8 @@ let x: i32 = c[0];
 // CHECK:STDOUT:     %ElementType.ref.loc8_47: %IndexWith.assoc_type.b14 = name_ref ElementType, %.loc8_47.2 [concrete = constants.%assoc0.ab8]
 // CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%IndexWith.lookup_impl_witness.407, element0 [symbolic_self = constants.%impl.elem0.9d3]
 // CHECK:STDOUT:     %ElementType.ref.loc8_62: type = name_ref ElementType, file.%ElementType.decl [concrete = constants.%ElementType]
-// CHECK:STDOUT:     %.loc8_41: type = where_expr %.Self [concrete = constants.%IndexWith_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%IndexWith.type.bbe
+// CHECK:STDOUT:     %.loc8_41: type = where_expr [concrete = constants.%IndexWith_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type %IndexWith.type
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %ElementType.ref.loc8_62
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }

+ 16 - 16
toolchain/check/testdata/where_expr/constraints.carbon

@@ -210,8 +210,8 @@ fn F() {
 // CHECK:STDOUT:       %.loc7_30: type = type_literal type [concrete = type]
 // CHECK:STDOUT:       %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:       %.loc7_18: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
-// CHECK:STDOUT:       %.loc7_12.2: type = where_expr %.Self.2 [concrete = constants.%I.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:       %.loc7_12.2: type = where_expr [concrete = constants.%I.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %I.ref
 // CHECK:STDOUT:         requirement_impls %.loc7_18, %.loc7_30
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -228,8 +228,8 @@ fn F() {
 // CHECK:STDOUT:       %Type.ref: type = name_ref Type, file.%Type [concrete = type]
 // CHECK:STDOUT:       %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:       %.loc13_18: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
-// CHECK:STDOUT:       %.loc13_12.2: type = where_expr %.Self.2 [concrete = constants.%I.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:       %.loc13_12.2: type = where_expr [concrete = constants.%I.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %I.ref
 // CHECK:STDOUT:         requirement_impls %.loc13_18, %Type.ref
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -279,8 +279,8 @@ fn F() {
 // CHECK:STDOUT:       %J.ref: <error> = name_ref J, <error> [concrete = <error>]
 // CHECK:STDOUT:       %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:       %.loc14_18: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
-// CHECK:STDOUT:       %.loc14_12.2: type = where_expr %.Self.2 [concrete = <error>] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:       %.loc14_12.2: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:         requirement_base_facet_type %I.ref
 // CHECK:STDOUT:         requirement_impls %.loc14_18, <error>
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -336,8 +336,8 @@ fn F() {
 // CHECK:STDOUT:       <elided>
 // CHECK:STDOUT:       %.Self.ref: %I.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.1dc]
 // CHECK:STDOUT:       %.loc12_37: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
-// CHECK:STDOUT:       %.loc12_21.2: type = where_expr %.Self.2 [concrete = constants.%I_where.type.310] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:       %.loc12_21.2: type = where_expr [concrete = constants.%I_where.type.310] {
+// CHECK:STDOUT:         requirement_base_facet_type %I.ref
 // CHECK:STDOUT:         requirement_equivalent %.Self.ref, %.loc12_37
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -354,8 +354,8 @@ fn F() {
 // CHECK:STDOUT:       %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
 // CHECK:STDOUT:       %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type.7b1]
 // CHECK:STDOUT:       %.loc14_22: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type.7b1]
-// CHECK:STDOUT:       %.loc14_16.2: type = where_expr %.Self.2 [concrete = constants.%J_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:       %.loc14_16.2: type = where_expr [concrete = constants.%J_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %J.ref
 // CHECK:STDOUT:         requirement_impls %.loc14_22, %I.ref
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -378,8 +378,8 @@ fn F() {
 // CHECK:STDOUT:       %Member.ref: %I.assoc_type = name_ref Member, @Member.%assoc0 [concrete = constants.%assoc0]
 // CHECK:STDOUT:       %impl.elem0: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:       %.loc16_50: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
-// CHECK:STDOUT:       %.loc16_14.2: type = where_expr %.Self.2 [concrete = constants.%I_where.type.ac1] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:       %.loc16_14.2: type = where_expr [concrete = constants.%I_where.type.ac1] {
+// CHECK:STDOUT:         requirement_base_facet_type %I.ref
 // CHECK:STDOUT:         requirement_impls %.loc16_20, %J.ref
 // CHECK:STDOUT:         requirement_equivalent %impl.elem0, %.loc16_50
 // CHECK:STDOUT:       }
@@ -454,8 +454,8 @@ fn F() {
 // CHECK:STDOUT:       %M.ref: type = name_ref M, file.%M.decl [concrete = constants.%M.type]
 // CHECK:STDOUT:       %as_type: type = facet_access_type %impl.elem0 [symbolic_self = constants.%as_type]
 // CHECK:STDOUT:       %.loc12_36.2: type = converted %impl.elem0, %as_type [symbolic_self = constants.%as_type]
-// CHECK:STDOUT:       %.loc12_30.2: type = where_expr %.Self.2 [symbolic_self = constants.%K_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%K.type
+// CHECK:STDOUT:       %.loc12_30.2: type = where_expr [symbolic_self = constants.%K_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %K.ref
 // CHECK:STDOUT:         requirement_impls %.loc12_36.2, %M.ref
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -495,8 +495,8 @@ fn F() {
 // CHECK:STDOUT:       %I.ref: <error> = name_ref I, <error> [concrete = <error>]
 // CHECK:STDOUT:       %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
 // CHECK:STDOUT:       %.loc9_29: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
-// CHECK:STDOUT:       %.loc9_23.2: type = where_expr %.Self.2 [concrete = <error>] {
-// CHECK:STDOUT:         requirement_base_facet_type type
+// CHECK:STDOUT:       %.loc9_23.2: type = where_expr [concrete = <error>] {
+// CHECK:STDOUT:         requirement_base_facet_type %.loc9_18
 // CHECK:STDOUT:         requirement_impls %.loc9_29, <error>
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }

+ 6 - 6
toolchain/check/testdata/where_expr/designator.carbon

@@ -179,8 +179,8 @@ fn G(unused T:! type where C(()) impls I(.Self)) {}
 // CHECK:STDOUT:       <elided>
 // CHECK:STDOUT:       %.Self.ref: %I.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.1dc]
 // CHECK:STDOUT:       %.loc9_37: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
-// CHECK:STDOUT:       %.loc9_21.2: type = where_expr %.Self.2 [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:       %.loc9_21.2: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %I.ref
 // CHECK:STDOUT:         requirement_equivalent %.Self.ref, %.loc9_37
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -199,8 +199,8 @@ fn G(unused T:! type where C(()) impls I(.Self)) {}
 // CHECK:STDOUT:       %Member.ref: %I.assoc_type = name_ref Member, @Member.%assoc0 [concrete = constants.%assoc0]
 // CHECK:STDOUT:       %impl.elem0: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:       %.loc11_41: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
-// CHECK:STDOUT:       %.loc11_23.2: type = where_expr %.Self.2 [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:       %.loc11_23.2: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %I.ref
 // CHECK:STDOUT:         requirement_equivalent %impl.elem0, %.loc11_41
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -217,8 +217,8 @@ fn G(unused T:! type where C(()) impls I(.Self)) {}
 // CHECK:STDOUT:       %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
 // CHECK:STDOUT:       %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type.246]
 // CHECK:STDOUT:       %.loc13_33: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type.246]
-// CHECK:STDOUT:       %.loc13_27.2: type = where_expr %.Self.2 [concrete = constants.%type_where] {
-// CHECK:STDOUT:         requirement_base_facet_type type
+// CHECK:STDOUT:       %.loc13_27.2: type = where_expr [concrete = constants.%type_where] {
+// CHECK:STDOUT:         requirement_base_facet_type %.loc13_22
 // CHECK:STDOUT:         requirement_impls %.loc13_33, %I.ref
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }

+ 2 - 2
toolchain/check/testdata/where_expr/dot_self_index.carbon

@@ -89,8 +89,8 @@ fn G(U: Empty(i32) where .A = i32*) {
 // CHECK:STDOUT:       %impl.elem0.loc21_41.2: type = impl_witness_access constants.%Empty.lookup_impl_witness.177, element0 [symbolic = %impl.elem0.loc21_41.1 (constants.%impl.elem0.de5)]
 // CHECK:STDOUT:       %T.ref.loc21_46: type = name_ref T, %T.loc21_7.2 [symbolic = %T.loc21_7.1 (constants.%T)]
 // CHECK:STDOUT:       %ptr.loc21_47.2: type = ptr_type %T.ref.loc21_46 [symbolic = %ptr.loc21_47.1 (constants.%ptr.e8f)]
-// CHECK:STDOUT:       %.loc21_35.2: type = where_expr %.Self.3 [symbolic = %Empty_where.type (constants.%Empty_where.type.2dc)] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%Empty.type.6f76f1.2
+// CHECK:STDOUT:       %.loc21_35.2: type = where_expr [symbolic = %Empty_where.type (constants.%Empty_where.type.2dc)] {
+// CHECK:STDOUT:         requirement_base_facet_type %Empty.type.loc21_33.2
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc21_41.2, %ptr.loc21_47.2
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }

+ 14 - 14
toolchain/check/testdata/where_expr/equal_rewrite.carbon

@@ -255,8 +255,8 @@ let K: (E where .F = .Self.G) = bool;
 // CHECK:STDOUT:       %impl.elem0: type = impl_witness_access constants.%N.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:       %.loc9_28.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:       %.loc9_28.2: type = converted %.loc9_28.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:       %.loc9_16.2: type = where_expr %.Self.2 [concrete = constants.%N_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%N.type
+// CHECK:STDOUT:       %.loc9_16.2: type = where_expr [concrete = constants.%N_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %N.ref
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0, %.loc9_28.2
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -310,8 +310,8 @@ let K: (E where .F = .Self.G) = bool;
 // CHECK:STDOUT:       %B.ref: %A.assoc_type = name_ref B, @B.%assoc0 [concrete = constants.%assoc0]
 // CHECK:STDOUT:       %impl.elem0: type = impl_witness_access constants.%A.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:       %.loc10_36: type = type_literal bool [concrete = bool]
-// CHECK:STDOUT:       %.loc10_25: type = where_expr %.Self.2 [concrete = constants.%A_where.type.f51] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%A.type
+// CHECK:STDOUT:       %.loc10_25: type = where_expr [concrete = constants.%A_where.type.f51] {
+// CHECK:STDOUT:         requirement_base_facet_type %A.ref
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0, %.loc10_36
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:       <elided>
@@ -322,8 +322,8 @@ let K: (E where .F = .Self.G) = bool;
 // CHECK:STDOUT:       %impl.elem1: type = impl_witness_access constants.%A.lookup_impl_witness, element1 [symbolic_self = constants.%impl.elem1]
 // CHECK:STDOUT:       %.loc10_54.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:       %.loc10_54.2: type = converted %.loc10_54.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:       %.loc10_42.2: type = where_expr %.Self.3 [concrete = constants.%A_where.type.321] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%A_where.type.f51
+// CHECK:STDOUT:       %.loc10_42.2: type = where_expr [concrete = constants.%A_where.type.321] {
+// CHECK:STDOUT:         requirement_base_facet_type %.loc10_25
 // CHECK:STDOUT:         requirement_rewrite %impl.elem1, %.loc10_54.2
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -379,8 +379,8 @@ let K: (E where .F = .Self.G) = bool;
 // CHECK:STDOUT:       %F.ref: %E.assoc_type = name_ref F, @F.%assoc0 [concrete = constants.%assoc0]
 // CHECK:STDOUT:       %impl.elem0: type = impl_witness_access constants.%E.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]
-// CHECK:STDOUT:       %.loc9_28.2: type = where_expr %.Self.2 [concrete = constants.%E_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%E.type
+// CHECK:STDOUT:       %.loc9_28.2: type = where_expr [concrete = constants.%E_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %E.ref
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0, %i32
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }
@@ -406,8 +406,8 @@ let K: (E where .F = .Self.G) = bool;
 // CHECK:STDOUT:       %impl.elem0.loc11_45: type = impl_witness_access constants.%E.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:       %impl.elem0.subst: type = impl_witness_access_substituted %impl.elem0.loc11_45, %i32.loc11_37 [concrete = constants.%i32]
 // CHECK:STDOUT:       %i32.loc11_50: type = type_literal constants.%i32 [concrete = constants.%i32]
-// CHECK:STDOUT:       %.loc11_26.2: type = where_expr %.Self.2 [concrete = constants.%E_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%E.type
+// CHECK:STDOUT:       %.loc11_26.2: type = where_expr [concrete = constants.%E_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %E.ref
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc11_32, %i32.loc11_37
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0.subst, %i32.loc11_50
 // CHECK:STDOUT:       }
@@ -511,8 +511,8 @@ let K: (E where .F = .Self.G) = bool;
 // CHECK:STDOUT:       %L.ref: %J.assoc_type = name_ref L, @L.%assoc1 [concrete = constants.%assoc1]
 // CHECK:STDOUT:       %impl.elem1: type = impl_witness_access constants.%J.lookup_impl_witness, element1 [symbolic_self = constants.%impl.elem1]
 // CHECK:STDOUT:       %.loc10_53: type = type_literal bool [concrete = bool]
-// CHECK:STDOUT:       %.loc10_30.2: type = where_expr %.Self.2 [concrete = constants.%J_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:       %.loc10_30.2: type = where_expr [concrete = constants.%J_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %J.ref
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0, %.loc10_42.2
 // CHECK:STDOUT:         requirement_rewrite %impl.elem1, %.loc10_53
 // CHECK:STDOUT:       }
@@ -539,8 +539,8 @@ let K: (E where .F = .Self.G) = bool;
 // CHECK:STDOUT:       %impl.elem0: type = impl_witness_access constants.%J.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:       %.loc12_45.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:       %.loc12_45.2: type = converted %.loc12_45.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:       %.loc12_19.2: type = where_expr %.Self.2 [concrete = constants.%J_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:       %.loc12_19.2: type = where_expr [concrete = constants.%J_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %J.ref
 // CHECK:STDOUT:         requirement_rewrite %impl.elem1, %.loc12_30
 // CHECK:STDOUT:         requirement_rewrite %impl.elem0, %.loc12_45.2
 // CHECK:STDOUT:       }

+ 2 - 2
toolchain/check/testdata/where_expr/non_generic.carbon

@@ -50,8 +50,8 @@ fn NotGenericF(unused U: I where .T == i32) {}
 // CHECK:STDOUT:       %T.ref: %I.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]
 // CHECK:STDOUT:       %impl.elem0: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
 // CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]
-// CHECK:STDOUT:       %.loc17_28.2: type = where_expr %.Self [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:       %.loc17_28.2: type = where_expr [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:         requirement_base_facet_type %I.ref
 // CHECK:STDOUT:         requirement_equivalent %impl.elem0, %i32
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:     }

+ 1 - 0
toolchain/check/type_completion.cpp

@@ -12,6 +12,7 @@
 #include "toolchain/check/generic.h"
 #include "toolchain/check/inst.h"
 #include "toolchain/check/literal.h"
+#include "toolchain/check/period_self.h"
 #include "toolchain/check/subst.h"
 #include "toolchain/check/type.h"
 #include "toolchain/diagnostics/emitter.h"

+ 0 - 1
toolchain/sem_ir/formatter.cpp

@@ -1273,7 +1273,6 @@ auto Formatter::FormatInstRhs(Inst inst) -> void {
     }
 
     case CARBON_KIND(WhereExpr where): {
-      FormatArgs(where.period_self_id);
       FormatTrailingBlock(where.requirements_id);
       return;
     }

+ 2 - 4
toolchain/sem_ir/typed_insts.h

@@ -1640,7 +1640,8 @@ struct RequirementBaseFacetType {
 
   // No type since not an expression
 
-  // A FacetType, the TypeType singleton, or an ErrorInst.
+  // An expression that evaluates to a FacetType, the TypeType singleton, or an
+  // ErrorInst.
   TypeInstId base_type_inst_id;
 };
 
@@ -2369,9 +2370,6 @@ struct WhereExpr {
        .constant_kind = InstConstantKind::Conditional});
 
   TypeId type_id;
-  // This is the `.Self` symbolic binding. Its type matches the left type
-  // argument of the `where`.
-  InstId period_self_id;
   InstBlockId requirements_id;
 };