Просмотр исходного кода

Support impl lookup for multiple interfaces in a facet type (#5047)

If the query facet type has more than one interface, we must find an
impl that provides that interface for the query type for each interface.
This just looks like a for loop over the interfaces and ensuring we
found one impl witness for every one.

However the impl matching must change since it can't look at the
constant value of the entire query facet type for comparison with the
impl, as that query facet type may be for multiple interfaces and we are
looking to match an impl of a single interface.

To do this we break the query facet type up into each interface and make
sure the interface ids match. Then ensure that the impl was able to
deduce any generic parameters using the specific of the single query
interface.

There are some TODOs left here:

1. If the facet type for the query or the impl constraint has
"other_requirements" then we can't verify that they match since they are
lost. We fall back to comparing the constant id of the query to the
impl's constraint (after deducing generics in the impl). This correctly
eliminates mismatches but eagerly eliminates impls that could match the
query interface as well when there's more than one interface in the
query.

2. We don't return a witness for every interface in the query facet
type. Since we can't demonstrate any use of the witness there yet, for
cases that can have more than one interface in the query facet type,
this doesn't break anything that was previously working. The return
value is currently treated as a bool for cases with multiple interfaces
in the facet type (as a test for "can this be converted") but the
converted-to facet value's witnesses are unused.

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
Dana Jansens 1 год назад
Родитель
Сommit
a0b7f39591

+ 3 - 5
toolchain/check/deduce.cpp

@@ -639,11 +639,10 @@ auto DeduceGenericCallArguments(
   return deduction.MakeSpecific();
 }
 
-// Deduces the impl arguments to use in a use of a parameterized impl. Returns
-// `None` if deduction fails.
 auto DeduceImplArguments(Context& context, SemIR::LocId loc_id,
                          const SemIR::Impl& impl, SemIR::ConstantId self_id,
-                         SemIR::ConstantId constraint_id) -> SemIR::SpecificId {
+                         SemIR::SpecificId constraint_specific_id)
+    -> SemIR::SpecificId {
   DeductionContext deduction(context, loc_id, impl.generic_id,
                              /*enclosing_specific_id=*/SemIR::SpecificId::None,
                              /*self_type_id=*/SemIR::InstId::None,
@@ -652,8 +651,7 @@ auto DeduceImplArguments(Context& context, SemIR::LocId loc_id,
   // Prepare to perform deduction of the type and interface.
   deduction.Add(impl.self_id, context.constant_values().GetInstId(self_id),
                 /*needs_substitution=*/false);
-  deduction.Add(impl.constraint_id,
-                context.constant_values().GetInstId(constraint_id),
+  deduction.Add(impl.interface.specific_id, constraint_specific_id,
                 /*needs_substitution=*/false);
 
   if (!deduction.Deduce() || !deduction.CheckDeductionIsComplete()) {

+ 2 - 1
toolchain/check/deduce.h

@@ -22,7 +22,8 @@ auto DeduceGenericCallArguments(
 // `None` if deduction fails.
 auto DeduceImplArguments(Context& context, SemIR::LocId loc_id,
                          const SemIR::Impl& impl, SemIR::ConstantId self_id,
-                         SemIR::ConstantId constraint_id) -> SemIR::SpecificId;
+                         SemIR::SpecificId constraint_specific_id)
+    -> SemIR::SpecificId;
 
 }  // namespace Carbon::Check
 

+ 9 - 0
toolchain/check/eval_inst.cpp

@@ -8,6 +8,7 @@
 #include "toolchain/check/import_ref.h"
 #include "toolchain/check/type.h"
 #include "toolchain/check/type_completion.h"
+#include "toolchain/sem_ir/typed_insts.h"
 
 namespace Carbon::Check {
 
@@ -199,6 +200,14 @@ auto EvalConstantInst(Context& context, SemIRLoc loc,
           context.insts().TryGetAs<SemIR::ImplWitness>(inst.witness_id)) {
     auto elements = context.inst_blocks().Get(witness->elements_id);
     auto index = static_cast<size_t>(inst.index.index);
+    // TODO: Remove this block when LookupImplWitness returns all the witnesses
+    // for a facet type instead of just one. We just don't want to introduce
+    // crashes in the meantime.
+    if (index >= elements.size()) {
+      context.TODO(loc,
+                   "incorrect witness for multiple interfaces in a facet type");
+      return ConstantEvalResult::Error;
+    }
     CARBON_CHECK(index < elements.size(), "Access out of bounds.");
     auto element = elements[index];
     if (!element.has_value()) {

+ 133 - 58
toolchain/check/impl_lookup.cpp

@@ -157,14 +157,12 @@ static auto FindAndDiagnoseImplLookupCycle(
   return false;
 }
 
-// Gets the `SemIR::InterfaceId` for a facet type (as a constant value).
-//
-// The facet type requires only one `InterfaceId` right now. But in the future,
-// a facet type may include more than a single interface. For now that is
-// unhandled with a TODO.
-static auto GetInterfaceIdFromConstantId(Context& context, SemIR::LocId loc_id,
-                                         SemIR::ConstantId interface_const_id)
-    -> SemIR::InterfaceId {
+// Gets the set of `SpecificInterface`s that are required by a facet type
+// (as a constant value).
+static auto GetInterfacesFromConstantId(Context& context, SemIR::LocId loc_id,
+                                        SemIR::ConstantId interface_const_id,
+                                        bool& has_other_requirements)
+    -> llvm::SmallVector<SemIR::CompleteFacetType::RequiredInterface> {
   // The `interface_const_id` is a constant value for some facet type. We do
   // this long chain of steps to go from that constant value to the
   // `FacetTypeId` found on the `FacetType` instruction of this constant value,
@@ -183,6 +181,9 @@ static auto GetInterfaceIdFromConstantId(Context& context, SemIR::LocId loc_id,
   const auto& complete_facet_type =
       context.complete_facet_types().Get(complete_facet_type_id);
 
+  has_other_requirements =
+      context.facet_types().Get(facet_type_id).other_requirements;
+
   if (complete_facet_type.required_interfaces.empty()) {
     // This should never happen - a FacetType either requires or is bounded by
     // some `.Self impls` clause. Otherwise you would just have `type` (aka
@@ -190,72 +191,101 @@ static auto GetInterfaceIdFromConstantId(Context& context, SemIR::LocId loc_id,
     context.TODO(loc_id,
                  "impl lookup for a FacetType with no interface (using "
                  "`where .Self impls ...` instead?)");
-    return SemIR::InterfaceId::None;
-  }
-  if (complete_facet_type.required_interfaces.size() > 1) {
-    context.TODO(loc_id,
-                 "impl lookup for a FacetType with more than one interface");
-    return SemIR::InterfaceId::None;
+    return {};
   }
-  return complete_facet_type.required_interfaces[0].interface_id;
+  return complete_facet_type.required_interfaces;
 }
 
-static auto GetWitnessIdForImpl(Context& context, SemIR::LocId loc_id,
-                                SemIR::ConstantId type_const_id,
-                                SemIR::ConstantId interface_const_id,
-                                SemIR::InterfaceId interface_id,
-                                const SemIR::Impl& impl) -> SemIR::InstId {
-  // If impl.constraint_id is not symbolic, and doesn't match the query, then
-  // we don't need to proceed.
-  auto impl_interface_const_id =
-      context.constant_values().Get(impl.constraint_id);
-  if (!impl_interface_const_id.is_symbolic() &&
-      interface_const_id != impl_interface_const_id) {
-    return SemIR::InstId::None;
-  }
-
-  // This is the (single) interface named in the query `interface_const_id`.
+static auto GetWitnessIdForImpl(
+    Context& context, SemIR::LocId loc_id, SemIR::ConstantId type_const_id,
+    const SemIR::CompleteFacetType::RequiredInterface& interface,
+    const SemIR::Impl& impl) -> SemIR::InstId {
   // If the impl's interface_id differs from the query, then this impl can not
   // possibly provide the queried interface, and we don't need to proceed.
-  // Unlike the early-out above comparing the `impl.constraint_id`, this also
-  // elides looking at impls of generic interfaces where the interface itself
-  // does not match the query.
-  if (impl.interface.interface_id != interface_id) {
+  if (impl.interface.interface_id != interface.interface_id) {
     return SemIR::InstId::None;
   }
 
-  auto specific_id = SemIR::SpecificId::None;
+  // When the impl's interface_id matches, but the interface is generic, the
+  // impl may or may not match based on restrictions in the generic parameters
+  // of the impl.
+  //
+  // As a shortcut, if the impl's constraint is not symbolic (does not depend on
+  // any generic parameters), then we can determine that we match if the
+  // specific ids match exactly.
+  auto impl_interface_const_id =
+      context.constant_values().Get(impl.constraint_id);
+  if (!impl_interface_const_id.is_symbolic()) {
+    if (impl.interface.specific_id != interface.specific_id) {
+      return SemIR::InstId::None;
+    }
+  }
+
   // This check comes first to avoid deduction with an invalid impl. We use an
   // error value to indicate an error during creation of the impl, such as a
   // recursive impl which will cause deduction to recurse infinitely.
   if (impl.witness_id == SemIR::ErrorInst::SingletonInstId) {
     return SemIR::InstId::None;
   }
+  CARBON_CHECK(impl.witness_id.has_value());
+
+  // The impl may have generic arguments, in which case we need to deduce them
+  // to find what they are given the specific type and interface query. We use
+  // that specific to map values in the impl to the deduced values.
+  auto specific_id = SemIR::SpecificId::None;
   if (impl.generic_id.has_value()) {
     specific_id = DeduceImplArguments(context, loc_id, impl, type_const_id,
-                                      interface_const_id);
+                                      interface.specific_id);
     if (!specific_id.has_value()) {
       return SemIR::InstId::None;
     }
   }
-  if (!context.constant_values().AreEqualAcrossDeclarations(
-          SemIR::GetConstantValueInSpecific(context.sem_ir(), specific_id,
-                                            impl.self_id),
-          type_const_id)) {
+
+  // The self type of the impl must match the type in the query, or this is an
+  // `impl T as ...` for some other type `T` and should not be considered.
+  auto deduced_self_const_id = SemIR::GetConstantValueInSpecific(
+      context.sem_ir(), specific_id, impl.self_id);
+  if (type_const_id != deduced_self_const_id) {
     return SemIR::InstId::None;
   }
-  if (!context.constant_values().AreEqualAcrossDeclarations(
-          SemIR::GetConstantValueInSpecific(context.sem_ir(), specific_id,
-                                            impl.constraint_id),
-          interface_const_id)) {
-    // TODO: An impl of a constraint type should be treated as implementing
-    // the constraint's interfaces.
+
+  // The impl's constraint is a facet type which it is implementing for the self
+  // type: the `I` in `impl ... as I`. The deduction step may be unable to be
+  // fully applied to the types in the constraint and result in an error here,
+  // in which case it does not match the query.
+  auto deduced_constraint_id =
+      context.constant_values().GetInstId(SemIR::GetConstantValueInSpecific(
+          context.sem_ir(), specific_id, impl.constraint_id));
+  if (deduced_constraint_id == SemIR::ErrorInst::SingletonInstId) {
     return SemIR::InstId::None;
   }
-  if (!impl.witness_id.has_value()) {
-    // TODO: Diagnose if the impl isn't defined yet?
+
+  auto deduced_constraint_facet_type_id =
+      context.insts()
+          .GetAs<SemIR::FacetType>(deduced_constraint_id)
+          .facet_type_id;
+  const auto& deduced_constraint_complete_facet_type =
+      context.complete_facet_types().Get(
+          context.complete_facet_types().TryGetId(
+              deduced_constraint_facet_type_id));
+  CARBON_CHECK(deduced_constraint_complete_facet_type.num_to_impl == 1);
+
+  if (context.facet_types()
+          .Get(deduced_constraint_facet_type_id)
+          .other_requirements) {
+    // TODO: Remove this when other requirements goes away.
     return SemIR::InstId::None;
   }
+
+  // The specifics in the queried interface must match the deduced specifics in
+  // the impl's constraint facet type.
+  auto impl_interface_specific_id =
+      deduced_constraint_complete_facet_type.required_interfaces[0].specific_id;
+  auto query_interface_specific_id = interface.specific_id;
+  if (impl_interface_specific_id != query_interface_specific_id) {
+    return SemIR::InstId::None;
+  }
+
   LoadImportRef(context, impl.witness_id);
   if (specific_id.has_value()) {
     // We need a definition of the specific `impl` so we can access its
@@ -292,28 +322,73 @@ auto LookupImplWitness(Context& context, SemIR::LocId loc_id,
     return SemIR::ErrorInst::SingletonInstId;
   }
 
-  auto interface_id =
-      GetInterfaceIdFromConstantId(context, loc_id, interface_const_id);
+  bool has_other_requirements = false;
+  auto interfaces = GetInterfacesFromConstantId(
+      context, loc_id, interface_const_id, has_other_requirements);
+  if (interfaces.empty()) {
+    // TODO: Remove this when the context.TODO() is removed in
+    // GetInterfacesFromConstantId.
+    return SemIR::InstId::None;
+  }
+  if (has_other_requirements) {
+    // TODO: Remove this when other requirements go away.
+    return SemIR::InstId::None;
+  }
 
-  auto result_witness_id = SemIR::InstId::None;
+  llvm::SmallVector<SemIR::InstId> result_witness_ids;
 
   auto& stack = context.impl_lookup_stack();
   stack.push_back({
       .type_const_id = type_const_id,
       .interface_const_id = interface_const_id,
   });
-  for (const auto& impl : context.impls().array_ref()) {
-    stack.back().impl_loc = impl.definition_id;
-    result_witness_id = GetWitnessIdForImpl(
-        context, loc_id, type_const_id, interface_const_id, interface_id, impl);
-    if (result_witness_id.has_value()) {
-      // We found a matching impl, don't keep looking.
+  // We need to find a witness for each interface in `interfaces`. We return
+  // them in the same order as they are found in the `CompleteFacetType`, which
+  // is the same order as in `interfaces` here.
+  for (const auto& interface : interfaces) {
+    bool found_witness = false;
+    for (const auto& impl : context.impls().array_ref()) {
+      stack.back().impl_loc = impl.definition_id;
+      auto result_witness_id =
+          GetWitnessIdForImpl(context, loc_id, type_const_id, interface, impl);
+      if (result_witness_id.has_value()) {
+        result_witness_ids.push_back(result_witness_id);
+        // We found a matching impl; don't keep looking for this `interface`,
+        // move onto the next.
+        found_witness = true;
+        break;
+      }
+    }
+    if (!found_witness) {
+      // At least one queried interface in the facet type has no witness for the
+      // given type, we can stop looking for more.
       break;
     }
   }
   stack.pop_back();
 
-  return result_witness_id;
+  // All interfaces in the query facet type must have been found to be available
+  // through some impl (TODO: or directly on the type itself if `type_const_id`
+  // is a facet type).
+  if (result_witness_ids.size() != interfaces.size()) {
+    return SemIR::InstId::None;
+  }
+
+  // TODO: Return the whole set as a (newly introduced) FacetTypeWitness
+  // instruction. For now we just return a single witness instruction which
+  // doesn't matter because it essentially goes unused anyway. So far this
+  // method is just used as a boolean test in cases where there can be more than
+  // one interface in the query facet type:
+  // - Concrete facet values (`({} as C) as (C as (A & B))`) are looked through
+  //   to the implementing type (typically a ClassType) to access members, and
+  //   thus don't use the witnesses in the facet value.
+  // - Compound member lookup (`G.(A & B).F()`) uses name lookup to find the
+  //   interface first, then does impl lookup for a witness with a single
+  //   interface query. It's also only possible on concrete facet values so far
+  //   (see below).
+  // - Qualified name lookup on symbolic facet values (`T:! A & B`) doesn't work
+  //   at all, so never gets to looking for a witness.
+  return result_witness_ids[0];
 }
 
 }  // namespace Carbon::Check

+ 1003 - 92
toolchain/check/testdata/builtin_conversions/no_prelude/convert_class_value_to_generic_facet_value_value.carbon

@@ -33,12 +33,83 @@ impl ImplsGeneric as Generic(GenericParam) {
   fn F() {}
 }
 
-fn CallGenericMethod2[T:! type, U:! Generic(T)](a: U, s: T) {
+fn CallGenericMethod[T:! type, U:! Generic(T)](a: U, s: T) {
   U.F();
 }
 
 fn G() {
-  CallGenericMethod2({} as ImplsGeneric, {} as GenericParam);
+  CallGenericMethod({} as ImplsGeneric, {} as GenericParam);
+}
+
+// --- multiple_generic_params_one_fixed_one_deduced.carbon
+library "[[@TEST_NAME]]";
+
+import Core;
+
+interface I(V:! type, W:! type) {}
+
+class C {}
+
+impl forall [T:! type] C as I(T, ()) {}
+
+fn A[T:! I({}, ())](t: T) {}
+
+fn B() {
+  A({} as C);
+}
+
+// --- fail_mismatch_impl_constraint_with_fixed_specific.carbon
+library "[[@TEST_NAME]]";
+
+import Core;
+
+interface I(V:! type, W:! type) {}
+
+class C {}
+
+impl forall [T:! type] C as I(T, ()) {}
+
+fn A[T:! I({}, {})](t: T) {}
+
+fn B() {
+  // CHECK:STDERR: fail_mismatch_impl_constraint_with_fixed_specific.carbon:[[@LINE+10]]:3: error: cannot implicitly convert value of type `type` to `I({}, {})` [ImplicitAsConversionFailure]
+  // CHECK:STDERR:   A({} as C);
+  // CHECK:STDERR:   ^~~~~~~~~~
+  // CHECK:STDERR: fail_mismatch_impl_constraint_with_fixed_specific.carbon:[[@LINE+7]]:3: note: type `type` does not implement interface `Core.ImplicitAs(I({}, {}))` [MissingImplInMemberAccessNote]
+  // CHECK:STDERR:   A({} as C);
+  // CHECK:STDERR:   ^~~~~~~~~~
+  // CHECK:STDERR: fail_mismatch_impl_constraint_with_fixed_specific.carbon:[[@LINE-9]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
+  // CHECK:STDERR: fn A[T:! I({}, {})](t: T) {}
+  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~
+  // CHECK:STDERR:
+  A({} as C);
+}
+
+// --- fail_mismatch_impl_self_with_fixed_specific.carbon
+library "[[@TEST_NAME]]";
+
+import Core;
+
+interface I {}
+
+class C(V:! type, W:! type) {}
+
+impl forall [T:! type] C(T, ()) as I {}
+
+fn A[T:! I](t: T) {}
+
+fn B() {
+  // CHECK:STDERR: fail_mismatch_impl_self_with_fixed_specific.carbon:[[@LINE+10]]:3: error: cannot implicitly convert value of type `type` to `I` [ImplicitAsConversionFailure]
+  // CHECK:STDERR:   A({} as C({}, {}));
+  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~
+  // CHECK:STDERR: fail_mismatch_impl_self_with_fixed_specific.carbon:[[@LINE+7]]:3: note: type `type` does not implement interface `Core.ImplicitAs(I)` [MissingImplInMemberAccessNote]
+  // CHECK:STDERR:   A({} as C({}, {}));
+  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~
+  // CHECK:STDERR: fail_mismatch_impl_self_with_fixed_specific.carbon:[[@LINE-9]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
+  // CHECK:STDERR: fn A[T:! I](t: T) {}
+  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~
+  // CHECK:STDERR:
+  A({} as C({}, {}));
 }
 
 // CHECK:STDOUT: --- core.carbon
@@ -168,8 +239,8 @@ fn G() {
 // CHECK:STDOUT:   %U: %Generic.type.91ccba.2 = bind_symbolic_name U, 1 [symbolic]
 // CHECK:STDOUT:   %U.patt: %Generic.type.91ccba.2 = symbolic_binding_pattern U, 1 [symbolic]
 // CHECK:STDOUT:   %U.as_type: type = facet_access_type %U [symbolic]
-// CHECK:STDOUT:   %CallGenericMethod2.type: type = fn_type @CallGenericMethod2 [concrete]
-// CHECK:STDOUT:   %CallGenericMethod2: %CallGenericMethod2.type = struct_value () [concrete]
+// CHECK:STDOUT:   %CallGenericMethod.type: type = fn_type @CallGenericMethod [concrete]
+// CHECK:STDOUT:   %CallGenericMethod: %CallGenericMethod.type = struct_value () [concrete]
 // CHECK:STDOUT:   %require_complete.7b2: <witness> = require_complete_type %U.as_type [symbolic]
 // CHECK:STDOUT:   %require_complete.4ae: <witness> = require_complete_type %T [symbolic]
 // CHECK:STDOUT:   %F.type.f439a9.2: type = fn_type @F.1, @Generic(%T) [symbolic]
@@ -186,7 +257,7 @@ fn G() {
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %ImplsGeneric.val: %ImplsGeneric = struct_value () [concrete]
 // CHECK:STDOUT:   %GenericParam.val: %GenericParam = struct_value () [concrete]
-// CHECK:STDOUT:   %CallGenericMethod2.specific_fn: <specific function> = specific_function %CallGenericMethod2, @CallGenericMethod2(%GenericParam, %Generic.facet.b0a) [concrete]
+// CHECK:STDOUT:   %CallGenericMethod.specific_fn: <specific function> = specific_function %CallGenericMethod, @CallGenericMethod(%GenericParam, %Generic.facet.b0a) [concrete]
 // CHECK:STDOUT:   %complete_type.997: <witness> = complete_type_witness %Generic.type.769 [concrete]
 // CHECK:STDOUT:   %.db1: type = fn_type_with_self_type %F.type.4cf, %Generic.facet.b0a [concrete]
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.a56, @F.1(%GenericParam, %Generic.facet.b0a) [concrete]
@@ -204,7 +275,7 @@ fn G() {
 // CHECK:STDOUT:     .Generic = %Generic.decl
 // CHECK:STDOUT:     .GenericParam = %GenericParam.decl
 // CHECK:STDOUT:     .ImplsGeneric = %ImplsGeneric.decl
-// CHECK:STDOUT:     .CallGenericMethod2 = %CallGenericMethod2.decl
+// CHECK:STDOUT:     .CallGenericMethod = %CallGenericMethod.decl
 // CHECK:STDOUT:     .G = %G.decl
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
@@ -222,31 +293,31 @@ fn G() {
 // CHECK:STDOUT:     %Generic.type: type = facet_type <@Generic, @Generic(constants.%GenericParam)> [concrete = constants.%Generic.type.769]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %impl_witness: <witness> = impl_witness (@impl.%F.decl) [concrete = constants.%impl_witness]
-// CHECK:STDOUT:   %CallGenericMethod2.decl: %CallGenericMethod2.type = fn_decl @CallGenericMethod2 [concrete = constants.%CallGenericMethod2] {
-// CHECK:STDOUT:     %T.patt.loc17_23.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc17_23.2 (constants.%T.patt)]
-// CHECK:STDOUT:     %U.patt.loc17_33.1: @CallGenericMethod2.%Generic.type.loc17_46.2 (%Generic.type.91ccba.2) = symbolic_binding_pattern U, 1 [symbolic = %U.patt.loc17_33.2 (constants.%U.patt)]
-// CHECK:STDOUT:     %a.patt: @CallGenericMethod2.%U.as_type.loc17_52.2 (%U.as_type) = binding_pattern a
-// CHECK:STDOUT:     %a.param_patt: @CallGenericMethod2.%U.as_type.loc17_52.2 (%U.as_type) = value_param_pattern %a.patt, call_param0
-// CHECK:STDOUT:     %s.patt: @CallGenericMethod2.%T.loc17_23.2 (%T) = binding_pattern s
-// CHECK:STDOUT:     %s.param_patt: @CallGenericMethod2.%T.loc17_23.2 (%T) = value_param_pattern %s.patt, call_param1
+// CHECK:STDOUT:   %CallGenericMethod.decl: %CallGenericMethod.type = fn_decl @CallGenericMethod [concrete = constants.%CallGenericMethod] {
+// CHECK:STDOUT:     %T.patt.loc17_22.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc17_22.2 (constants.%T.patt)]
+// CHECK:STDOUT:     %U.patt.loc17_32.1: @CallGenericMethod.%Generic.type.loc17_45.2 (%Generic.type.91ccba.2) = symbolic_binding_pattern U, 1 [symbolic = %U.patt.loc17_32.2 (constants.%U.patt)]
+// CHECK:STDOUT:     %a.patt: @CallGenericMethod.%U.as_type.loc17_51.2 (%U.as_type) = binding_pattern a
+// CHECK:STDOUT:     %a.param_patt: @CallGenericMethod.%U.as_type.loc17_51.2 (%U.as_type) = value_param_pattern %a.patt, call_param0
+// CHECK:STDOUT:     %s.patt: @CallGenericMethod.%T.loc17_22.2 (%T) = binding_pattern s
+// CHECK:STDOUT:     %s.param_patt: @CallGenericMethod.%T.loc17_22.2 (%T) = value_param_pattern %s.patt, call_param1
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.loc17_23.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc17_23.2 (constants.%T)]
-// CHECK:STDOUT:     %.loc17_46: type = splice_block %Generic.type.loc17_46.1 [symbolic = %Generic.type.loc17_46.2 (constants.%Generic.type.91ccba.2)] {
+// CHECK:STDOUT:     %T.loc17_22.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc17_22.2 (constants.%T)]
+// CHECK:STDOUT:     %.loc17_45: type = splice_block %Generic.type.loc17_45.1 [symbolic = %Generic.type.loc17_45.2 (constants.%Generic.type.91ccba.2)] {
 // CHECK:STDOUT:       %Generic.ref: %Generic.type.c21 = name_ref Generic, file.%Generic.decl [concrete = constants.%Generic.generic]
-// CHECK:STDOUT:       %T.ref.loc17_45: type = name_ref T, %T.loc17_23.1 [symbolic = %T.loc17_23.2 (constants.%T)]
-// CHECK:STDOUT:       %Generic.type.loc17_46.1: type = facet_type <@Generic, @Generic(constants.%T)> [symbolic = %Generic.type.loc17_46.2 (constants.%Generic.type.91ccba.2)]
+// CHECK:STDOUT:       %T.ref.loc17_44: type = name_ref T, %T.loc17_22.1 [symbolic = %T.loc17_22.2 (constants.%T)]
+// CHECK:STDOUT:       %Generic.type.loc17_45.1: type = facet_type <@Generic, @Generic(constants.%T)> [symbolic = %Generic.type.loc17_45.2 (constants.%Generic.type.91ccba.2)]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %U.loc17_33.1: @CallGenericMethod2.%Generic.type.loc17_46.2 (%Generic.type.91ccba.2) = bind_symbolic_name U, 1 [symbolic = %U.loc17_33.2 (constants.%U)]
-// CHECK:STDOUT:     %a.param: @CallGenericMethod2.%U.as_type.loc17_52.2 (%U.as_type) = value_param call_param0
-// CHECK:STDOUT:     %.loc17_52.1: type = splice_block %.loc17_52.2 [symbolic = %U.as_type.loc17_52.2 (constants.%U.as_type)] {
-// CHECK:STDOUT:       %U.ref.loc17: @CallGenericMethod2.%Generic.type.loc17_46.2 (%Generic.type.91ccba.2) = name_ref U, %U.loc17_33.1 [symbolic = %U.loc17_33.2 (constants.%U)]
-// CHECK:STDOUT:       %U.as_type.loc17_52.1: type = facet_access_type %U.ref.loc17 [symbolic = %U.as_type.loc17_52.2 (constants.%U.as_type)]
-// CHECK:STDOUT:       %.loc17_52.2: type = converted %U.ref.loc17, %U.as_type.loc17_52.1 [symbolic = %U.as_type.loc17_52.2 (constants.%U.as_type)]
+// CHECK:STDOUT:     %U.loc17_32.1: @CallGenericMethod.%Generic.type.loc17_45.2 (%Generic.type.91ccba.2) = bind_symbolic_name U, 1 [symbolic = %U.loc17_32.2 (constants.%U)]
+// CHECK:STDOUT:     %a.param: @CallGenericMethod.%U.as_type.loc17_51.2 (%U.as_type) = value_param call_param0
+// CHECK:STDOUT:     %.loc17_51.1: type = splice_block %.loc17_51.2 [symbolic = %U.as_type.loc17_51.2 (constants.%U.as_type)] {
+// CHECK:STDOUT:       %U.ref.loc17: @CallGenericMethod.%Generic.type.loc17_45.2 (%Generic.type.91ccba.2) = name_ref U, %U.loc17_32.1 [symbolic = %U.loc17_32.2 (constants.%U)]
+// CHECK:STDOUT:       %U.as_type.loc17_51.1: type = facet_access_type %U.ref.loc17 [symbolic = %U.as_type.loc17_51.2 (constants.%U.as_type)]
+// CHECK:STDOUT:       %.loc17_51.2: type = converted %U.ref.loc17, %U.as_type.loc17_51.1 [symbolic = %U.as_type.loc17_51.2 (constants.%U.as_type)]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %a: @CallGenericMethod2.%U.as_type.loc17_52.2 (%U.as_type) = bind_name a, %a.param
-// CHECK:STDOUT:     %s.param: @CallGenericMethod2.%T.loc17_23.2 (%T) = value_param call_param1
-// CHECK:STDOUT:     %T.ref.loc17_58: type = name_ref T, %T.loc17_23.1 [symbolic = %T.loc17_23.2 (constants.%T)]
-// CHECK:STDOUT:     %s: @CallGenericMethod2.%T.loc17_23.2 (%T) = bind_name s, %s.param
+// CHECK:STDOUT:     %a: @CallGenericMethod.%U.as_type.loc17_51.2 (%U.as_type) = bind_name a, %a.param
+// CHECK:STDOUT:     %s.param: @CallGenericMethod.%T.loc17_22.2 (%T) = value_param call_param1
+// CHECK:STDOUT:     %T.ref.loc17_57: type = name_ref T, %T.loc17_22.1 [symbolic = %T.loc17_22.2 (constants.%T)]
+// CHECK:STDOUT:     %s: @CallGenericMethod.%T.loc17_22.2 (%T) = bind_name s, %s.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}
 // CHECK:STDOUT: }
@@ -308,36 +379,36 @@ fn G() {
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: generic fn @CallGenericMethod2(%T.loc17_23.1: type, %U.loc17_33.1: @CallGenericMethod2.%Generic.type.loc17_46.2 (%Generic.type.91ccba.2)) {
-// CHECK:STDOUT:   %T.loc17_23.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc17_23.2 (constants.%T)]
-// CHECK:STDOUT:   %T.patt.loc17_23.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc17_23.2 (constants.%T.patt)]
-// CHECK:STDOUT:   %Generic.type.loc17_46.2: type = facet_type <@Generic, @Generic(%T.loc17_23.2)> [symbolic = %Generic.type.loc17_46.2 (constants.%Generic.type.91ccba.2)]
-// CHECK:STDOUT:   %U.loc17_33.2: %Generic.type.91ccba.2 = bind_symbolic_name U, 1 [symbolic = %U.loc17_33.2 (constants.%U)]
-// CHECK:STDOUT:   %U.patt.loc17_33.2: %Generic.type.91ccba.2 = symbolic_binding_pattern U, 1 [symbolic = %U.patt.loc17_33.2 (constants.%U.patt)]
-// CHECK:STDOUT:   %U.as_type.loc17_52.2: type = facet_access_type %U.loc17_33.2 [symbolic = %U.as_type.loc17_52.2 (constants.%U.as_type)]
+// CHECK:STDOUT: generic fn @CallGenericMethod(%T.loc17_22.1: type, %U.loc17_32.1: @CallGenericMethod.%Generic.type.loc17_45.2 (%Generic.type.91ccba.2)) {
+// CHECK:STDOUT:   %T.loc17_22.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc17_22.2 (constants.%T)]
+// CHECK:STDOUT:   %T.patt.loc17_22.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc17_22.2 (constants.%T.patt)]
+// CHECK:STDOUT:   %Generic.type.loc17_45.2: type = facet_type <@Generic, @Generic(%T.loc17_22.2)> [symbolic = %Generic.type.loc17_45.2 (constants.%Generic.type.91ccba.2)]
+// CHECK:STDOUT:   %U.loc17_32.2: %Generic.type.91ccba.2 = bind_symbolic_name U, 1 [symbolic = %U.loc17_32.2 (constants.%U)]
+// CHECK:STDOUT:   %U.patt.loc17_32.2: %Generic.type.91ccba.2 = symbolic_binding_pattern U, 1 [symbolic = %U.patt.loc17_32.2 (constants.%U.patt)]
+// CHECK:STDOUT:   %U.as_type.loc17_51.2: type = facet_access_type %U.loc17_32.2 [symbolic = %U.as_type.loc17_51.2 (constants.%U.as_type)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete.loc17_50: <witness> = require_complete_type @CallGenericMethod2.%U.as_type.loc17_52.2 (%U.as_type) [symbolic = %require_complete.loc17_50 (constants.%require_complete.7b2)]
-// CHECK:STDOUT:   %require_complete.loc17_56: <witness> = require_complete_type @CallGenericMethod2.%T.loc17_23.2 (%T) [symbolic = %require_complete.loc17_56 (constants.%require_complete.4ae)]
-// CHECK:STDOUT:   %require_complete.loc18: <witness> = require_complete_type @CallGenericMethod2.%Generic.type.loc17_46.2 (%Generic.type.91ccba.2) [symbolic = %require_complete.loc18 (constants.%require_complete.02a)]
-// CHECK:STDOUT:   %Generic.assoc_type: type = assoc_entity_type @CallGenericMethod2.%Generic.type.loc17_46.2 (%Generic.type.91ccba.2) [symbolic = %Generic.assoc_type (constants.%Generic.assoc_type.de973d.2)]
-// CHECK:STDOUT:   %assoc0: @CallGenericMethod2.%Generic.assoc_type (%Generic.assoc_type.de973d.2) = assoc_entity element0, @Generic.%F.decl [symbolic = %assoc0 (constants.%assoc0.29ce53.2)]
-// CHECK:STDOUT:   %U.as_wit.loc18_4.2: <witness> = facet_access_witness %U.loc17_33.2 [symbolic = %U.as_wit.loc18_4.2 (constants.%U.as_wit)]
-// CHECK:STDOUT:   %F.type: type = fn_type @F.1, @Generic(%T.loc17_23.2) [symbolic = %F.type (constants.%F.type.f439a9.2)]
-// CHECK:STDOUT:   %Generic.facet: @CallGenericMethod2.%Generic.type.loc17_46.2 (%Generic.type.91ccba.2) = facet_value %U.as_type.loc17_52.2, %U.as_wit.loc18_4.2 [symbolic = %Generic.facet (constants.%Generic.facet.2ea)]
+// CHECK:STDOUT:   %require_complete.loc17_49: <witness> = require_complete_type @CallGenericMethod.%U.as_type.loc17_51.2 (%U.as_type) [symbolic = %require_complete.loc17_49 (constants.%require_complete.7b2)]
+// CHECK:STDOUT:   %require_complete.loc17_55: <witness> = require_complete_type @CallGenericMethod.%T.loc17_22.2 (%T) [symbolic = %require_complete.loc17_55 (constants.%require_complete.4ae)]
+// CHECK:STDOUT:   %require_complete.loc18: <witness> = require_complete_type @CallGenericMethod.%Generic.type.loc17_45.2 (%Generic.type.91ccba.2) [symbolic = %require_complete.loc18 (constants.%require_complete.02a)]
+// CHECK:STDOUT:   %Generic.assoc_type: type = assoc_entity_type @CallGenericMethod.%Generic.type.loc17_45.2 (%Generic.type.91ccba.2) [symbolic = %Generic.assoc_type (constants.%Generic.assoc_type.de973d.2)]
+// CHECK:STDOUT:   %assoc0: @CallGenericMethod.%Generic.assoc_type (%Generic.assoc_type.de973d.2) = assoc_entity element0, @Generic.%F.decl [symbolic = %assoc0 (constants.%assoc0.29ce53.2)]
+// CHECK:STDOUT:   %U.as_wit.loc18_4.2: <witness> = facet_access_witness %U.loc17_32.2 [symbolic = %U.as_wit.loc18_4.2 (constants.%U.as_wit)]
+// CHECK:STDOUT:   %F.type: type = fn_type @F.1, @Generic(%T.loc17_22.2) [symbolic = %F.type (constants.%F.type.f439a9.2)]
+// CHECK:STDOUT:   %Generic.facet: @CallGenericMethod.%Generic.type.loc17_45.2 (%Generic.type.91ccba.2) = facet_value %U.as_type.loc17_51.2, %U.as_wit.loc18_4.2 [symbolic = %Generic.facet (constants.%Generic.facet.2ea)]
 // CHECK:STDOUT:   %.loc18_4.3: type = fn_type_with_self_type %F.type, %Generic.facet [symbolic = %.loc18_4.3 (constants.%.da8)]
-// CHECK:STDOUT:   %impl.elem0.loc18_4.2: @CallGenericMethod2.%.loc18_4.3 (%.da8) = impl_witness_access %U.as_wit.loc18_4.2, element0 [symbolic = %impl.elem0.loc18_4.2 (constants.%impl.elem0)]
-// CHECK:STDOUT:   %specific_fn.loc18_4.2: <specific function> = specific_function %impl.elem0.loc18_4.2, @F.1(%T.loc17_23.2, %Generic.facet) [symbolic = %specific_fn.loc18_4.2 (constants.%specific_fn)]
+// CHECK:STDOUT:   %impl.elem0.loc18_4.2: @CallGenericMethod.%.loc18_4.3 (%.da8) = impl_witness_access %U.as_wit.loc18_4.2, element0 [symbolic = %impl.elem0.loc18_4.2 (constants.%impl.elem0)]
+// CHECK:STDOUT:   %specific_fn.loc18_4.2: <specific function> = specific_function %impl.elem0.loc18_4.2, @F.1(%T.loc17_22.2, %Generic.facet) [symbolic = %specific_fn.loc18_4.2 (constants.%specific_fn)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn[%T.patt.loc17_23.1: type, %U.patt.loc17_33.1: @CallGenericMethod2.%Generic.type.loc17_46.2 (%Generic.type.91ccba.2)](%a.param_patt: @CallGenericMethod2.%U.as_type.loc17_52.2 (%U.as_type), %s.param_patt: @CallGenericMethod2.%T.loc17_23.2 (%T)) {
+// CHECK:STDOUT:   fn[%T.patt.loc17_22.1: type, %U.patt.loc17_32.1: @CallGenericMethod.%Generic.type.loc17_45.2 (%Generic.type.91ccba.2)](%a.param_patt: @CallGenericMethod.%U.as_type.loc17_51.2 (%U.as_type), %s.param_patt: @CallGenericMethod.%T.loc17_22.2 (%T)) {
 // CHECK:STDOUT:   !entry:
-// CHECK:STDOUT:     %U.ref.loc18: @CallGenericMethod2.%Generic.type.loc17_46.2 (%Generic.type.91ccba.2) = name_ref U, %U.loc17_33.1 [symbolic = %U.loc17_33.2 (constants.%U)]
-// CHECK:STDOUT:     %.loc18_4.1: @CallGenericMethod2.%Generic.assoc_type (%Generic.assoc_type.de973d.2) = specific_constant @Generic.%assoc0.loc7_9.1, @Generic(constants.%T) [symbolic = %assoc0 (constants.%assoc0.29ce53.2)]
-// CHECK:STDOUT:     %F.ref: @CallGenericMethod2.%Generic.assoc_type (%Generic.assoc_type.de973d.2) = name_ref F, %.loc18_4.1 [symbolic = %assoc0 (constants.%assoc0.29ce53.2)]
-// CHECK:STDOUT:     %U.as_type.loc18: type = facet_access_type %U.ref.loc18 [symbolic = %U.as_type.loc17_52.2 (constants.%U.as_type)]
-// CHECK:STDOUT:     %.loc18_4.2: type = converted %U.ref.loc18, %U.as_type.loc18 [symbolic = %U.as_type.loc17_52.2 (constants.%U.as_type)]
+// CHECK:STDOUT:     %U.ref.loc18: @CallGenericMethod.%Generic.type.loc17_45.2 (%Generic.type.91ccba.2) = name_ref U, %U.loc17_32.1 [symbolic = %U.loc17_32.2 (constants.%U)]
+// CHECK:STDOUT:     %.loc18_4.1: @CallGenericMethod.%Generic.assoc_type (%Generic.assoc_type.de973d.2) = specific_constant @Generic.%assoc0.loc7_9.1, @Generic(constants.%T) [symbolic = %assoc0 (constants.%assoc0.29ce53.2)]
+// CHECK:STDOUT:     %F.ref: @CallGenericMethod.%Generic.assoc_type (%Generic.assoc_type.de973d.2) = name_ref F, %.loc18_4.1 [symbolic = %assoc0 (constants.%assoc0.29ce53.2)]
+// CHECK:STDOUT:     %U.as_type.loc18: type = facet_access_type %U.ref.loc18 [symbolic = %U.as_type.loc17_51.2 (constants.%U.as_type)]
+// CHECK:STDOUT:     %.loc18_4.2: type = converted %U.ref.loc18, %U.as_type.loc18 [symbolic = %U.as_type.loc17_51.2 (constants.%U.as_type)]
 // CHECK:STDOUT:     %U.as_wit.loc18_4.1: <witness> = facet_access_witness %U.ref.loc18 [symbolic = %U.as_wit.loc18_4.2 (constants.%U.as_wit)]
-// CHECK:STDOUT:     %impl.elem0.loc18_4.1: @CallGenericMethod2.%.loc18_4.3 (%.da8) = impl_witness_access %U.as_wit.loc18_4.1, element0 [symbolic = %impl.elem0.loc18_4.2 (constants.%impl.elem0)]
+// CHECK:STDOUT:     %impl.elem0.loc18_4.1: @CallGenericMethod.%.loc18_4.3 (%.da8) = impl_witness_access %U.as_wit.loc18_4.1, element0 [symbolic = %impl.elem0.loc18_4.2 (constants.%impl.elem0)]
 // CHECK:STDOUT:     %specific_fn.loc18_4.1: <specific function> = specific_function %impl.elem0.loc18_4.1, @F.1(constants.%T, constants.%Generic.facet.2ea) [symbolic = %specific_fn.loc18_4.2 (constants.%specific_fn)]
 // CHECK:STDOUT:     %F.call: init %empty_tuple.type = call %specific_fn.loc18_4.1()
 // CHECK:STDOUT:     return
@@ -346,25 +417,25 @@ fn G() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @G() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %CallGenericMethod2.ref: %CallGenericMethod2.type = name_ref CallGenericMethod2, file.%CallGenericMethod2.decl [concrete = constants.%CallGenericMethod2]
-// CHECK:STDOUT:   %.loc22_23.1: %empty_struct_type = struct_literal ()
+// CHECK:STDOUT:   %CallGenericMethod.ref: %CallGenericMethod.type = name_ref CallGenericMethod, file.%CallGenericMethod.decl [concrete = constants.%CallGenericMethod]
+// CHECK:STDOUT:   %.loc22_22.1: %empty_struct_type = struct_literal ()
 // CHECK:STDOUT:   %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric]
-// CHECK:STDOUT:   %.loc22_23.2: ref %ImplsGeneric = temporary_storage
-// CHECK:STDOUT:   %.loc22_23.3: init %ImplsGeneric = class_init (), %.loc22_23.2 [concrete = constants.%ImplsGeneric.val]
-// CHECK:STDOUT:   %.loc22_23.4: ref %ImplsGeneric = temporary %.loc22_23.2, %.loc22_23.3
-// CHECK:STDOUT:   %.loc22_25.1: ref %ImplsGeneric = converted %.loc22_23.1, %.loc22_23.4
-// CHECK:STDOUT:   %.loc22_43.1: %empty_struct_type = struct_literal ()
+// CHECK:STDOUT:   %.loc22_22.2: ref %ImplsGeneric = temporary_storage
+// CHECK:STDOUT:   %.loc22_22.3: init %ImplsGeneric = class_init (), %.loc22_22.2 [concrete = constants.%ImplsGeneric.val]
+// CHECK:STDOUT:   %.loc22_22.4: ref %ImplsGeneric = temporary %.loc22_22.2, %.loc22_22.3
+// CHECK:STDOUT:   %.loc22_24.1: ref %ImplsGeneric = converted %.loc22_22.1, %.loc22_22.4
+// CHECK:STDOUT:   %.loc22_42.1: %empty_struct_type = struct_literal ()
 // CHECK:STDOUT:   %GenericParam.ref: type = name_ref GenericParam, file.%GenericParam.decl [concrete = constants.%GenericParam]
-// CHECK:STDOUT:   %.loc22_43.2: ref %GenericParam = temporary_storage
-// CHECK:STDOUT:   %.loc22_43.3: init %GenericParam = class_init (), %.loc22_43.2 [concrete = constants.%GenericParam.val]
-// CHECK:STDOUT:   %.loc22_43.4: ref %GenericParam = temporary %.loc22_43.2, %.loc22_43.3
-// CHECK:STDOUT:   %.loc22_45.1: ref %GenericParam = converted %.loc22_43.1, %.loc22_43.4
+// CHECK:STDOUT:   %.loc22_42.2: ref %GenericParam = temporary_storage
+// CHECK:STDOUT:   %.loc22_42.3: init %GenericParam = class_init (), %.loc22_42.2 [concrete = constants.%GenericParam.val]
+// CHECK:STDOUT:   %.loc22_42.4: ref %GenericParam = temporary %.loc22_42.2, %.loc22_42.3
+// CHECK:STDOUT:   %.loc22_44.1: ref %GenericParam = converted %.loc22_42.1, %.loc22_42.4
 // CHECK:STDOUT:   %Generic.facet: %Generic.type.769 = facet_value constants.%ImplsGeneric, constants.%impl_witness [concrete = constants.%Generic.facet.b0a]
-// CHECK:STDOUT:   %.loc22_60: %Generic.type.769 = converted constants.%ImplsGeneric, %Generic.facet [concrete = constants.%Generic.facet.b0a]
-// CHECK:STDOUT:   %CallGenericMethod2.specific_fn: <specific function> = specific_function %CallGenericMethod2.ref, @CallGenericMethod2(constants.%GenericParam, %.loc22_60) [concrete = constants.%CallGenericMethod2.specific_fn]
-// CHECK:STDOUT:   %.loc22_25.2: %ImplsGeneric = bind_value %.loc22_25.1
-// CHECK:STDOUT:   %.loc22_45.2: %GenericParam = bind_value %.loc22_45.1
-// CHECK:STDOUT:   %CallGenericMethod2.call: init %empty_tuple.type = call %CallGenericMethod2.specific_fn(%.loc22_25.2, %.loc22_45.2)
+// CHECK:STDOUT:   %.loc22_59: %Generic.type.769 = converted constants.%ImplsGeneric, %Generic.facet [concrete = constants.%Generic.facet.b0a]
+// CHECK:STDOUT:   %CallGenericMethod.specific_fn: <specific function> = specific_function %CallGenericMethod.ref, @CallGenericMethod(constants.%GenericParam, %.loc22_59) [concrete = constants.%CallGenericMethod.specific_fn]
+// CHECK:STDOUT:   %.loc22_24.2: %ImplsGeneric = bind_value %.loc22_24.1
+// CHECK:STDOUT:   %.loc22_44.2: %GenericParam = bind_value %.loc22_44.1
+// CHECK:STDOUT:   %CallGenericMethod.call: init %empty_tuple.type = call %CallGenericMethod.specific_fn(%.loc22_24.2, %.loc22_44.2)
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -405,32 +476,32 @@ fn G() {
 // CHECK:STDOUT:   %assoc0.loc7_9.2 => constants.%assoc0.29ce53.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @CallGenericMethod2(constants.%T, constants.%U) {
-// CHECK:STDOUT:   %T.loc17_23.2 => constants.%T
-// CHECK:STDOUT:   %T.patt.loc17_23.2 => constants.%T
-// CHECK:STDOUT:   %Generic.type.loc17_46.2 => constants.%Generic.type.91ccba.2
-// CHECK:STDOUT:   %U.loc17_33.2 => constants.%U
-// CHECK:STDOUT:   %U.patt.loc17_33.2 => constants.%U
-// CHECK:STDOUT:   %U.as_type.loc17_52.2 => constants.%U.as_type
+// CHECK:STDOUT: specific @CallGenericMethod(constants.%T, constants.%U) {
+// CHECK:STDOUT:   %T.loc17_22.2 => constants.%T
+// CHECK:STDOUT:   %T.patt.loc17_22.2 => constants.%T
+// CHECK:STDOUT:   %Generic.type.loc17_45.2 => constants.%Generic.type.91ccba.2
+// CHECK:STDOUT:   %U.loc17_32.2 => constants.%U
+// CHECK:STDOUT:   %U.patt.loc17_32.2 => constants.%U
+// CHECK:STDOUT:   %U.as_type.loc17_51.2 => constants.%U.as_type
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @Generic(@CallGenericMethod2.%T.loc17_23.2) {}
+// CHECK:STDOUT: specific @Generic(@CallGenericMethod.%T.loc17_22.2) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @F.1(constants.%T, constants.%Generic.facet.2ea) {}
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @F.1(@CallGenericMethod2.%T.loc17_23.2, @CallGenericMethod2.%Generic.facet) {}
+// CHECK:STDOUT: specific @F.1(@CallGenericMethod.%T.loc17_22.2, @CallGenericMethod.%Generic.facet) {}
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @CallGenericMethod2(constants.%GenericParam, @G.%.loc22_60) {
-// CHECK:STDOUT:   %T.loc17_23.2 => constants.%GenericParam
-// CHECK:STDOUT:   %T.patt.loc17_23.2 => constants.%GenericParam
-// CHECK:STDOUT:   %Generic.type.loc17_46.2 => constants.%Generic.type.769
-// CHECK:STDOUT:   %U.loc17_33.2 => constants.%Generic.facet.b0a
-// CHECK:STDOUT:   %U.patt.loc17_33.2 => constants.%Generic.facet.b0a
-// CHECK:STDOUT:   %U.as_type.loc17_52.2 => constants.%ImplsGeneric
+// CHECK:STDOUT: specific @CallGenericMethod(constants.%GenericParam, @G.%.loc22_59) {
+// CHECK:STDOUT:   %T.loc17_22.2 => constants.%GenericParam
+// CHECK:STDOUT:   %T.patt.loc17_22.2 => constants.%GenericParam
+// CHECK:STDOUT:   %Generic.type.loc17_45.2 => constants.%Generic.type.769
+// CHECK:STDOUT:   %U.loc17_32.2 => constants.%Generic.facet.b0a
+// CHECK:STDOUT:   %U.patt.loc17_32.2 => constants.%Generic.facet.b0a
+// CHECK:STDOUT:   %U.as_type.loc17_51.2 => constants.%ImplsGeneric
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete.loc17_50 => constants.%complete_type.357
-// CHECK:STDOUT:   %require_complete.loc17_56 => constants.%complete_type.357
+// CHECK:STDOUT:   %require_complete.loc17_49 => constants.%complete_type.357
+// CHECK:STDOUT:   %require_complete.loc17_55 => constants.%complete_type.357
 // CHECK:STDOUT:   %require_complete.loc18 => constants.%complete_type.997
 // CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.9f1
 // CHECK:STDOUT:   %assoc0 => constants.%assoc0.9b7
@@ -442,12 +513,852 @@ fn G() {
 // CHECK:STDOUT:   %specific_fn.loc18_4.2 => constants.%F.specific_fn
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @CallGenericMethod2(constants.%GenericParam, constants.%Generic.facet.b0a) {
-// CHECK:STDOUT:   %T.loc17_23.2 => constants.%GenericParam
-// CHECK:STDOUT:   %T.patt.loc17_23.2 => constants.%GenericParam
-// CHECK:STDOUT:   %Generic.type.loc17_46.2 => constants.%Generic.type.769
-// CHECK:STDOUT:   %U.loc17_33.2 => constants.%Generic.facet.b0a
-// CHECK:STDOUT:   %U.patt.loc17_33.2 => constants.%Generic.facet.b0a
-// CHECK:STDOUT:   %U.as_type.loc17_52.2 => constants.%ImplsGeneric
+// CHECK:STDOUT: specific @CallGenericMethod(constants.%GenericParam, constants.%Generic.facet.b0a) {
+// CHECK:STDOUT:   %T.loc17_22.2 => constants.%GenericParam
+// CHECK:STDOUT:   %T.patt.loc17_22.2 => constants.%GenericParam
+// CHECK:STDOUT:   %Generic.type.loc17_45.2 => constants.%Generic.type.769
+// CHECK:STDOUT:   %U.loc17_32.2 => constants.%Generic.facet.b0a
+// CHECK:STDOUT:   %U.patt.loc17_32.2 => constants.%Generic.facet.b0a
+// CHECK:STDOUT:   %U.as_type.loc17_51.2 => constants.%ImplsGeneric
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- multiple_generic_params_one_fixed_one_deduced.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %V: type = bind_symbolic_name V, 0 [symbolic]
+// CHECK:STDOUT:   %V.patt: type = symbolic_binding_pattern V, 0 [symbolic]
+// CHECK:STDOUT:   %W: type = bind_symbolic_name W, 1 [symbolic]
+// CHECK:STDOUT:   %W.patt: type = symbolic_binding_pattern W, 1 [symbolic]
+// CHECK:STDOUT:   %I.type.dac: type = generic_interface_type @I [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
+// CHECK:STDOUT:   %I.generic: %I.type.dac = struct_value () [concrete]
+// CHECK:STDOUT:   %I.type.f76: type = facet_type <@I, @I(%V, %W)> [symbolic]
+// CHECK:STDOUT:   %Self: %I.type.f76 = bind_symbolic_name Self, 2 [symbolic]
+// CHECK:STDOUT:   %C: type = class_type @C [concrete]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %T.8b3: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %T.patt.e01: type = symbolic_binding_pattern T, 0 [symbolic]
+// CHECK:STDOUT:   %I.type.bea: type = facet_type <@I, @I(%T.8b3, %empty_tuple.type)> [symbolic]
+// CHECK:STDOUT:   %require_complete.5ce: <witness> = require_complete_type %I.type.bea [symbolic]
+// CHECK:STDOUT:   %impl_witness.298: <witness> = impl_witness (), @impl(%T.8b3) [symbolic]
+// CHECK:STDOUT:   %I.type.202: type = facet_type <@I, @I(%empty_struct_type, %empty_tuple.type)> [concrete]
+// CHECK:STDOUT:   %T.e96: %I.type.202 = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %T.patt.5b9: %I.type.202 = symbolic_binding_pattern T, 0 [symbolic]
+// CHECK:STDOUT:   %T.as_type: type = facet_access_type %T.e96 [symbolic]
+// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]
+// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]
+// CHECK:STDOUT:   %require_complete.c8b: <witness> = require_complete_type %T.as_type [symbolic]
+// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]
+// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]
+// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]
+// CHECK:STDOUT:   %complete_type.3d9: <witness> = complete_type_witness %I.type.202 [concrete]
+// CHECK:STDOUT:   %impl_witness.e3d: <witness> = impl_witness (), @impl(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %I.facet: %I.type.202 = facet_value %C, %impl_witness.e3d [concrete]
+// CHECK:STDOUT:   %A.specific_fn: <specific function> = specific_function %A, @A(%I.facet) [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
+// CHECK:STDOUT:     import Core//default
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .Core = imports.%Core
+// CHECK:STDOUT:     .I = %I.decl
+// CHECK:STDOUT:     .C = %C.decl
+// CHECK:STDOUT:     .A = %A.decl
+// CHECK:STDOUT:     .B = %B.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   %I.decl: %I.type.dac = interface_decl @I [concrete = constants.%I.generic] {
+// CHECK:STDOUT:     %V.patt.loc5_13.1: type = symbolic_binding_pattern V, 0 [symbolic = %V.patt.loc5_13.2 (constants.%V.patt)]
+// CHECK:STDOUT:     %W.patt.loc5_23.1: type = symbolic_binding_pattern W, 1 [symbolic = %W.patt.loc5_23.2 (constants.%W.patt)]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %V.loc5_13.1: type = bind_symbolic_name V, 0 [symbolic = %V.loc5_13.2 (constants.%V)]
+// CHECK:STDOUT:     %W.loc5_23.1: type = bind_symbolic_name W, 1 [symbolic = %W.loc5_23.2 (constants.%W)]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
+// CHECK:STDOUT:   impl_decl @impl [concrete] {
+// CHECK:STDOUT:     %T.patt.loc9_14.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc9_14.2 (constants.%T.patt.e01)]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %I.ref: %I.type.dac = name_ref I, file.%I.decl [concrete = constants.%I.generic]
+// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc9_14.1 [symbolic = %T.loc9_14.2 (constants.%T.8b3)]
+// CHECK:STDOUT:     %.loc9_35: %empty_tuple.type = tuple_literal ()
+// CHECK:STDOUT:     %.loc9_36: type = converted %.loc9_35, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
+// CHECK:STDOUT:     %I.type.loc9_36.1: type = facet_type <@I, @I(constants.%T.8b3, constants.%empty_tuple.type)> [symbolic = %I.type.loc9_36.2 (constants.%I.type.bea)]
+// CHECK:STDOUT:     %T.loc9_14.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc9_14.2 (constants.%T.8b3)]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %impl_witness: <witness> = impl_witness (), @impl(constants.%T.8b3) [symbolic = @impl.%impl_witness (constants.%impl_witness.298)]
+// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {
+// CHECK:STDOUT:     %T.patt.loc11_6.1: %I.type.202 = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc11_6.2 (constants.%T.patt.5b9)]
+// CHECK:STDOUT:     %t.patt: @A.%T.as_type.loc11_24.2 (%T.as_type) = binding_pattern t
+// CHECK:STDOUT:     %t.param_patt: @A.%T.as_type.loc11_24.2 (%T.as_type) = value_param_pattern %t.patt, call_param0
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %.loc11_18.1: type = splice_block %I.type [concrete = constants.%I.type.202] {
+// CHECK:STDOUT:       %I.ref: %I.type.dac = name_ref I, file.%I.decl [concrete = constants.%I.generic]
+// CHECK:STDOUT:       %.loc11_13: %empty_struct_type = struct_literal ()
+// CHECK:STDOUT:       %.loc11_17: %empty_tuple.type = tuple_literal ()
+// CHECK:STDOUT:       %.loc11_18.2: type = converted %.loc11_13, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
+// CHECK:STDOUT:       %.loc11_18.3: type = converted %.loc11_17, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
+// CHECK:STDOUT:       %I.type: type = facet_type <@I, @I(constants.%empty_struct_type, constants.%empty_tuple.type)> [concrete = constants.%I.type.202]
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %T.loc11_6.1: %I.type.202 = bind_symbolic_name T, 0 [symbolic = %T.loc11_6.2 (constants.%T.e96)]
+// CHECK:STDOUT:     %t.param: @A.%T.as_type.loc11_24.2 (%T.as_type) = value_param call_param0
+// CHECK:STDOUT:     %.loc11_24.1: type = splice_block %.loc11_24.2 [symbolic = %T.as_type.loc11_24.2 (constants.%T.as_type)] {
+// CHECK:STDOUT:       %T.ref: %I.type.202 = name_ref T, %T.loc11_6.1 [symbolic = %T.loc11_6.2 (constants.%T.e96)]
+// CHECK:STDOUT:       %T.as_type.loc11_24.1: type = facet_access_type %T.ref [symbolic = %T.as_type.loc11_24.2 (constants.%T.as_type)]
+// CHECK:STDOUT:       %.loc11_24.2: type = converted %T.ref, %T.as_type.loc11_24.1 [symbolic = %T.as_type.loc11_24.2 (constants.%T.as_type)]
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %t: @A.%T.as_type.loc11_24.2 (%T.as_type) = bind_name t, %t.param
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {} {}
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic interface @I(%V.loc5_13.1: type, %W.loc5_23.1: type) {
+// CHECK:STDOUT:   %V.loc5_13.2: type = bind_symbolic_name V, 0 [symbolic = %V.loc5_13.2 (constants.%V)]
+// CHECK:STDOUT:   %V.patt.loc5_13.2: type = symbolic_binding_pattern V, 0 [symbolic = %V.patt.loc5_13.2 (constants.%V.patt)]
+// CHECK:STDOUT:   %W.loc5_23.2: type = bind_symbolic_name W, 1 [symbolic = %W.loc5_23.2 (constants.%W)]
+// CHECK:STDOUT:   %W.patt.loc5_23.2: type = symbolic_binding_pattern W, 1 [symbolic = %W.patt.loc5_23.2 (constants.%W.patt)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%V.loc5_13.2, %W.loc5_23.2)> [symbolic = %I.type (constants.%I.type.f76)]
+// CHECK:STDOUT:   %Self.2: %I.type.f76 = bind_symbolic_name Self, 2 [symbolic = %Self.2 (constants.%Self)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   interface {
+// CHECK:STDOUT:     %Self.1: @I.%I.type (%I.type.f76) = bind_symbolic_name Self, 2 [symbolic = %Self.2 (constants.%Self)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = %Self.1
+// CHECK:STDOUT:     witness = ()
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic impl @impl(%T.loc9_14.1: type) {
+// CHECK:STDOUT:   %T.loc9_14.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc9_14.2 (constants.%T.8b3)]
+// CHECK:STDOUT:   %T.patt.loc9_14.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc9_14.2 (constants.%T.patt.e01)]
+// CHECK:STDOUT:   %I.type.loc9_36.2: type = facet_type <@I, @I(%T.loc9_14.2, constants.%empty_tuple.type)> [symbolic = %I.type.loc9_36.2 (constants.%I.type.bea)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type @impl.%I.type.loc9_36.2 (%I.type.bea) [symbolic = %require_complete (constants.%require_complete.5ce)]
+// CHECK:STDOUT:   %impl_witness: <witness> = impl_witness (), @impl(%T.loc9_14.2) [symbolic = %impl_witness (constants.%impl_witness.298)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:
+// CHECK:STDOUT:   impl: %C.ref as %I.type.loc9_36.1 {
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     witness = file.%impl_witness
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357]
+// CHECK:STDOUT:   complete_type_witness = %complete_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = constants.%C
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @A(%T.loc11_6.1: %I.type.202) {
+// CHECK:STDOUT:   %T.loc11_6.2: %I.type.202 = bind_symbolic_name T, 0 [symbolic = %T.loc11_6.2 (constants.%T.e96)]
+// CHECK:STDOUT:   %T.patt.loc11_6.2: %I.type.202 = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc11_6.2 (constants.%T.patt.5b9)]
+// CHECK:STDOUT:   %T.as_type.loc11_24.2: type = facet_access_type %T.loc11_6.2 [symbolic = %T.as_type.loc11_24.2 (constants.%T.as_type)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type @A.%T.as_type.loc11_24.2 (%T.as_type) [symbolic = %require_complete (constants.%require_complete.c8b)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn[%T.patt.loc11_6.1: %I.type.202](%t.param_patt: @A.%T.as_type.loc11_24.2 (%T.as_type)) {
+// CHECK:STDOUT:   !entry:
+// CHECK:STDOUT:     return
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @B() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A]
+// CHECK:STDOUT:   %.loc14_6.1: %empty_struct_type = struct_literal ()
+// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:   %.loc14_6.2: ref %C = temporary_storage
+// CHECK:STDOUT:   %.loc14_6.3: init %C = class_init (), %.loc14_6.2 [concrete = constants.%C.val]
+// CHECK:STDOUT:   %.loc14_6.4: ref %C = temporary %.loc14_6.2, %.loc14_6.3
+// CHECK:STDOUT:   %.loc14_8.1: ref %C = converted %.loc14_6.1, %.loc14_6.4
+// CHECK:STDOUT:   %I.facet.loc14_12.1: %I.type.202 = facet_value constants.%C, constants.%impl_witness.e3d [concrete = constants.%I.facet]
+// CHECK:STDOUT:   %.loc14_12.1: %I.type.202 = converted constants.%C, %I.facet.loc14_12.1 [concrete = constants.%I.facet]
+// CHECK:STDOUT:   %I.facet.loc14_12.2: %I.type.202 = facet_value constants.%C, constants.%impl_witness.e3d [concrete = constants.%I.facet]
+// CHECK:STDOUT:   %.loc14_12.2: %I.type.202 = converted constants.%C, %I.facet.loc14_12.2 [concrete = constants.%I.facet]
+// CHECK:STDOUT:   %A.specific_fn: <specific function> = specific_function %A.ref, @A(constants.%I.facet) [concrete = constants.%A.specific_fn]
+// CHECK:STDOUT:   %.loc14_8.2: %C = bind_value %.loc14_8.1
+// CHECK:STDOUT:   %A.call: init %empty_tuple.type = call %A.specific_fn(%.loc14_8.2)
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(constants.%V, constants.%W) {
+// CHECK:STDOUT:   %V.loc5_13.2 => constants.%V
+// CHECK:STDOUT:   %V.patt.loc5_13.2 => constants.%V
+// CHECK:STDOUT:   %W.loc5_23.2 => constants.%W
+// CHECK:STDOUT:   %W.patt.loc5_23.2 => constants.%W
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(%V.loc5_13.2, %W.loc5_23.2) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(constants.%T.8b3, constants.%empty_tuple.type) {
+// CHECK:STDOUT:   %V.loc5_13.2 => constants.%T.8b3
+// CHECK:STDOUT:   %V.patt.loc5_13.2 => constants.%T.8b3
+// CHECK:STDOUT:   %W.loc5_23.2 => constants.%empty_tuple.type
+// CHECK:STDOUT:   %W.patt.loc5_23.2 => constants.%empty_tuple.type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type => constants.%I.type.bea
+// CHECK:STDOUT:   %Self.2 => constants.%Self
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @impl(constants.%T.8b3) {
+// CHECK:STDOUT:   %T.loc9_14.2 => constants.%T.8b3
+// CHECK:STDOUT:   %T.patt.loc9_14.2 => constants.%T.8b3
+// CHECK:STDOUT:   %I.type.loc9_36.2 => constants.%I.type.bea
+// CHECK:STDOUT:   %require_complete => constants.%require_complete.5ce
+// CHECK:STDOUT:   %impl_witness => constants.%impl_witness.298
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(@impl.%T.loc9_14.2, constants.%empty_tuple.type) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @impl(%T.loc9_14.2) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(constants.%empty_struct_type, constants.%empty_tuple.type) {
+// CHECK:STDOUT:   %V.loc5_13.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %V.patt.loc5_13.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %W.loc5_23.2 => constants.%empty_tuple.type
+// CHECK:STDOUT:   %W.patt.loc5_23.2 => constants.%empty_tuple.type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type => constants.%I.type.202
+// CHECK:STDOUT:   %Self.2 => constants.%Self
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @A(constants.%T.e96) {
+// CHECK:STDOUT:   %T.loc11_6.2 => constants.%T.e96
+// CHECK:STDOUT:   %T.patt.loc11_6.2 => constants.%T.e96
+// CHECK:STDOUT:   %T.as_type.loc11_24.2 => constants.%T.as_type
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @impl(constants.%empty_struct_type) {
+// CHECK:STDOUT:   %T.loc9_14.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %T.patt.loc9_14.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %I.type.loc9_36.2 => constants.%I.type.202
+// CHECK:STDOUT:   %require_complete => constants.%complete_type.3d9
+// CHECK:STDOUT:   %impl_witness => constants.%impl_witness.e3d
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @A(constants.%I.facet) {
+// CHECK:STDOUT:   %T.loc11_6.2 => constants.%I.facet
+// CHECK:STDOUT:   %T.patt.loc11_6.2 => constants.%I.facet
+// CHECK:STDOUT:   %T.as_type.loc11_24.2 => constants.%C
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %require_complete => constants.%complete_type.357
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- fail_mismatch_impl_constraint_with_fixed_specific.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %V: type = bind_symbolic_name V, 0 [symbolic]
+// CHECK:STDOUT:   %V.patt: type = symbolic_binding_pattern V, 0 [symbolic]
+// CHECK:STDOUT:   %W: type = bind_symbolic_name W, 1 [symbolic]
+// CHECK:STDOUT:   %W.patt: type = symbolic_binding_pattern W, 1 [symbolic]
+// CHECK:STDOUT:   %I.type.dac: type = generic_interface_type @I [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
+// CHECK:STDOUT:   %I.generic: %I.type.dac = struct_value () [concrete]
+// CHECK:STDOUT:   %I.type.f76: type = facet_type <@I, @I(%V, %W)> [symbolic]
+// CHECK:STDOUT:   %Self.770: %I.type.f76 = bind_symbolic_name Self, 2 [symbolic]
+// CHECK:STDOUT:   %C: type = class_type @C [concrete]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %T.8b3: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %T.patt.e01: type = symbolic_binding_pattern T, 0 [symbolic]
+// CHECK:STDOUT:   %I.type.bea: type = facet_type <@I, @I(%T.8b3, %empty_tuple.type)> [symbolic]
+// CHECK:STDOUT:   %require_complete.5ce: <witness> = require_complete_type %I.type.bea [symbolic]
+// CHECK:STDOUT:   %impl_witness.298: <witness> = impl_witness (), @impl(%T.8b3) [symbolic]
+// CHECK:STDOUT:   %I.type.906: type = facet_type <@I, @I(%empty_struct_type, %empty_struct_type)> [concrete]
+// CHECK:STDOUT:   %T.4b2: %I.type.906 = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %T.patt.6fc: %I.type.906 = symbolic_binding_pattern T, 0 [symbolic]
+// CHECK:STDOUT:   %T.as_type: type = facet_access_type %T.4b2 [symbolic]
+// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]
+// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]
+// CHECK:STDOUT:   %require_complete.d5b: <witness> = require_complete_type %T.as_type [symbolic]
+// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]
+// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]
+// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]
+// CHECK:STDOUT:   %I.type.202: type = facet_type <@I, @I(%empty_struct_type, %empty_tuple.type)> [concrete]
+// CHECK:STDOUT:   %complete_type.3d9: <witness> = complete_type_witness %I.type.202 [concrete]
+// CHECK:STDOUT:   %impl_witness.e3d: <witness> = impl_witness (), @impl(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.d62: type = facet_type <@ImplicitAs, @ImplicitAs(%T.8b3)> [symbolic]
+// CHECK:STDOUT:   %Self.519: %ImplicitAs.type.d62 = bind_symbolic_name Self, 1 [symbolic]
+// CHECK:STDOUT:   %Convert.type.275: type = fn_type @Convert, @ImplicitAs(%T.8b3) [symbolic]
+// CHECK:STDOUT:   %Convert.42e: %Convert.type.275 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Self.as_type: type = facet_access_type %Self.519 [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.assoc_type.837: type = assoc_entity_type %ImplicitAs.type.d62 [symbolic]
+// CHECK:STDOUT:   %assoc0.43db8b.1: %ImplicitAs.assoc_type.837 = assoc_entity element0, imports.%Core.import_ref.207961.1 [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.type.442: type = facet_type <@ImplicitAs, @ImplicitAs(%I.type.906)> [concrete]
+// CHECK:STDOUT:   %Convert.type.b43: type = fn_type @Convert, @ImplicitAs(%I.type.906) [concrete]
+// CHECK:STDOUT:   %Convert.2fc: %Convert.type.b43 = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.assoc_type.128: type = assoc_entity_type %ImplicitAs.type.442 [concrete]
+// CHECK:STDOUT:   %assoc0.5ba: %ImplicitAs.assoc_type.128 = assoc_entity element0, imports.%Core.import_ref.207961.1 [concrete]
+// CHECK:STDOUT:   %assoc0.43db8b.2: %ImplicitAs.assoc_type.837 = assoc_entity element0, imports.%Core.import_ref.207961.2 [symbolic]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
+// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     import Core//default
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %Core.import_ref.5ab3ec.1: type = import_ref Core//default, loc4_22, loaded [symbolic = @ImplicitAs.%T (constants.%T.8b3)]
+// CHECK:STDOUT:   %Core.import_ref.ff5 = import_ref Core//default, inst24 [no loc], unloaded
+// CHECK:STDOUT:   %Core.import_ref.630: @ImplicitAs.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.837) = import_ref Core//default, loc5_32, loaded [symbolic = @ImplicitAs.%assoc0 (constants.%assoc0.43db8b.2)]
+// CHECK:STDOUT:   %Core.Convert = import_ref Core//default, Convert, unloaded
+// CHECK:STDOUT:   %Core.import_ref.5ab3ec.2: type = import_ref Core//default, loc4_22, loaded [symbolic = @ImplicitAs.%T (constants.%T.8b3)]
+// CHECK:STDOUT:   %Core.import_ref.ce1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.d62) = import_ref Core//default, inst24 [no loc], loaded [symbolic = @ImplicitAs.%Self (constants.%Self.519)]
+// CHECK:STDOUT:   %Core.import_ref.207961.1 = import_ref Core//default, loc5_32, unloaded
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .Core = imports.%Core
+// CHECK:STDOUT:     .I = %I.decl
+// CHECK:STDOUT:     .C = %C.decl
+// CHECK:STDOUT:     .A = %A.decl
+// CHECK:STDOUT:     .B = %B.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   %I.decl: %I.type.dac = interface_decl @I [concrete = constants.%I.generic] {
+// CHECK:STDOUT:     %V.patt.loc5_13.1: type = symbolic_binding_pattern V, 0 [symbolic = %V.patt.loc5_13.2 (constants.%V.patt)]
+// CHECK:STDOUT:     %W.patt.loc5_23.1: type = symbolic_binding_pattern W, 1 [symbolic = %W.patt.loc5_23.2 (constants.%W.patt)]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %V.loc5_13.1: type = bind_symbolic_name V, 0 [symbolic = %V.loc5_13.2 (constants.%V)]
+// CHECK:STDOUT:     %W.loc5_23.1: type = bind_symbolic_name W, 1 [symbolic = %W.loc5_23.2 (constants.%W)]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
+// CHECK:STDOUT:   impl_decl @impl [concrete] {
+// CHECK:STDOUT:     %T.patt.loc9_14.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc9_14.2 (constants.%T.patt.e01)]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %I.ref: %I.type.dac = name_ref I, file.%I.decl [concrete = constants.%I.generic]
+// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc9_14.1 [symbolic = %T.loc9_14.2 (constants.%T.8b3)]
+// CHECK:STDOUT:     %.loc9_35: %empty_tuple.type = tuple_literal ()
+// CHECK:STDOUT:     %.loc9_36: type = converted %.loc9_35, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
+// CHECK:STDOUT:     %I.type.loc9_36.1: type = facet_type <@I, @I(constants.%T.8b3, constants.%empty_tuple.type)> [symbolic = %I.type.loc9_36.2 (constants.%I.type.bea)]
+// CHECK:STDOUT:     %T.loc9_14.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc9_14.2 (constants.%T.8b3)]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %impl_witness: <witness> = impl_witness (), @impl(constants.%T.8b3) [symbolic = @impl.%impl_witness (constants.%impl_witness.298)]
+// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {
+// CHECK:STDOUT:     %T.patt.loc11_6.1: %I.type.906 = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc11_6.2 (constants.%T.patt.6fc)]
+// CHECK:STDOUT:     %t.patt: @A.%T.as_type.loc11_24.2 (%T.as_type) = binding_pattern t
+// CHECK:STDOUT:     %t.param_patt: @A.%T.as_type.loc11_24.2 (%T.as_type) = value_param_pattern %t.patt, call_param0
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %.loc11_18.1: type = splice_block %I.type [concrete = constants.%I.type.906] {
+// CHECK:STDOUT:       %I.ref: %I.type.dac = name_ref I, file.%I.decl [concrete = constants.%I.generic]
+// CHECK:STDOUT:       %.loc11_13: %empty_struct_type = struct_literal ()
+// CHECK:STDOUT:       %.loc11_17: %empty_struct_type = struct_literal ()
+// CHECK:STDOUT:       %.loc11_18.2: type = converted %.loc11_13, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
+// CHECK:STDOUT:       %.loc11_18.3: type = converted %.loc11_17, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
+// CHECK:STDOUT:       %I.type: type = facet_type <@I, @I(constants.%empty_struct_type, constants.%empty_struct_type)> [concrete = constants.%I.type.906]
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %T.loc11_6.1: %I.type.906 = bind_symbolic_name T, 0 [symbolic = %T.loc11_6.2 (constants.%T.4b2)]
+// CHECK:STDOUT:     %t.param: @A.%T.as_type.loc11_24.2 (%T.as_type) = value_param call_param0
+// CHECK:STDOUT:     %.loc11_24.1: type = splice_block %.loc11_24.2 [symbolic = %T.as_type.loc11_24.2 (constants.%T.as_type)] {
+// CHECK:STDOUT:       %T.ref: %I.type.906 = name_ref T, %T.loc11_6.1 [symbolic = %T.loc11_6.2 (constants.%T.4b2)]
+// CHECK:STDOUT:       %T.as_type.loc11_24.1: type = facet_access_type %T.ref [symbolic = %T.as_type.loc11_24.2 (constants.%T.as_type)]
+// CHECK:STDOUT:       %.loc11_24.2: type = converted %T.ref, %T.as_type.loc11_24.1 [symbolic = %T.as_type.loc11_24.2 (constants.%T.as_type)]
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %t: @A.%T.as_type.loc11_24.2 (%T.as_type) = bind_name t, %t.param
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {} {}
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic interface @I(%V.loc5_13.1: type, %W.loc5_23.1: type) {
+// CHECK:STDOUT:   %V.loc5_13.2: type = bind_symbolic_name V, 0 [symbolic = %V.loc5_13.2 (constants.%V)]
+// CHECK:STDOUT:   %V.patt.loc5_13.2: type = symbolic_binding_pattern V, 0 [symbolic = %V.patt.loc5_13.2 (constants.%V.patt)]
+// CHECK:STDOUT:   %W.loc5_23.2: type = bind_symbolic_name W, 1 [symbolic = %W.loc5_23.2 (constants.%W)]
+// CHECK:STDOUT:   %W.patt.loc5_23.2: type = symbolic_binding_pattern W, 1 [symbolic = %W.patt.loc5_23.2 (constants.%W.patt)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%V.loc5_13.2, %W.loc5_23.2)> [symbolic = %I.type (constants.%I.type.f76)]
+// CHECK:STDOUT:   %Self.2: %I.type.f76 = bind_symbolic_name Self, 2 [symbolic = %Self.2 (constants.%Self.770)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   interface {
+// CHECK:STDOUT:     %Self.1: @I.%I.type (%I.type.f76) = bind_symbolic_name Self, 2 [symbolic = %Self.2 (constants.%Self.770)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = %Self.1
+// CHECK:STDOUT:     witness = ()
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic interface @ImplicitAs(imports.%Core.import_ref.5ab3ec.1: type) [from "core.carbon"] {
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T.8b3)]
+// CHECK:STDOUT:   %T.patt: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt (constants.%T.patt.e01)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%T)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.d62)]
+// CHECK:STDOUT:   %Self: %ImplicitAs.type.d62 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.519)]
+// CHECK:STDOUT:   %Convert.type: type = fn_type @Convert, @ImplicitAs(%T) [symbolic = %Convert.type (constants.%Convert.type.275)]
+// CHECK:STDOUT:   %Convert: @ImplicitAs.%Convert.type (%Convert.type.275) = struct_value () [symbolic = %Convert (constants.%Convert.42e)]
+// CHECK:STDOUT:   %ImplicitAs.assoc_type: type = assoc_entity_type @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.d62) [symbolic = %ImplicitAs.assoc_type (constants.%ImplicitAs.assoc_type.837)]
+// CHECK:STDOUT:   %assoc0: @ImplicitAs.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.837) = assoc_entity element0, imports.%Core.import_ref.207961.1 [symbolic = %assoc0 (constants.%assoc0.43db8b.1)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   interface {
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = imports.%Core.import_ref.ff5
+// CHECK:STDOUT:     .Convert = imports.%Core.import_ref.630
+// CHECK:STDOUT:     witness = (imports.%Core.Convert)
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic impl @impl(%T.loc9_14.1: type) {
+// CHECK:STDOUT:   %T.loc9_14.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc9_14.2 (constants.%T.8b3)]
+// CHECK:STDOUT:   %T.patt.loc9_14.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc9_14.2 (constants.%T.patt.e01)]
+// CHECK:STDOUT:   %I.type.loc9_36.2: type = facet_type <@I, @I(%T.loc9_14.2, constants.%empty_tuple.type)> [symbolic = %I.type.loc9_36.2 (constants.%I.type.bea)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type @impl.%I.type.loc9_36.2 (%I.type.bea) [symbolic = %require_complete (constants.%require_complete.5ce)]
+// CHECK:STDOUT:   %impl_witness: <witness> = impl_witness (), @impl(%T.loc9_14.2) [symbolic = %impl_witness (constants.%impl_witness.298)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:
+// CHECK:STDOUT:   impl: %C.ref as %I.type.loc9_36.1 {
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     witness = file.%impl_witness
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357]
+// CHECK:STDOUT:   complete_type_witness = %complete_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = constants.%C
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @A(%T.loc11_6.1: %I.type.906) {
+// CHECK:STDOUT:   %T.loc11_6.2: %I.type.906 = bind_symbolic_name T, 0 [symbolic = %T.loc11_6.2 (constants.%T.4b2)]
+// CHECK:STDOUT:   %T.patt.loc11_6.2: %I.type.906 = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc11_6.2 (constants.%T.patt.6fc)]
+// CHECK:STDOUT:   %T.as_type.loc11_24.2: type = facet_access_type %T.loc11_6.2 [symbolic = %T.as_type.loc11_24.2 (constants.%T.as_type)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type @A.%T.as_type.loc11_24.2 (%T.as_type) [symbolic = %require_complete (constants.%require_complete.d5b)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn[%T.patt.loc11_6.1: %I.type.906](%t.param_patt: @A.%T.as_type.loc11_24.2 (%T.as_type)) {
+// CHECK:STDOUT:   !entry:
+// CHECK:STDOUT:     return
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @B() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A]
+// CHECK:STDOUT:   %.loc24_6.1: %empty_struct_type = struct_literal ()
+// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:   %.loc24_6.2: ref %C = temporary_storage
+// CHECK:STDOUT:   %.loc24_6.3: init %C = class_init (), %.loc24_6.2 [concrete = constants.%C.val]
+// CHECK:STDOUT:   %.loc24_6.4: ref %C = temporary %.loc24_6.2, %.loc24_6.3
+// CHECK:STDOUT:   %.loc24_8: ref %C = converted %.loc24_6.1, %.loc24_6.4
+// CHECK:STDOUT:   %.loc24_12: %I.type.906 = converted constants.%C, <error> [concrete = <error>]
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @Convert(imports.%Core.import_ref.5ab3ec.2: type, imports.%Core.import_ref.ce1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.d62)) [from "core.carbon"] {
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T.8b3)]
+// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%T)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.d62)]
+// CHECK:STDOUT:   %Self: %ImplicitAs.type.d62 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.519)]
+// CHECK:STDOUT:   %Self.as_type: type = facet_access_type %Self [symbolic = %Self.as_type (constants.%Self.as_type)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn[%self.param_patt: @Convert.%Self.as_type (%Self.as_type)]() -> @Convert.%T (%T.8b3);
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(constants.%V, constants.%W) {
+// CHECK:STDOUT:   %V.loc5_13.2 => constants.%V
+// CHECK:STDOUT:   %V.patt.loc5_13.2 => constants.%V
+// CHECK:STDOUT:   %W.loc5_23.2 => constants.%W
+// CHECK:STDOUT:   %W.patt.loc5_23.2 => constants.%W
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(%V.loc5_13.2, %W.loc5_23.2) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(constants.%T.8b3, constants.%empty_tuple.type) {
+// CHECK:STDOUT:   %V.loc5_13.2 => constants.%T.8b3
+// CHECK:STDOUT:   %V.patt.loc5_13.2 => constants.%T.8b3
+// CHECK:STDOUT:   %W.loc5_23.2 => constants.%empty_tuple.type
+// CHECK:STDOUT:   %W.patt.loc5_23.2 => constants.%empty_tuple.type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type => constants.%I.type.bea
+// CHECK:STDOUT:   %Self.2 => constants.%Self.770
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @impl(constants.%T.8b3) {
+// CHECK:STDOUT:   %T.loc9_14.2 => constants.%T.8b3
+// CHECK:STDOUT:   %T.patt.loc9_14.2 => constants.%T.8b3
+// CHECK:STDOUT:   %I.type.loc9_36.2 => constants.%I.type.bea
+// CHECK:STDOUT:   %require_complete => constants.%require_complete.5ce
+// CHECK:STDOUT:   %impl_witness => constants.%impl_witness.298
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(@impl.%T.loc9_14.2, constants.%empty_tuple.type) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @impl(%T.loc9_14.2) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(constants.%empty_struct_type, constants.%empty_struct_type) {
+// CHECK:STDOUT:   %V.loc5_13.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %V.patt.loc5_13.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %W.loc5_23.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %W.patt.loc5_23.2 => constants.%empty_struct_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type => constants.%I.type.906
+// CHECK:STDOUT:   %Self.2 => constants.%Self.770
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @A(constants.%T.4b2) {
+// CHECK:STDOUT:   %T.loc11_6.2 => constants.%T.4b2
+// CHECK:STDOUT:   %T.patt.loc11_6.2 => constants.%T.4b2
+// CHECK:STDOUT:   %T.as_type.loc11_24.2 => constants.%T.as_type
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @impl(constants.%empty_struct_type) {
+// CHECK:STDOUT:   %T.loc9_14.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %T.patt.loc9_14.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %I.type.loc9_36.2 => constants.%I.type.202
+// CHECK:STDOUT:   %require_complete => constants.%complete_type.3d9
+// CHECK:STDOUT:   %impl_witness => constants.%impl_witness.e3d
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(constants.%empty_struct_type, constants.%empty_tuple.type) {
+// CHECK:STDOUT:   %V.loc5_13.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %V.patt.loc5_13.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %W.loc5_23.2 => constants.%empty_tuple.type
+// CHECK:STDOUT:   %W.patt.loc5_23.2 => constants.%empty_tuple.type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type => constants.%I.type.202
+// CHECK:STDOUT:   %Self.2 => constants.%Self.770
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(constants.%T.8b3) {
+// CHECK:STDOUT:   %T => constants.%T.8b3
+// CHECK:STDOUT:   %T.patt => constants.%T.8b3
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(%T) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(@Convert.%T) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Convert(constants.%T.8b3, constants.%Self.519) {
+// CHECK:STDOUT:   %T => constants.%T.8b3
+// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.d62
+// CHECK:STDOUT:   %Self => constants.%Self.519
+// CHECK:STDOUT:   %Self.as_type => constants.%Self.as_type
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(constants.%I.type.906) {
+// CHECK:STDOUT:   %T => constants.%I.type.906
+// CHECK:STDOUT:   %T.patt => constants.%I.type.906
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.442
+// CHECK:STDOUT:   %Self => constants.%Self.519
+// CHECK:STDOUT:   %Convert.type => constants.%Convert.type.b43
+// CHECK:STDOUT:   %Convert => constants.%Convert.2fc
+// CHECK:STDOUT:   %ImplicitAs.assoc_type => constants.%ImplicitAs.assoc_type.128
+// CHECK:STDOUT:   %assoc0 => constants.%assoc0.5ba
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- fail_mismatch_impl_self_with_fixed_specific.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]
+// CHECK:STDOUT:   %Self.826: %I.type = bind_symbolic_name Self, 0 [symbolic]
+// CHECK:STDOUT:   %V: type = bind_symbolic_name V, 0 [symbolic]
+// CHECK:STDOUT:   %V.patt: type = symbolic_binding_pattern V, 0 [symbolic]
+// CHECK:STDOUT:   %W: type = bind_symbolic_name W, 1 [symbolic]
+// CHECK:STDOUT:   %W.patt: type = symbolic_binding_pattern W, 1 [symbolic]
+// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
+// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]
+// CHECK:STDOUT:   %C.c6b: type = class_type @C, @C(%V, %W) [symbolic]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %T.8b3: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %T.patt.e01: type = symbolic_binding_pattern T, 0 [symbolic]
+// CHECK:STDOUT:   %C.463: type = class_type @C, @C(%T.8b3, %empty_tuple.type) [symbolic]
+// CHECK:STDOUT:   %impl_witness.1a1: <witness> = impl_witness (), @impl(%T.8b3) [symbolic]
+// CHECK:STDOUT:   %T.826: %I.type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %T.patt.3ad: %I.type = symbolic_binding_pattern T, 0 [symbolic]
+// CHECK:STDOUT:   %T.as_type: type = facet_access_type %T.826 [symbolic]
+// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]
+// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.as_type [symbolic]
+// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]
+// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]
+// CHECK:STDOUT:   %C.c74: type = class_type @C, @C(%empty_struct_type, %empty_struct_type) [concrete]
+// CHECK:STDOUT:   %C.val: %C.c74 = struct_value () [concrete]
+// CHECK:STDOUT:   %C.83b: type = class_type @C, @C(%empty_struct_type, %empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %impl_witness.366: <witness> = impl_witness (), @impl(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.d62: type = facet_type <@ImplicitAs, @ImplicitAs(%T.8b3)> [symbolic]
+// CHECK:STDOUT:   %Self.519: %ImplicitAs.type.d62 = bind_symbolic_name Self, 1 [symbolic]
+// CHECK:STDOUT:   %Convert.type.275: type = fn_type @Convert, @ImplicitAs(%T.8b3) [symbolic]
+// CHECK:STDOUT:   %Convert.42e: %Convert.type.275 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Self.as_type: type = facet_access_type %Self.519 [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.assoc_type.837: type = assoc_entity_type %ImplicitAs.type.d62 [symbolic]
+// CHECK:STDOUT:   %assoc0.43db8b.1: %ImplicitAs.assoc_type.837 = assoc_entity element0, imports.%Core.import_ref.207961.1 [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.type.c42: type = facet_type <@ImplicitAs, @ImplicitAs(%I.type)> [concrete]
+// CHECK:STDOUT:   %Convert.type.7ef: type = fn_type @Convert, @ImplicitAs(%I.type) [concrete]
+// CHECK:STDOUT:   %Convert.c77: %Convert.type.7ef = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.assoc_type.167: type = assoc_entity_type %ImplicitAs.type.c42 [concrete]
+// CHECK:STDOUT:   %assoc0.ae9: %ImplicitAs.assoc_type.167 = assoc_entity element0, imports.%Core.import_ref.207961.1 [concrete]
+// CHECK:STDOUT:   %assoc0.43db8b.2: %ImplicitAs.assoc_type.837 = assoc_entity element0, imports.%Core.import_ref.207961.2 [symbolic]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
+// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     import Core//default
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %Core.import_ref.5ab3ec.1: type = import_ref Core//default, loc4_22, loaded [symbolic = @ImplicitAs.%T (constants.%T.8b3)]
+// CHECK:STDOUT:   %Core.import_ref.ff5 = import_ref Core//default, inst24 [no loc], unloaded
+// CHECK:STDOUT:   %Core.import_ref.630: @ImplicitAs.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.837) = import_ref Core//default, loc5_32, loaded [symbolic = @ImplicitAs.%assoc0 (constants.%assoc0.43db8b.2)]
+// CHECK:STDOUT:   %Core.Convert = import_ref Core//default, Convert, unloaded
+// CHECK:STDOUT:   %Core.import_ref.5ab3ec.2: type = import_ref Core//default, loc4_22, loaded [symbolic = @ImplicitAs.%T (constants.%T.8b3)]
+// CHECK:STDOUT:   %Core.import_ref.ce1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.d62) = import_ref Core//default, inst24 [no loc], loaded [symbolic = @ImplicitAs.%Self (constants.%Self.519)]
+// CHECK:STDOUT:   %Core.import_ref.207961.1 = import_ref Core//default, loc5_32, unloaded
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .Core = imports.%Core
+// CHECK:STDOUT:     .I = %I.decl
+// CHECK:STDOUT:     .C = %C.decl
+// CHECK:STDOUT:     .A = %A.decl
+// CHECK:STDOUT:     .B = %B.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}
+// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {
+// CHECK:STDOUT:     %V.patt.loc7_9.1: type = symbolic_binding_pattern V, 0 [symbolic = %V.patt.loc7_9.2 (constants.%V.patt)]
+// CHECK:STDOUT:     %W.patt.loc7_19.1: type = symbolic_binding_pattern W, 1 [symbolic = %W.patt.loc7_19.2 (constants.%W.patt)]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %V.loc7_9.1: type = bind_symbolic_name V, 0 [symbolic = %V.loc7_9.2 (constants.%V)]
+// CHECK:STDOUT:     %W.loc7_19.1: type = bind_symbolic_name W, 1 [symbolic = %W.loc7_19.2 (constants.%W)]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   impl_decl @impl [concrete] {
+// CHECK:STDOUT:     %T.patt.loc9_14.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc9_14.2 (constants.%T.patt.e01)]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]
+// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc9_14.1 [symbolic = %T.loc9_14.2 (constants.%T.8b3)]
+// CHECK:STDOUT:     %.loc9_30: %empty_tuple.type = tuple_literal ()
+// CHECK:STDOUT:     %.loc9_31: type = converted %.loc9_30, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
+// CHECK:STDOUT:     %C.loc9_31.1: type = class_type @C, @C(constants.%T.8b3, constants.%empty_tuple.type) [symbolic = %C.loc9_31.2 (constants.%C.463)]
+// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
+// CHECK:STDOUT:     %T.loc9_14.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc9_14.2 (constants.%T.8b3)]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %impl_witness: <witness> = impl_witness (), @impl(constants.%T.8b3) [symbolic = @impl.%impl_witness (constants.%impl_witness.1a1)]
+// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {
+// CHECK:STDOUT:     %T.patt.loc11_6.1: %I.type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc11_6.2 (constants.%T.patt.3ad)]
+// CHECK:STDOUT:     %t.patt: @A.%T.as_type.loc11_16.2 (%T.as_type) = binding_pattern t
+// CHECK:STDOUT:     %t.param_patt: @A.%T.as_type.loc11_16.2 (%T.as_type) = value_param_pattern %t.patt, call_param0
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
+// CHECK:STDOUT:     %T.loc11_6.1: %I.type = bind_symbolic_name T, 0 [symbolic = %T.loc11_6.2 (constants.%T.826)]
+// CHECK:STDOUT:     %t.param: @A.%T.as_type.loc11_16.2 (%T.as_type) = value_param call_param0
+// CHECK:STDOUT:     %.loc11_16.1: type = splice_block %.loc11_16.2 [symbolic = %T.as_type.loc11_16.2 (constants.%T.as_type)] {
+// CHECK:STDOUT:       %T.ref: %I.type = name_ref T, %T.loc11_6.1 [symbolic = %T.loc11_6.2 (constants.%T.826)]
+// CHECK:STDOUT:       %T.as_type.loc11_16.1: type = facet_access_type %T.ref [symbolic = %T.as_type.loc11_16.2 (constants.%T.as_type)]
+// CHECK:STDOUT:       %.loc11_16.2: type = converted %T.ref, %T.as_type.loc11_16.1 [symbolic = %T.as_type.loc11_16.2 (constants.%T.as_type)]
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %t: @A.%T.as_type.loc11_16.2 (%T.as_type) = bind_name t, %t.param
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {} {}
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @I {
+// CHECK:STDOUT:   %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.826]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = %Self
+// CHECK:STDOUT:   witness = ()
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic interface @ImplicitAs(imports.%Core.import_ref.5ab3ec.1: type) [from "core.carbon"] {
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T.8b3)]
+// CHECK:STDOUT:   %T.patt: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt (constants.%T.patt.e01)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%T)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.d62)]
+// CHECK:STDOUT:   %Self: %ImplicitAs.type.d62 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.519)]
+// CHECK:STDOUT:   %Convert.type: type = fn_type @Convert, @ImplicitAs(%T) [symbolic = %Convert.type (constants.%Convert.type.275)]
+// CHECK:STDOUT:   %Convert: @ImplicitAs.%Convert.type (%Convert.type.275) = struct_value () [symbolic = %Convert (constants.%Convert.42e)]
+// CHECK:STDOUT:   %ImplicitAs.assoc_type: type = assoc_entity_type @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.d62) [symbolic = %ImplicitAs.assoc_type (constants.%ImplicitAs.assoc_type.837)]
+// CHECK:STDOUT:   %assoc0: @ImplicitAs.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.837) = assoc_entity element0, imports.%Core.import_ref.207961.1 [symbolic = %assoc0 (constants.%assoc0.43db8b.1)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   interface {
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = imports.%Core.import_ref.ff5
+// CHECK:STDOUT:     .Convert = imports.%Core.import_ref.630
+// CHECK:STDOUT:     witness = (imports.%Core.Convert)
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic impl @impl(%T.loc9_14.1: type) {
+// CHECK:STDOUT:   %T.loc9_14.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc9_14.2 (constants.%T.8b3)]
+// CHECK:STDOUT:   %T.patt.loc9_14.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc9_14.2 (constants.%T.patt.e01)]
+// CHECK:STDOUT:   %C.loc9_31.2: type = class_type @C, @C(%T.loc9_14.2, constants.%empty_tuple.type) [symbolic = %C.loc9_31.2 (constants.%C.463)]
+// CHECK:STDOUT:   %impl_witness: <witness> = impl_witness (), @impl(%T.loc9_14.2) [symbolic = %impl_witness (constants.%impl_witness.1a1)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:
+// CHECK:STDOUT:   impl: %C.loc9_31.1 as %I.ref {
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     witness = file.%impl_witness
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic class @C(%V.loc7_9.1: type, %W.loc7_19.1: type) {
+// CHECK:STDOUT:   %V.loc7_9.2: type = bind_symbolic_name V, 0 [symbolic = %V.loc7_9.2 (constants.%V)]
+// CHECK:STDOUT:   %V.patt.loc7_9.2: type = symbolic_binding_pattern V, 0 [symbolic = %V.patt.loc7_9.2 (constants.%V.patt)]
+// CHECK:STDOUT:   %W.loc7_19.2: type = bind_symbolic_name W, 1 [symbolic = %W.loc7_19.2 (constants.%W)]
+// CHECK:STDOUT:   %W.patt.loc7_19.2: type = symbolic_binding_pattern W, 1 [symbolic = %W.patt.loc7_19.2 (constants.%W.patt)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:
+// CHECK:STDOUT:   class {
+// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:     complete_type_witness = %complete_type
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = constants.%C.c6b
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @A(%T.loc11_6.1: %I.type) {
+// CHECK:STDOUT:   %T.loc11_6.2: %I.type = bind_symbolic_name T, 0 [symbolic = %T.loc11_6.2 (constants.%T.826)]
+// CHECK:STDOUT:   %T.patt.loc11_6.2: %I.type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc11_6.2 (constants.%T.patt.3ad)]
+// CHECK:STDOUT:   %T.as_type.loc11_16.2: type = facet_access_type %T.loc11_6.2 [symbolic = %T.as_type.loc11_16.2 (constants.%T.as_type)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type @A.%T.as_type.loc11_16.2 (%T.as_type) [symbolic = %require_complete (constants.%require_complete)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn[%T.patt.loc11_6.1: %I.type](%t.param_patt: @A.%T.as_type.loc11_16.2 (%T.as_type)) {
+// CHECK:STDOUT:   !entry:
+// CHECK:STDOUT:     return
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @B() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A]
+// CHECK:STDOUT:   %.loc24_6.1: %empty_struct_type = struct_literal ()
+// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]
+// CHECK:STDOUT:   %.loc24_14: %empty_struct_type = struct_literal ()
+// CHECK:STDOUT:   %.loc24_18: %empty_struct_type = struct_literal ()
+// CHECK:STDOUT:   %.loc24_19.1: type = converted %.loc24_14, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
+// CHECK:STDOUT:   %.loc24_19.2: type = converted %.loc24_18, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
+// CHECK:STDOUT:   %C: type = class_type @C, @C(constants.%empty_struct_type, constants.%empty_struct_type) [concrete = constants.%C.c74]
+// CHECK:STDOUT:   %.loc24_6.2: ref %C.c74 = temporary_storage
+// CHECK:STDOUT:   %.loc24_6.3: init %C.c74 = class_init (), %.loc24_6.2 [concrete = constants.%C.val]
+// CHECK:STDOUT:   %.loc24_6.4: ref %C.c74 = temporary %.loc24_6.2, %.loc24_6.3
+// CHECK:STDOUT:   %.loc24_8: ref %C.c74 = converted %.loc24_6.1, %.loc24_6.4
+// CHECK:STDOUT:   %.loc24_20: %I.type = converted constants.%C.c74, <error> [concrete = <error>]
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @Convert(imports.%Core.import_ref.5ab3ec.2: type, imports.%Core.import_ref.ce1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.d62)) [from "core.carbon"] {
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T.8b3)]
+// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%T)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.d62)]
+// CHECK:STDOUT:   %Self: %ImplicitAs.type.d62 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.519)]
+// CHECK:STDOUT:   %Self.as_type: type = facet_access_type %Self [symbolic = %Self.as_type (constants.%Self.as_type)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn[%self.param_patt: @Convert.%Self.as_type (%Self.as_type)]() -> @Convert.%T (%T.8b3);
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @C(constants.%V, constants.%W) {
+// CHECK:STDOUT:   %V.loc7_9.2 => constants.%V
+// CHECK:STDOUT:   %V.patt.loc7_9.2 => constants.%V
+// CHECK:STDOUT:   %W.loc7_19.2 => constants.%W
+// CHECK:STDOUT:   %W.patt.loc7_19.2 => constants.%W
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @C(constants.%T.8b3, constants.%empty_tuple.type) {
+// CHECK:STDOUT:   %V.loc7_9.2 => constants.%T.8b3
+// CHECK:STDOUT:   %V.patt.loc7_9.2 => constants.%T.8b3
+// CHECK:STDOUT:   %W.loc7_19.2 => constants.%empty_tuple.type
+// CHECK:STDOUT:   %W.patt.loc7_19.2 => constants.%empty_tuple.type
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @impl(constants.%T.8b3) {
+// CHECK:STDOUT:   %T.loc9_14.2 => constants.%T.8b3
+// CHECK:STDOUT:   %T.patt.loc9_14.2 => constants.%T.8b3
+// CHECK:STDOUT:   %C.loc9_31.2 => constants.%C.463
+// CHECK:STDOUT:   %impl_witness => constants.%impl_witness.1a1
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @C(@impl.%T.loc9_14.2, constants.%empty_tuple.type) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @impl(%T.loc9_14.2) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @A(constants.%T.826) {
+// CHECK:STDOUT:   %T.loc11_6.2 => constants.%T.826
+// CHECK:STDOUT:   %T.patt.loc11_6.2 => constants.%T.826
+// CHECK:STDOUT:   %T.as_type.loc11_16.2 => constants.%T.as_type
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @C(constants.%empty_struct_type, constants.%empty_struct_type) {
+// CHECK:STDOUT:   %V.loc7_9.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %V.patt.loc7_9.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %W.loc7_19.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %W.patt.loc7_19.2 => constants.%empty_struct_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @impl(constants.%empty_struct_type) {
+// CHECK:STDOUT:   %T.loc9_14.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %T.patt.loc9_14.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %C.loc9_31.2 => constants.%C.83b
+// CHECK:STDOUT:   %impl_witness => constants.%impl_witness.366
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @C(constants.%empty_struct_type, constants.%empty_tuple.type) {
+// CHECK:STDOUT:   %V.loc7_9.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %V.patt.loc7_9.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %W.loc7_19.2 => constants.%empty_tuple.type
+// CHECK:STDOUT:   %W.patt.loc7_19.2 => constants.%empty_tuple.type
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(constants.%T.8b3) {
+// CHECK:STDOUT:   %T => constants.%T.8b3
+// CHECK:STDOUT:   %T.patt => constants.%T.8b3
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(%T) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(@Convert.%T) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Convert(constants.%T.8b3, constants.%Self.519) {
+// CHECK:STDOUT:   %T => constants.%T.8b3
+// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.d62
+// CHECK:STDOUT:   %Self => constants.%Self.519
+// CHECK:STDOUT:   %Self.as_type => constants.%Self.as_type
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(constants.%I.type) {
+// CHECK:STDOUT:   %T => constants.%I.type
+// CHECK:STDOUT:   %T.patt => constants.%I.type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.c42
+// CHECK:STDOUT:   %Self => constants.%Self.519
+// CHECK:STDOUT:   %Convert.type => constants.%Convert.type.7ef
+// CHECK:STDOUT:   %Convert => constants.%Convert.c77
+// CHECK:STDOUT:   %ImplicitAs.assoc_type => constants.%ImplicitAs.assoc_type.167
+// CHECK:STDOUT:   %assoc0 => constants.%assoc0.ae9
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 101 - 72
toolchain/check/testdata/facet/no_prelude/combine.carbon

@@ -37,6 +37,26 @@ import Core;
 interface A {}
 class C {}
 
+// CHECK:STDERR: fail_combine_with_non_facet_type.carbon:[[@LINE+4]]:11: error: non-facet type `C` combined with `&` operator [FacetTypeRequiredForTypeAndOperator]
+// CHECK:STDERR: fn AC[T:! A & C](t: T) {}
+// CHECK:STDERR:           ^~~~~
+// CHECK:STDERR:
+fn AC[T:! A & C](t: T) {}
+// CHECK:STDERR: fail_combine_with_non_facet_type.carbon:[[@LINE+4]]:11: error: non-facet type `C` combined with `&` operator [FacetTypeRequiredForTypeAndOperator]
+// CHECK:STDERR: fn CA[T:! C & A](t: T) {}
+// CHECK:STDERR:           ^~~~~
+// CHECK:STDERR:
+fn CA[T:! C & A](t: T) {}
+// CHECK:STDERR: fail_combine_with_non_facet_type.carbon:[[@LINE+8]]:11: error: non-facet type `C` combined with `&` operator [FacetTypeRequiredForTypeAndOperator]
+// CHECK:STDERR: fn CC[T:! C & C](t: T) {}
+// CHECK:STDERR:           ^~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_combine_with_non_facet_type.carbon:[[@LINE+4]]:11: error: non-facet type `C` combined with `&` operator [FacetTypeRequiredForTypeAndOperator]
+// CHECK:STDERR: fn CC[T:! C & C](t: T) {}
+// CHECK:STDERR:           ^~~~~
+// CHECK:STDERR:
+fn CC[T:! C & C](t: T) {}
+
 fn F() {
   // CHECK:STDERR: fail_combine_with_non_facet_type.carbon:[[@LINE+4]]:23: error: non-facet type `C` combined with `&` operator [FacetTypeRequiredForTypeAndOperator]
   // CHECK:STDERR:   ({} as C) as (C as (A & C));
@@ -57,6 +77,10 @@ fn F() {
   // CHECK:STDERR:                       ^~~~~
   // CHECK:STDERR:
   ({} as C) as (C as (C & C));
+
+  AC({} as C);
+  CA({} as C);
+  CC({} as C);
 }
 
 // --- same.carbon
@@ -64,22 +88,17 @@ library "[[@TEST_NAME]]";
 
 import Core;
 
-// Non-instance versions of these tests are in
-// .../interface/no_prelude/compound_member_access.carbon.
-
-interface A {
-  fn G[self: Self]();
-}
+interface A {}
 
 class C {}
-impl C as A {
-  fn G[self: Self]() {}
-}
+impl C as A {}
+
+fn AA[T:! A & A](t: T) {}
 
 fn F() {
-  ({} as C).((A & A).G)();
-  (({} as C) as (C as (A & A))).((A & A).G)();
-  (({} as C) as (C as (A & A))).(A.G)();
+  ({} as C) as (C as (A & A));
+
+  AA({} as C);
 }
 
 // --- fail_name_collision.carbon
@@ -112,95 +131,105 @@ fn F() {
   ({} as C).((A & B).G)();
 }
 
-// --- fail_todo_combine.carbon
+// --- combine.carbon
 library "[[@TEST_NAME]]";
 
 import Core;
 
 interface A {}
 interface B {
-  fn G[self: Self]();
+  fn BB[self: Self]();
 }
 
 class C {}
 impl C as A {}
 impl C as B {
-  fn G[self: Self]() {}
+  fn BB[self: Self]() {}
 }
 
+fn G[T:! A & B](t: T) {}
+
 fn F() {
-  ({} as C).((A & B).G)();
+  ({} as C).((A & B).BB)();
 
-  // CHECK:STDERR: fail_todo_combine.carbon:[[@LINE+11]]:18: error: semantics TODO: `impl lookup for a FacetType with more than one interface` [SemanticsTodo]
-  // CHECK:STDERR:   (({} as C) as (C as (A & B))).((A & B).G)();
-  // CHECK:STDERR:                  ^~~~~~~~~~~~
-  // CHECK:STDERR:
-  // CHECK:STDERR: fail_todo_combine.carbon:[[@LINE+7]]:18: error: cannot convert value of type `type` to `A & B` with `as` [ExplicitAsConversionFailure]
-  // CHECK:STDERR:   (({} as C) as (C as (A & B))).((A & B).G)();
-  // CHECK:STDERR:                  ^~~~~~~~~~~~
-  // CHECK:STDERR: fail_todo_combine.carbon:[[@LINE+4]]:18: note: type `type` does not implement interface `Core.As(A & B)` [MissingImplInMemberAccessNote]
-  // CHECK:STDERR:   (({} as C) as (C as (A & B))).((A & B).G)();
-  // CHECK:STDERR:                  ^~~~~~~~~~~~
-  // CHECK:STDERR:
-  (({} as C) as (C as (A & B))).((A & B).G)();
+  (({} as C) as (C as (A & B))).((A & B).BB)();
+  (({} as C) as (C as (A & B))).(B.BB)();
 
-  // CHECK:STDERR: fail_todo_combine.carbon:[[@LINE+11]]:18: error: semantics TODO: `impl lookup for a FacetType with more than one interface` [SemanticsTodo]
-  // CHECK:STDERR:   (({} as C) as (C as (A & B))).((B).G)();
-  // CHECK:STDERR:                  ^~~~~~~~~~~~
-  // CHECK:STDERR:
-  // CHECK:STDERR: fail_todo_combine.carbon:[[@LINE+7]]:18: error: cannot convert value of type `type` to `A & B` with `as` [ExplicitAsConversionFailure]
-  // CHECK:STDERR:   (({} as C) as (C as (A & B))).((B).G)();
-  // CHECK:STDERR:                  ^~~~~~~~~~~~
-  // CHECK:STDERR: fail_todo_combine.carbon:[[@LINE+4]]:18: note: type `type` does not implement interface `Core.As(A & B)` [MissingImplInMemberAccessNote]
-  // CHECK:STDERR:   (({} as C) as (C as (A & B))).((B).G)();
-  // CHECK:STDERR:                  ^~~~~~~~~~~~
-  // CHECK:STDERR:
-  (({} as C) as (C as (A & B))).((B).G)();
+  G({} as C);
 }
 
-// --- fail_todo_generic_combine.carbon
-
+// --- generic_interface.carbon
 library "[[@TEST_NAME]]";
 
 import Core;
 
-interface A {
-}
-interface B {
-  fn G[self: Self]();
-}
+interface A(T:! type) {}
+interface B {}
 
-fn H[T:! A & B](t: T) {
-  // CHECK:STDERR: fail_todo_generic_combine.carbon:[[@LINE+4]]:3: error: cannot access member of interface `B` in type `T` that does not implement that interface [MissingImplInMemberAccess]
-  // CHECK:STDERR:   t.(B.G)();
-  // CHECK:STDERR:   ^~~~~~~
-  // CHECK:STDERR:
-  t.(B.G)();
-}
+class P1 {}
+class P2 {}
 
 class C {}
-impl C as A {}
-impl C as B {
-  fn G[self: Self]() {}
+impl C as A(P1) {}
+impl C as B {}
+
+fn G[T:! A(P1) & B](t: T) {}
+
+fn F() {
+  G({} as C);
 }
 
+// --- fail_wrong_generic_interface.carbon
+library "[[@TEST_NAME]]";
+
+import Core;
+
+interface A(T:! type) {}
+interface B {}
+
+class P1 {}
+class P2 {}
+
+class C {}
+impl C as A(P1) {}
+impl C as B {}
+
+fn G[T:! A(P2) & B](t: T) {}
+
 fn F() {
-  // CHECK:STDERR: fail_todo_generic_combine.carbon:[[@LINE+17]]:3: error: semantics TODO: `impl lookup for a FacetType with more than one interface` [SemanticsTodo]
-  // CHECK:STDERR:   H({} as C);
+  // CHECK:STDERR: fail_wrong_generic_interface.carbon:[[@LINE+10]]:3: error: cannot implicitly convert value of type `type` to `A(P2) & B` [ImplicitAsConversionFailure]
+  // CHECK:STDERR:   G({} as C);
   // CHECK:STDERR:   ^~~~~~~~~~
-  // CHECK:STDERR: fail_todo_generic_combine.carbon:[[@LINE-18]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
-  // CHECK:STDERR: fn H[T:! A & B](t: T) {
-  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
-  // CHECK:STDERR: fail_todo_generic_combine.carbon:[[@LINE+10]]:3: error: cannot implicitly convert value of type `type` to `A & B` [ImplicitAsConversionFailure]
-  // CHECK:STDERR:   H({} as C);
-  // CHECK:STDERR:   ^~~~~~~~~~
-  // CHECK:STDERR: fail_todo_generic_combine.carbon:[[@LINE+7]]:3: note: type `type` does not implement interface `Core.ImplicitAs(A & B)` [MissingImplInMemberAccessNote]
-  // CHECK:STDERR:   H({} as C);
+  // CHECK:STDERR: fail_wrong_generic_interface.carbon:[[@LINE+7]]:3: note: type `type` does not implement interface `Core.ImplicitAs(A(P2) & B)` [MissingImplInMemberAccessNote]
+  // CHECK:STDERR:   G({} as C);
   // CHECK:STDERR:   ^~~~~~~~~~
-  // CHECK:STDERR: fail_todo_generic_combine.carbon:[[@LINE-28]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
-  // CHECK:STDERR: fn H[T:! A & B](t: T) {
-  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~
+  // CHECK:STDERR: fail_wrong_generic_interface.carbon:[[@LINE-9]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
+  // CHECK:STDERR: fn G[T:! A(P2) & B](t: T) {}
+  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~
   // CHECK:STDERR:
-  H({} as C);
+  G({} as C);
+}
+
+// --- generic_forall_impl.carbon
+library "[[@TEST_NAME]]";
+
+import Core;
+
+interface Iface {}
+interface GenericIface(T:! type) {}
+
+class GenericClass(T:! type) {}
+
+class ImplIface {}
+impl ImplIface as Iface {}
+
+class C {}
+impl C as Iface {}
+
+impl forall [IfaceType:! Iface] C as GenericIface(GenericClass(IfaceType)) {}
+
+fn G[T:! Iface & GenericIface(GenericClass(ImplIface))](t: T) {}
+
+fn F() {
+  G({} as C);
 }

+ 839 - 0
toolchain/check/testdata/facet/no_prelude/fail_todo_call_combined_impl_witness.carbon

@@ -0,0 +1,839 @@
+// 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
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/no_prelude/fail_todo_call_combined_impl_witness.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/no_prelude/fail_todo_call_combined_impl_witness.carbon
+
+// --- core.carbon
+package Core;
+
+interface As(Dest:! type) {
+  fn Convert[self: Self]() -> Dest;
+}
+
+interface ImplicitAs(Dest:! type) {
+  fn Convert[self: Self]() -> Dest;
+}
+
+interface BitAnd {
+  fn Op[self: Self](other: Self) -> Self;
+}
+
+impl forall [T:! type] T as BitAnd {
+  fn Op[self: Self](other: Self) -> Self = "type.and";
+}
+
+// --- fail_todo_call_combined_impl_witness.carbon
+
+library "[[@TEST_NAME]]";
+
+import Core;
+
+interface Empty {
+}
+interface A {
+  fn AA();
+}
+interface B {
+  fn BB();
+}
+
+class C {}
+impl C as Empty {}
+impl C as A {
+  fn AA() {}
+}
+impl C as B {
+  fn BB() {}
+}
+
+fn G[T:! A & Empty & B](t: T) {
+  t.AA();
+  t.BB();
+
+  T.AA();
+  T.BB();
+
+  // TODO: Qualified lookup of `AA` and `BB` should also be possible here, using
+  // the witnesses found in type deduction.
+
+  // CHECK:STDERR: fail_todo_call_combined_impl_witness.carbon:[[@LINE+4]]:3: error: cannot access member of interface `A` in type `Empty & A & B` that does not implement that interface [MissingImplInMemberAccess]
+  // CHECK:STDERR:   T.(A.AA)();
+  // CHECK:STDERR:   ^~~~~~~~
+  // CHECK:STDERR:
+  T.(A.AA)();
+  // CHECK:STDERR: fail_todo_call_combined_impl_witness.carbon:[[@LINE+7]]:3: error: cannot access member of interface `B` in type `Empty & A & B` that does not implement that interface [MissingImplInMemberAccess]
+  // CHECK:STDERR:   T.(B.BB)();
+  // CHECK:STDERR:   ^~~~~~~~
+  // CHECK:STDERR:
+  // CHECK:STDERR: fail_todo_call_combined_impl_witness.carbon:[[@LINE-18]]:3: error: semantics TODO: `incorrect witness for multiple interfaces in a facet type` [SemanticsTodo]
+  // CHECK:STDERR:   t.AA();
+  // CHECK:STDERR:   ^~~~
+  T.(B.BB)();
+}
+
+fn F() {
+  // CHECK:STDERR: fail_todo_call_combined_impl_witness.carbon:[[@LINE+11]]:3: note: in `G(C as Empty & A & B)` used here [ResolvingSpecificHere]
+  // CHECK:STDERR:   G({} as C);
+  // CHECK:STDERR:   ^
+  // CHECK:STDERR:
+  // CHECK:STDERR: fail_todo_call_combined_impl_witness.carbon:[[@LINE-28]]:3: error: semantics TODO: `incorrect witness for multiple interfaces in a facet type` [SemanticsTodo]
+  // CHECK:STDERR:   t.BB();
+  // CHECK:STDERR:   ^~~~
+  // CHECK:STDERR: fail_todo_call_combined_impl_witness.carbon:[[@LINE+4]]:3: note: in `G(C as Empty & A & B)` used here [ResolvingSpecificHere]
+  // CHECK:STDERR:   G({} as C);
+  // CHECK:STDERR:   ^
+  // CHECK:STDERR:
+  G({} as C);
+}
+
+// CHECK:STDOUT: --- core.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %Dest: type = bind_symbolic_name Dest, 0 [symbolic]
+// CHECK:STDOUT:   %Dest.patt: type = symbolic_binding_pattern Dest, 0 [symbolic]
+// CHECK:STDOUT:   %As.type.b51: type = generic_interface_type @As [concrete]
+// CHECK:STDOUT:   %As.generic: %As.type.b51 = struct_value () [concrete]
+// CHECK:STDOUT:   %As.type.8ba: type = facet_type <@As, @As(%Dest)> [symbolic]
+// CHECK:STDOUT:   %Self.b4e: %As.type.8ba = bind_symbolic_name Self, 1 [symbolic]
+// CHECK:STDOUT:   %Self.as_type.7f0: type = facet_access_type %Self.b4e [symbolic]
+// CHECK:STDOUT:   %Convert.type.ad1: type = fn_type @Convert.1, @As(%Dest) [symbolic]
+// CHECK:STDOUT:   %Convert.0ed: %Convert.type.ad1 = struct_value () [symbolic]
+// CHECK:STDOUT:   %As.assoc_type: type = assoc_entity_type %As.type.8ba [symbolic]
+// CHECK:STDOUT:   %assoc0.ac5: %As.assoc_type = assoc_entity element0, @As.%Convert.decl [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.type.96f: type = generic_interface_type @ImplicitAs [concrete]
+// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.96f = struct_value () [concrete]
+// CHECK:STDOUT:   %ImplicitAs.type.07f: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest)> [symbolic]
+// CHECK:STDOUT:   %Self.0f3: %ImplicitAs.type.07f = bind_symbolic_name Self, 1 [symbolic]
+// CHECK:STDOUT:   %Self.as_type.419: type = facet_access_type %Self.0f3 [symbolic]
+// CHECK:STDOUT:   %Convert.type.4cf: type = fn_type @Convert.2, @ImplicitAs(%Dest) [symbolic]
+// CHECK:STDOUT:   %Convert.147: %Convert.type.4cf = struct_value () [symbolic]
+// CHECK:STDOUT:   %ImplicitAs.assoc_type: type = assoc_entity_type %ImplicitAs.type.07f [symbolic]
+// CHECK:STDOUT:   %assoc0.a50: %ImplicitAs.assoc_type = assoc_entity element0, @ImplicitAs.%Convert.decl [symbolic]
+// CHECK:STDOUT:   %BitAnd.type: type = facet_type <@BitAnd> [concrete]
+// CHECK:STDOUT:   %Self.e44: %BitAnd.type = bind_symbolic_name Self, 0 [symbolic]
+// CHECK:STDOUT:   %Self.as_type.560: type = facet_access_type %Self.e44 [symbolic]
+// CHECK:STDOUT:   %Op.type.613: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.d98: %Op.type.613 = struct_value () [concrete]
+// CHECK:STDOUT:   %BitAnd.assoc_type: type = assoc_entity_type %BitAnd.type [concrete]
+// CHECK:STDOUT:   %assoc0.121: %BitAnd.assoc_type = assoc_entity element0, @BitAnd.%Op.decl [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %T.patt: type = symbolic_binding_pattern T, 0 [symbolic]
+// CHECK:STDOUT:   %impl_witness: <witness> = impl_witness (@impl.%Op.decl), @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.type.28d: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.902: %Op.type.28d = struct_value () [symbolic]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic]
+// CHECK:STDOUT:   %BitAnd.facet: %BitAnd.type = facet_value %T, %impl_witness [symbolic]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .As = %As.decl
+// CHECK:STDOUT:     .ImplicitAs = %ImplicitAs.decl
+// CHECK:STDOUT:     .BitAnd = %BitAnd.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %As.decl: %As.type.b51 = interface_decl @As [concrete = constants.%As.generic] {
+// CHECK:STDOUT:     %Dest.patt.loc3_14.1: type = symbolic_binding_pattern Dest, 0 [symbolic = %Dest.patt.loc3_14.2 (constants.%Dest.patt)]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %Dest.loc3_14.1: type = bind_symbolic_name Dest, 0 [symbolic = %Dest.loc3_14.2 (constants.%Dest)]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %ImplicitAs.decl: %ImplicitAs.type.96f = interface_decl @ImplicitAs [concrete = constants.%ImplicitAs.generic] {
+// CHECK:STDOUT:     %Dest.patt.loc7_22.1: type = symbolic_binding_pattern Dest, 0 [symbolic = %Dest.patt.loc7_22.2 (constants.%Dest.patt)]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %Dest.loc7_22.1: type = bind_symbolic_name Dest, 0 [symbolic = %Dest.loc7_22.2 (constants.%Dest)]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %BitAnd.decl: type = interface_decl @BitAnd [concrete = constants.%BitAnd.type] {} {}
+// CHECK:STDOUT:   impl_decl @impl [concrete] {
+// CHECK:STDOUT:     %T.patt.loc15_14.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc15_14.2 (constants.%T.patt)]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc15_14.1 [symbolic = %T.loc15_14.2 (constants.%T)]
+// CHECK:STDOUT:     %BitAnd.ref: type = name_ref BitAnd, file.%BitAnd.decl [concrete = constants.%BitAnd.type]
+// CHECK:STDOUT:     %T.loc15_14.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc15_14.2 (constants.%T)]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %impl_witness: <witness> = impl_witness (@impl.%Op.decl), @impl(constants.%T) [symbolic = @impl.%impl_witness (constants.%impl_witness)]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic interface @As(%Dest.loc3_14.1: type) {
+// CHECK:STDOUT:   %Dest.loc3_14.2: type = bind_symbolic_name Dest, 0 [symbolic = %Dest.loc3_14.2 (constants.%Dest)]
+// CHECK:STDOUT:   %Dest.patt.loc3_14.2: type = symbolic_binding_pattern Dest, 0 [symbolic = %Dest.patt.loc3_14.2 (constants.%Dest.patt)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %As.type: type = facet_type <@As, @As(%Dest.loc3_14.2)> [symbolic = %As.type (constants.%As.type.8ba)]
+// CHECK:STDOUT:   %Self.2: %As.type.8ba = bind_symbolic_name Self, 1 [symbolic = %Self.2 (constants.%Self.b4e)]
+// CHECK:STDOUT:   %Convert.type: type = fn_type @Convert.1, @As(%Dest.loc3_14.2) [symbolic = %Convert.type (constants.%Convert.type.ad1)]
+// CHECK:STDOUT:   %Convert: @As.%Convert.type (%Convert.type.ad1) = struct_value () [symbolic = %Convert (constants.%Convert.0ed)]
+// CHECK:STDOUT:   %As.assoc_type: type = assoc_entity_type @As.%As.type (%As.type.8ba) [symbolic = %As.assoc_type (constants.%As.assoc_type)]
+// CHECK:STDOUT:   %assoc0.loc4_35.2: @As.%As.assoc_type (%As.assoc_type) = assoc_entity element0, %Convert.decl [symbolic = %assoc0.loc4_35.2 (constants.%assoc0.ac5)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   interface {
+// CHECK:STDOUT:     %Self.1: @As.%As.type (%As.type.8ba) = bind_symbolic_name Self, 1 [symbolic = %Self.2 (constants.%Self.b4e)]
+// CHECK:STDOUT:     %Convert.decl: @As.%Convert.type (%Convert.type.ad1) = fn_decl @Convert.1 [symbolic = @As.%Convert (constants.%Convert.0ed)] {
+// CHECK:STDOUT:       %self.patt: @Convert.1.%Self.as_type.loc4_20.1 (%Self.as_type.7f0) = binding_pattern self
+// CHECK:STDOUT:       %self.param_patt: @Convert.1.%Self.as_type.loc4_20.1 (%Self.as_type.7f0) = value_param_pattern %self.patt, call_param0
+// CHECK:STDOUT:       %return.patt: @Convert.1.%Dest (%Dest) = return_slot_pattern
+// CHECK:STDOUT:       %return.param_patt: @Convert.1.%Dest (%Dest) = out_param_pattern %return.patt, call_param1
+// CHECK:STDOUT:     } {
+// CHECK:STDOUT:       %Dest.ref: type = name_ref Dest, @As.%Dest.loc3_14.1 [symbolic = %Dest (constants.%Dest)]
+// CHECK:STDOUT:       %self.param: @Convert.1.%Self.as_type.loc4_20.1 (%Self.as_type.7f0) = value_param call_param0
+// CHECK:STDOUT:       %.loc4_20.1: type = splice_block %.loc4_20.3 [symbolic = %Self.as_type.loc4_20.1 (constants.%Self.as_type.7f0)] {
+// CHECK:STDOUT:         %.loc4_20.2: @Convert.1.%As.type (%As.type.8ba) = specific_constant @As.%Self.1, @As(constants.%Dest) [symbolic = %Self (constants.%Self.b4e)]
+// CHECK:STDOUT:         %Self.ref: @Convert.1.%As.type (%As.type.8ba) = name_ref Self, %.loc4_20.2 [symbolic = %Self (constants.%Self.b4e)]
+// CHECK:STDOUT:         %Self.as_type.loc4_20.2: type = facet_access_type %Self.ref [symbolic = %Self.as_type.loc4_20.1 (constants.%Self.as_type.7f0)]
+// CHECK:STDOUT:         %.loc4_20.3: type = converted %Self.ref, %Self.as_type.loc4_20.2 [symbolic = %Self.as_type.loc4_20.1 (constants.%Self.as_type.7f0)]
+// CHECK:STDOUT:       }
+// CHECK:STDOUT:       %self: @Convert.1.%Self.as_type.loc4_20.1 (%Self.as_type.7f0) = bind_name self, %self.param
+// CHECK:STDOUT:       %return.param: ref @Convert.1.%Dest (%Dest) = out_param call_param1
+// CHECK:STDOUT:       %return: ref @Convert.1.%Dest (%Dest) = return_slot %return.param
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %assoc0.loc4_35.1: @As.%As.assoc_type (%As.assoc_type) = assoc_entity element0, %Convert.decl [symbolic = %assoc0.loc4_35.2 (constants.%assoc0.ac5)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = %Self.1
+// CHECK:STDOUT:     .Dest = <poisoned>
+// CHECK:STDOUT:     .Convert = %assoc0.loc4_35.1
+// CHECK:STDOUT:     witness = (%Convert.decl)
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic interface @ImplicitAs(%Dest.loc7_22.1: type) {
+// CHECK:STDOUT:   %Dest.loc7_22.2: type = bind_symbolic_name Dest, 0 [symbolic = %Dest.loc7_22.2 (constants.%Dest)]
+// CHECK:STDOUT:   %Dest.patt.loc7_22.2: type = symbolic_binding_pattern Dest, 0 [symbolic = %Dest.patt.loc7_22.2 (constants.%Dest.patt)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest.loc7_22.2)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.07f)]
+// CHECK:STDOUT:   %Self.2: %ImplicitAs.type.07f = bind_symbolic_name Self, 1 [symbolic = %Self.2 (constants.%Self.0f3)]
+// CHECK:STDOUT:   %Convert.type: type = fn_type @Convert.2, @ImplicitAs(%Dest.loc7_22.2) [symbolic = %Convert.type (constants.%Convert.type.4cf)]
+// CHECK:STDOUT:   %Convert: @ImplicitAs.%Convert.type (%Convert.type.4cf) = struct_value () [symbolic = %Convert (constants.%Convert.147)]
+// CHECK:STDOUT:   %ImplicitAs.assoc_type: type = assoc_entity_type @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.07f) [symbolic = %ImplicitAs.assoc_type (constants.%ImplicitAs.assoc_type)]
+// CHECK:STDOUT:   %assoc0.loc8_35.2: @ImplicitAs.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type) = assoc_entity element0, %Convert.decl [symbolic = %assoc0.loc8_35.2 (constants.%assoc0.a50)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   interface {
+// CHECK:STDOUT:     %Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.07f) = bind_symbolic_name Self, 1 [symbolic = %Self.2 (constants.%Self.0f3)]
+// CHECK:STDOUT:     %Convert.decl: @ImplicitAs.%Convert.type (%Convert.type.4cf) = fn_decl @Convert.2 [symbolic = @ImplicitAs.%Convert (constants.%Convert.147)] {
+// CHECK:STDOUT:       %self.patt: @Convert.2.%Self.as_type.loc8_20.1 (%Self.as_type.419) = binding_pattern self
+// CHECK:STDOUT:       %self.param_patt: @Convert.2.%Self.as_type.loc8_20.1 (%Self.as_type.419) = value_param_pattern %self.patt, call_param0
+// CHECK:STDOUT:       %return.patt: @Convert.2.%Dest (%Dest) = return_slot_pattern
+// CHECK:STDOUT:       %return.param_patt: @Convert.2.%Dest (%Dest) = out_param_pattern %return.patt, call_param1
+// CHECK:STDOUT:     } {
+// CHECK:STDOUT:       %Dest.ref: type = name_ref Dest, @ImplicitAs.%Dest.loc7_22.1 [symbolic = %Dest (constants.%Dest)]
+// CHECK:STDOUT:       %self.param: @Convert.2.%Self.as_type.loc8_20.1 (%Self.as_type.419) = value_param call_param0
+// CHECK:STDOUT:       %.loc8_20.1: type = splice_block %.loc8_20.3 [symbolic = %Self.as_type.loc8_20.1 (constants.%Self.as_type.419)] {
+// CHECK:STDOUT:         %.loc8_20.2: @Convert.2.%ImplicitAs.type (%ImplicitAs.type.07f) = specific_constant @ImplicitAs.%Self.1, @ImplicitAs(constants.%Dest) [symbolic = %Self (constants.%Self.0f3)]
+// CHECK:STDOUT:         %Self.ref: @Convert.2.%ImplicitAs.type (%ImplicitAs.type.07f) = name_ref Self, %.loc8_20.2 [symbolic = %Self (constants.%Self.0f3)]
+// CHECK:STDOUT:         %Self.as_type.loc8_20.2: type = facet_access_type %Self.ref [symbolic = %Self.as_type.loc8_20.1 (constants.%Self.as_type.419)]
+// CHECK:STDOUT:         %.loc8_20.3: type = converted %Self.ref, %Self.as_type.loc8_20.2 [symbolic = %Self.as_type.loc8_20.1 (constants.%Self.as_type.419)]
+// CHECK:STDOUT:       }
+// CHECK:STDOUT:       %self: @Convert.2.%Self.as_type.loc8_20.1 (%Self.as_type.419) = bind_name self, %self.param
+// CHECK:STDOUT:       %return.param: ref @Convert.2.%Dest (%Dest) = out_param call_param1
+// CHECK:STDOUT:       %return: ref @Convert.2.%Dest (%Dest) = return_slot %return.param
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %assoc0.loc8_35.1: @ImplicitAs.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type) = assoc_entity element0, %Convert.decl [symbolic = %assoc0.loc8_35.2 (constants.%assoc0.a50)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = %Self.1
+// CHECK:STDOUT:     .Dest = <poisoned>
+// CHECK:STDOUT:     .Convert = %assoc0.loc8_35.1
+// CHECK:STDOUT:     witness = (%Convert.decl)
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @BitAnd {
+// CHECK:STDOUT:   %Self: %BitAnd.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.e44]
+// CHECK:STDOUT:   %Op.decl: %Op.type.613 = fn_decl @Op.1 [concrete = constants.%Op.d98] {
+// CHECK:STDOUT:     %self.patt: @Op.1.%Self.as_type.loc12_15.1 (%Self.as_type.560) = binding_pattern self
+// CHECK:STDOUT:     %self.param_patt: @Op.1.%Self.as_type.loc12_15.1 (%Self.as_type.560) = value_param_pattern %self.patt, call_param0
+// CHECK:STDOUT:     %other.patt: @Op.1.%Self.as_type.loc12_15.1 (%Self.as_type.560) = binding_pattern other
+// CHECK:STDOUT:     %other.param_patt: @Op.1.%Self.as_type.loc12_15.1 (%Self.as_type.560) = value_param_pattern %other.patt, call_param1
+// CHECK:STDOUT:     %return.patt: @Op.1.%Self.as_type.loc12_15.1 (%Self.as_type.560) = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: @Op.1.%Self.as_type.loc12_15.1 (%Self.as_type.560) = out_param_pattern %return.patt, call_param2
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %Self.ref.loc12_37: %BitAnd.type = name_ref Self, @BitAnd.%Self [symbolic = %Self (constants.%Self.e44)]
+// CHECK:STDOUT:     %Self.as_type.loc12_37: type = facet_access_type %Self.ref.loc12_37 [symbolic = %Self.as_type.loc12_15.1 (constants.%Self.as_type.560)]
+// CHECK:STDOUT:     %.loc12_37: type = converted %Self.ref.loc12_37, %Self.as_type.loc12_37 [symbolic = %Self.as_type.loc12_15.1 (constants.%Self.as_type.560)]
+// CHECK:STDOUT:     %self.param: @Op.1.%Self.as_type.loc12_15.1 (%Self.as_type.560) = value_param call_param0
+// CHECK:STDOUT:     %.loc12_15.1: type = splice_block %.loc12_15.2 [symbolic = %Self.as_type.loc12_15.1 (constants.%Self.as_type.560)] {
+// CHECK:STDOUT:       %Self.ref.loc12_15: %BitAnd.type = name_ref Self, @BitAnd.%Self [symbolic = %Self (constants.%Self.e44)]
+// CHECK:STDOUT:       %Self.as_type.loc12_15.2: type = facet_access_type %Self.ref.loc12_15 [symbolic = %Self.as_type.loc12_15.1 (constants.%Self.as_type.560)]
+// CHECK:STDOUT:       %.loc12_15.2: type = converted %Self.ref.loc12_15, %Self.as_type.loc12_15.2 [symbolic = %Self.as_type.loc12_15.1 (constants.%Self.as_type.560)]
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %self: @Op.1.%Self.as_type.loc12_15.1 (%Self.as_type.560) = bind_name self, %self.param
+// CHECK:STDOUT:     %other.param: @Op.1.%Self.as_type.loc12_15.1 (%Self.as_type.560) = value_param call_param1
+// CHECK:STDOUT:     %.loc12_28.1: type = splice_block %.loc12_28.2 [symbolic = %Self.as_type.loc12_15.1 (constants.%Self.as_type.560)] {
+// CHECK:STDOUT:       %Self.ref.loc12_28: %BitAnd.type = name_ref Self, @BitAnd.%Self [symbolic = %Self (constants.%Self.e44)]
+// CHECK:STDOUT:       %Self.as_type.loc12_28: type = facet_access_type %Self.ref.loc12_28 [symbolic = %Self.as_type.loc12_15.1 (constants.%Self.as_type.560)]
+// CHECK:STDOUT:       %.loc12_28.2: type = converted %Self.ref.loc12_28, %Self.as_type.loc12_28 [symbolic = %Self.as_type.loc12_15.1 (constants.%Self.as_type.560)]
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %other: @Op.1.%Self.as_type.loc12_15.1 (%Self.as_type.560) = bind_name other, %other.param
+// CHECK:STDOUT:     %return.param: ref @Op.1.%Self.as_type.loc12_15.1 (%Self.as_type.560) = out_param call_param2
+// CHECK:STDOUT:     %return: ref @Op.1.%Self.as_type.loc12_15.1 (%Self.as_type.560) = return_slot %return.param
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %assoc0: %BitAnd.assoc_type = assoc_entity element0, %Op.decl [concrete = constants.%assoc0.121]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = %Self
+// CHECK:STDOUT:   .Op = %assoc0
+// CHECK:STDOUT:   witness = (%Op.decl)
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic impl @impl(%T.loc15_14.1: type) {
+// CHECK:STDOUT:   %T.loc15_14.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc15_14.2 (constants.%T)]
+// CHECK:STDOUT:   %T.patt.loc15_14.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc15_14.2 (constants.%T.patt)]
+// CHECK:STDOUT:   %impl_witness: <witness> = impl_witness (%Op.decl), @impl(%T.loc15_14.2) [symbolic = %impl_witness (constants.%impl_witness)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %Op.type: type = fn_type @Op.2, @impl(%T.loc15_14.2) [symbolic = %Op.type (constants.%Op.type.28d)]
+// CHECK:STDOUT:   %Op: @impl.%Op.type (%Op.type.28d) = struct_value () [symbolic = %Op (constants.%Op.902)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type @impl.%T.loc15_14.2 (%T) [symbolic = %require_complete (constants.%require_complete)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   impl: %T.ref as %BitAnd.ref {
+// CHECK:STDOUT:     %Op.decl: @impl.%Op.type (%Op.type.28d) = fn_decl @Op.2 [symbolic = @impl.%Op (constants.%Op.902)] {
+// CHECK:STDOUT:       %self.patt: @Op.2.%T (%T) = binding_pattern self
+// CHECK:STDOUT:       %self.param_patt: @Op.2.%T (%T) = value_param_pattern %self.patt, call_param0
+// CHECK:STDOUT:       %other.patt: @Op.2.%T (%T) = binding_pattern other
+// CHECK:STDOUT:       %other.param_patt: @Op.2.%T (%T) = value_param_pattern %other.patt, call_param1
+// CHECK:STDOUT:       %return.patt: @Op.2.%T (%T) = return_slot_pattern
+// CHECK:STDOUT:       %return.param_patt: @Op.2.%T (%T) = out_param_pattern %return.patt, call_param2
+// CHECK:STDOUT:     } {
+// CHECK:STDOUT:       %Self.ref.loc16_37: type = name_ref Self, @impl.%T.ref [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:       %self.param: @Op.2.%T (%T) = value_param call_param0
+// CHECK:STDOUT:       %Self.ref.loc16_15: type = name_ref Self, @impl.%T.ref [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:       %self: @Op.2.%T (%T) = bind_name self, %self.param
+// CHECK:STDOUT:       %other.param: @Op.2.%T (%T) = value_param call_param1
+// CHECK:STDOUT:       %Self.ref.loc16_28: type = name_ref Self, @impl.%T.ref [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:       %other: @Op.2.%T (%T) = bind_name other, %other.param
+// CHECK:STDOUT:       %return.param: ref @Op.2.%T (%T) = out_param call_param2
+// CHECK:STDOUT:       %return: ref @Op.2.%T (%T) = return_slot %return.param
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Op = %Op.decl
+// CHECK:STDOUT:     witness = file.%impl_witness
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @Convert.1(@As.%Dest.loc3_14.1: type, @As.%Self.1: @As.%As.type (%As.type.8ba)) {
+// CHECK:STDOUT:   %Dest: type = bind_symbolic_name Dest, 0 [symbolic = %Dest (constants.%Dest)]
+// CHECK:STDOUT:   %As.type: type = facet_type <@As, @As(%Dest)> [symbolic = %As.type (constants.%As.type.8ba)]
+// CHECK:STDOUT:   %Self: %As.type.8ba = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.b4e)]
+// CHECK:STDOUT:   %Self.as_type.loc4_20.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc4_20.1 (constants.%Self.as_type.7f0)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn[%self.param_patt: @Convert.1.%Self.as_type.loc4_20.1 (%Self.as_type.7f0)]() -> @Convert.1.%Dest (%Dest);
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @Convert.2(@ImplicitAs.%Dest.loc7_22.1: type, @ImplicitAs.%Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.07f)) {
+// CHECK:STDOUT:   %Dest: type = bind_symbolic_name Dest, 0 [symbolic = %Dest (constants.%Dest)]
+// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.07f)]
+// CHECK:STDOUT:   %Self: %ImplicitAs.type.07f = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.0f3)]
+// CHECK:STDOUT:   %Self.as_type.loc8_20.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc8_20.1 (constants.%Self.as_type.419)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn[%self.param_patt: @Convert.2.%Self.as_type.loc8_20.1 (%Self.as_type.419)]() -> @Convert.2.%Dest (%Dest);
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @Op.1(@BitAnd.%Self: %BitAnd.type) {
+// CHECK:STDOUT:   %Self: %BitAnd.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self.e44)]
+// CHECK:STDOUT:   %Self.as_type.loc12_15.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc12_15.1 (constants.%Self.as_type.560)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn[%self.param_patt: @Op.1.%Self.as_type.loc12_15.1 (%Self.as_type.560)](%other.param_patt: @Op.1.%Self.as_type.loc12_15.1 (%Self.as_type.560)) -> @Op.1.%Self.as_type.loc12_15.1 (%Self.as_type.560);
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @Op.2(@impl.%T.loc15_14.1: type) {
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn[%self.param_patt: @Op.2.%T (%T)](%other.param_patt: @Op.2.%T (%T)) -> @Op.2.%T (%T) = "type.and";
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @As(constants.%Dest) {
+// CHECK:STDOUT:   %Dest.loc3_14.2 => constants.%Dest
+// CHECK:STDOUT:   %Dest.patt.loc3_14.2 => constants.%Dest
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Convert.1(constants.%Dest, constants.%Self.b4e) {
+// CHECK:STDOUT:   %Dest => constants.%Dest
+// CHECK:STDOUT:   %As.type => constants.%As.type.8ba
+// CHECK:STDOUT:   %Self => constants.%Self.b4e
+// CHECK:STDOUT:   %Self.as_type.loc4_20.1 => constants.%Self.as_type.7f0
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @As(@Convert.1.%Dest) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @As(%Dest.loc3_14.2) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(constants.%Dest) {
+// CHECK:STDOUT:   %Dest.loc7_22.2 => constants.%Dest
+// CHECK:STDOUT:   %Dest.patt.loc7_22.2 => constants.%Dest
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Convert.2(constants.%Dest, constants.%Self.0f3) {
+// CHECK:STDOUT:   %Dest => constants.%Dest
+// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.07f
+// CHECK:STDOUT:   %Self => constants.%Self.0f3
+// CHECK:STDOUT:   %Self.as_type.loc8_20.1 => constants.%Self.as_type.419
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(@Convert.2.%Dest) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @ImplicitAs(%Dest.loc7_22.2) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Op.1(constants.%Self.e44) {
+// CHECK:STDOUT:   %Self => constants.%Self.e44
+// CHECK:STDOUT:   %Self.as_type.loc12_15.1 => constants.%Self.as_type.560
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @impl(constants.%T) {
+// CHECK:STDOUT:   %T.loc15_14.2 => constants.%T
+// CHECK:STDOUT:   %T.patt.loc15_14.2 => constants.%T
+// CHECK:STDOUT:   %impl_witness => constants.%impl_witness
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @impl(%T.loc15_14.2) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Op.2(constants.%T) {
+// CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Op.1(constants.%BitAnd.facet) {
+// CHECK:STDOUT:   %Self => constants.%BitAnd.facet
+// CHECK:STDOUT:   %Self.as_type.loc12_15.1 => constants.%T
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- fail_todo_call_combined_impl_witness.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %Empty.type: type = facet_type <@Empty> [concrete]
+// CHECK:STDOUT:   %Self.193: %Empty.type = bind_symbolic_name Self, 0 [symbolic]
+// CHECK:STDOUT:   %A.type: type = facet_type <@A> [concrete]
+// CHECK:STDOUT:   %Self.31d: %A.type = bind_symbolic_name Self, 0 [symbolic]
+// CHECK:STDOUT:   %AA.type.b97: type = fn_type @AA.1 [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
+// CHECK:STDOUT:   %AA.c3a: %AA.type.b97 = struct_value () [concrete]
+// CHECK:STDOUT:   %A.assoc_type: type = assoc_entity_type %A.type [concrete]
+// CHECK:STDOUT:   %assoc0.f33: %A.assoc_type = assoc_entity element0, @A.%AA.decl [concrete]
+// CHECK:STDOUT:   %B.type: type = facet_type <@B> [concrete]
+// CHECK:STDOUT:   %Self.783: %B.type = bind_symbolic_name Self, 0 [symbolic]
+// CHECK:STDOUT:   %BB.type.64d: type = fn_type @BB.1 [concrete]
+// CHECK:STDOUT:   %BB.11b: %BB.type.64d = struct_value () [concrete]
+// CHECK:STDOUT:   %B.assoc_type: type = assoc_entity_type %B.type [concrete]
+// CHECK:STDOUT:   %assoc0.019: %B.assoc_type = assoc_entity element0, @B.%BB.decl [concrete]
+// CHECK:STDOUT:   %C: type = class_type @C [concrete]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %impl_witness.1bc: <witness> = impl_witness () [concrete]
+// CHECK:STDOUT:   %impl_witness.97a: <witness> = impl_witness (@impl.77d.%AA.decl) [concrete]
+// CHECK:STDOUT:   %AA.type.c29: type = fn_type @AA.2 [concrete]
+// CHECK:STDOUT:   %AA.95d: %AA.type.c29 = struct_value () [concrete]
+// CHECK:STDOUT:   %A.facet.afe: %A.type = facet_value %C, %impl_witness.97a [concrete]
+// CHECK:STDOUT:   %impl_witness.fe4: <witness> = impl_witness (@impl.c94.%BB.decl) [concrete]
+// CHECK:STDOUT:   %BB.type.24d: type = fn_type @BB.2 [concrete]
+// CHECK:STDOUT:   %BB.fe8: %BB.type.24d = struct_value () [concrete]
+// CHECK:STDOUT:   %B.facet.3a2: %B.type = facet_value %C, %impl_witness.fe4 [concrete]
+// CHECK:STDOUT:   %BitAnd.type: type = facet_type <@BitAnd> [concrete]
+// CHECK:STDOUT:   %Self.25f: %BitAnd.type = bind_symbolic_name Self, 0 [symbolic]
+// CHECK:STDOUT:   %BitAnd.assoc_type: type = assoc_entity_type %BitAnd.type [concrete]
+// CHECK:STDOUT:   %assoc0.a63: %BitAnd.assoc_type = assoc_entity element0, imports.%Core.import_ref.a93 [concrete]
+// CHECK:STDOUT:   %T.8b3: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %T.patt.e01: type = symbolic_binding_pattern T, 0 [symbolic]
+// CHECK:STDOUT:   %impl_witness.db8: <witness> = impl_witness (imports.%Core.import_ref.1e6), @impl.f92(%T.8b3) [symbolic]
+// CHECK:STDOUT:   %Op.type.f99: type = fn_type @Op.1, @impl.f92(%T.8b3) [symbolic]
+// CHECK:STDOUT:   %Op.05a: %Op.type.f99 = struct_value () [symbolic]
+// CHECK:STDOUT:   %require_complete.4ae: <witness> = require_complete_type %T.8b3 [symbolic]
+// CHECK:STDOUT:   %impl_witness.3ea: <witness> = impl_witness (imports.%Core.import_ref.1e6), @impl.f92(type) [concrete]
+// CHECK:STDOUT:   %impl_witness.b81: <witness> = impl_witness (imports.%Core.import_ref.bd4), @impl.f92(%T.8b3) [symbolic]
+// CHECK:STDOUT:   %Op.type.eb8: type = fn_type @Op.1, @impl.f92(type) [concrete]
+// CHECK:STDOUT:   %Op.444: %Op.type.eb8 = struct_value () [concrete]
+// CHECK:STDOUT:   %complete_type.473: <witness> = complete_type_witness type [concrete]
+// CHECK:STDOUT:   %Op.type.27a: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %Self.as_type: type = facet_access_type %Self.25f [symbolic]
+// CHECK:STDOUT:   %BitAnd.facet: %BitAnd.type = facet_value type, %impl_witness.3ea [concrete]
+// CHECK:STDOUT:   %.d4d: type = fn_type_with_self_type %Op.type.27a, %BitAnd.facet [concrete]
+// CHECK:STDOUT:   %Op.bound.6b1: <bound method> = bound_method %A.type, %Op.444 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.b4b: <specific function> = specific_function %Op.bound.6b1, @Op.1(type) [concrete]
+// CHECK:STDOUT:   %facet_type.d5f: type = facet_type <@Empty & @A> [concrete]
+// CHECK:STDOUT:   %Op.bound.b5b: <bound method> = bound_method %facet_type.d5f, %Op.444 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.165: <specific function> = specific_function %Op.bound.b5b, @Op.1(type) [concrete]
+// CHECK:STDOUT:   %facet_type.242: type = facet_type <@Empty & @A & @B> [concrete]
+// CHECK:STDOUT:   %T.2df: %facet_type.242 = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %T.patt.fd9: %facet_type.242 = symbolic_binding_pattern T, 0 [symbolic]
+// CHECK:STDOUT:   %T.as_type: type = facet_access_type %T.2df [symbolic]
+// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]
+// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
+// CHECK:STDOUT:   %require_complete.383: <witness> = require_complete_type %T.as_type [symbolic]
+// CHECK:STDOUT:   %T.as_wit: <witness> = facet_access_witness %T.2df [symbolic]
+// CHECK:STDOUT:   %A.facet.d6d: %A.type = facet_value %T.as_type, %T.as_wit [symbolic]
+// CHECK:STDOUT:   %.124: type = fn_type_with_self_type %AA.type.b97, %A.facet.d6d [symbolic]
+// CHECK:STDOUT:   %impl.elem0.2b1: %.124 = impl_witness_access %T.as_wit, element0 [symbolic]
+// CHECK:STDOUT:   %specific_fn.80f: <specific function> = specific_function %impl.elem0.2b1, @AA.1(%A.facet.d6d) [symbolic]
+// CHECK:STDOUT:   %B.facet.1c2: %B.type = facet_value %T.as_type, %T.as_wit [symbolic]
+// CHECK:STDOUT:   %.e3a: type = fn_type_with_self_type %BB.type.64d, %B.facet.1c2 [symbolic]
+// CHECK:STDOUT:   %impl.elem0.f5b: %.e3a = impl_witness_access %T.as_wit, element0 [symbolic]
+// CHECK:STDOUT:   %specific_fn.62f: <specific function> = specific_function %impl.elem0.f5b, @BB.1(%B.facet.1c2) [symbolic]
+// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
+// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
+// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]
+// CHECK:STDOUT:   %facet_value: %facet_type.242 = facet_value %C, %impl_witness.1bc [concrete]
+// CHECK:STDOUT:   %G.specific_fn: <specific function> = specific_function %G, @G(%facet_value) [concrete]
+// CHECK:STDOUT:   %A.facet.beb: %A.type = facet_value %C, %impl_witness.1bc [concrete]
+// CHECK:STDOUT:   %.778: type = fn_type_with_self_type %AA.type.b97, %A.facet.beb [concrete]
+// CHECK:STDOUT:   %B.facet.5e0: %B.type = facet_value %C, %impl_witness.1bc [concrete]
+// CHECK:STDOUT:   %.555: type = fn_type_with_self_type %BB.type.64d, %B.facet.5e0 [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
+// CHECK:STDOUT:     .BitAnd = %Core.BitAnd
+// CHECK:STDOUT:     import Core//default
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %Core.import_ref.ad0 = import_ref Core//default, inst100 [no loc], unloaded
+// CHECK:STDOUT:   %Core.import_ref.08d: %BitAnd.assoc_type = import_ref Core//default, loc12_41, loaded [concrete = constants.%assoc0.a63]
+// CHECK:STDOUT:   %Core.Op = import_ref Core//default, Op, unloaded
+// CHECK:STDOUT:   %Core.import_ref.51c: <witness> = import_ref Core//default, loc15_36, loaded [symbolic = @impl.f92.%impl_witness (constants.%impl_witness.b81)]
+// CHECK:STDOUT:   %Core.import_ref.5ab3ec.1: type = import_ref Core//default, loc15_14, loaded [symbolic = @impl.f92.%T (constants.%T.8b3)]
+// CHECK:STDOUT:   %Core.import_ref.583: type = import_ref Core//default, loc15_24, loaded [symbolic = @impl.f92.%T (constants.%T.8b3)]
+// CHECK:STDOUT:   %Core.import_ref.9c1: type = import_ref Core//default, loc15_29, loaded [concrete = constants.%BitAnd.type]
+// CHECK:STDOUT:   %Core.import_ref.1e6: @impl.f92.%Op.type (%Op.type.f99) = import_ref Core//default, loc16_42, loaded [symbolic = @impl.f92.%Op (constants.%Op.05a)]
+// CHECK:STDOUT:   %Core.import_ref.5ab3ec.2: type = import_ref Core//default, loc15_14, loaded [symbolic = @impl.f92.%T (constants.%T.8b3)]
+// CHECK:STDOUT:   %Core.import_ref.040: %BitAnd.type = import_ref Core//default, inst100 [no loc], loaded [symbolic = constants.%Self.25f]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .Core = imports.%Core
+// CHECK:STDOUT:     .Empty = %Empty.decl
+// CHECK:STDOUT:     .A = %A.decl
+// CHECK:STDOUT:     .B = %B.decl
+// CHECK:STDOUT:     .C = %C.decl
+// CHECK:STDOUT:     .G = %G.decl
+// CHECK:STDOUT:     .F = %F.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   %Empty.decl: type = interface_decl @Empty [concrete = constants.%Empty.type] {} {}
+// CHECK:STDOUT:   %A.decl: type = interface_decl @A [concrete = constants.%A.type] {} {}
+// CHECK:STDOUT:   %B.decl: type = interface_decl @B [concrete = constants.%B.type] {} {}
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
+// CHECK:STDOUT:   impl_decl @impl.d78 [concrete] {} {
+// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %Empty.ref: type = name_ref Empty, file.%Empty.decl [concrete = constants.%Empty.type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %impl_witness.loc16: <witness> = impl_witness () [concrete = constants.%impl_witness.1bc]
+// CHECK:STDOUT:   impl_decl @impl.77d [concrete] {} {
+// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A.type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %impl_witness.loc17: <witness> = impl_witness (@impl.77d.%AA.decl) [concrete = constants.%impl_witness.97a]
+// CHECK:STDOUT:   impl_decl @impl.c94 [concrete] {} {
+// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B.type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %impl_witness.loc20: <witness> = impl_witness (@impl.c94.%BB.decl) [concrete = constants.%impl_witness.fe4]
+// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {
+// CHECK:STDOUT:     %T.patt.loc24_6.1: %facet_type.242 = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc24_6.2 (constants.%T.patt.fd9)]
+// CHECK:STDOUT:     %t.patt: @G.%T.as_type.loc24_28.2 (%T.as_type) = binding_pattern t
+// CHECK:STDOUT:     %t.param_patt: @G.%T.as_type.loc24_28.2 (%T.as_type) = value_param_pattern %t.patt, call_param0
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %.loc24_20.1: type = splice_block %.loc24_20.3 [concrete = constants.%facet_type.242] {
+// CHECK:STDOUT:       %A.ref.loc24: type = name_ref A, file.%A.decl [concrete = constants.%A.type]
+// CHECK:STDOUT:       %Empty.ref: type = name_ref Empty, file.%Empty.decl [concrete = constants.%Empty.type]
+// CHECK:STDOUT:       %impl.elem0.loc24_12: %.d4d = impl_witness_access constants.%impl_witness.3ea, element0 [concrete = constants.%Op.444]
+// CHECK:STDOUT:       %bound_method.loc24_12: <bound method> = bound_method %A.ref.loc24, %impl.elem0.loc24_12 [concrete = constants.%Op.bound.6b1]
+// CHECK:STDOUT:       %specific_fn.loc24_12: <specific function> = specific_function %bound_method.loc24_12, @Op.1(type) [concrete = constants.%Op.specific_fn.b4b]
+// CHECK:STDOUT:       %type.and.loc24_12: init type = call %specific_fn.loc24_12(%A.ref.loc24, %Empty.ref) [concrete = constants.%facet_type.d5f]
+// CHECK:STDOUT:       %B.ref.loc24: type = name_ref B, file.%B.decl [concrete = constants.%B.type]
+// CHECK:STDOUT:       %impl.elem0.loc24_20: %.d4d = impl_witness_access constants.%impl_witness.3ea, element0 [concrete = constants.%Op.444]
+// CHECK:STDOUT:       %bound_method.loc24_20: <bound method> = bound_method %type.and.loc24_12, %impl.elem0.loc24_20 [concrete = constants.%Op.bound.b5b]
+// CHECK:STDOUT:       %specific_fn.loc24_20: <specific function> = specific_function %bound_method.loc24_20, @Op.1(type) [concrete = constants.%Op.specific_fn.165]
+// CHECK:STDOUT:       %.loc24_12.1: type = value_of_initializer %type.and.loc24_12 [concrete = constants.%facet_type.d5f]
+// CHECK:STDOUT:       %.loc24_12.2: type = converted %type.and.loc24_12, %.loc24_12.1 [concrete = constants.%facet_type.d5f]
+// CHECK:STDOUT:       %type.and.loc24_20: init type = call %specific_fn.loc24_20(%.loc24_12.2, %B.ref.loc24) [concrete = constants.%facet_type.242]
+// CHECK:STDOUT:       %.loc24_20.2: type = value_of_initializer %type.and.loc24_20 [concrete = constants.%facet_type.242]
+// CHECK:STDOUT:       %.loc24_20.3: type = converted %type.and.loc24_20, %.loc24_20.2 [concrete = constants.%facet_type.242]
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %T.loc24_6.1: %facet_type.242 = bind_symbolic_name T, 0 [symbolic = %T.loc24_6.2 (constants.%T.2df)]
+// CHECK:STDOUT:     %t.param: @G.%T.as_type.loc24_28.2 (%T.as_type) = value_param call_param0
+// CHECK:STDOUT:     %.loc24_28.1: type = splice_block %.loc24_28.2 [symbolic = %T.as_type.loc24_28.2 (constants.%T.as_type)] {
+// CHECK:STDOUT:       %T.ref.loc24: %facet_type.242 = name_ref T, %T.loc24_6.1 [symbolic = %T.loc24_6.2 (constants.%T.2df)]
+// CHECK:STDOUT:       %T.as_type.loc24_28.1: type = facet_access_type %T.ref.loc24 [symbolic = %T.as_type.loc24_28.2 (constants.%T.as_type)]
+// CHECK:STDOUT:       %.loc24_28.2: type = converted %T.ref.loc24, %T.as_type.loc24_28.1 [symbolic = %T.as_type.loc24_28.2 (constants.%T.as_type)]
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %t: @G.%T.as_type.loc24_28.2 (%T.as_type) = bind_name t, %t.param
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @Empty {
+// CHECK:STDOUT:   %Self: %Empty.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.193]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = %Self
+// CHECK:STDOUT:   .AA = <poisoned>
+// CHECK:STDOUT:   .BB = <poisoned>
+// CHECK:STDOUT:   witness = ()
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @A {
+// CHECK:STDOUT:   %Self: %A.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.31d]
+// CHECK:STDOUT:   %AA.decl: %AA.type.b97 = fn_decl @AA.1 [concrete = constants.%AA.c3a] {} {}
+// CHECK:STDOUT:   %assoc0: %A.assoc_type = assoc_entity element0, %AA.decl [concrete = constants.%assoc0.f33]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = %Self
+// CHECK:STDOUT:   .AA = %assoc0
+// CHECK:STDOUT:   .BB = <poisoned>
+// CHECK:STDOUT:   witness = (%AA.decl)
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @B {
+// CHECK:STDOUT:   %Self: %B.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.783]
+// CHECK:STDOUT:   %BB.decl: %BB.type.64d = fn_decl @BB.1 [concrete = constants.%BB.11b] {} {}
+// CHECK:STDOUT:   %assoc0: %B.assoc_type = assoc_entity element0, %BB.decl [concrete = constants.%assoc0.019]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = %Self
+// CHECK:STDOUT:   .BB = %assoc0
+// CHECK:STDOUT:   .AA = <poisoned>
+// CHECK:STDOUT:   witness = (%BB.decl)
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @BitAnd [from "core.carbon"] {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = imports.%Core.import_ref.ad0
+// CHECK:STDOUT:   .Op = imports.%Core.import_ref.08d
+// CHECK:STDOUT:   witness = (imports.%Core.Op)
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @impl.d78: %C.ref as %Empty.ref {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   witness = file.%impl_witness.loc16
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @impl.77d: %C.ref as %A.ref {
+// CHECK:STDOUT:   %AA.decl: %AA.type.c29 = fn_decl @AA.2 [concrete = constants.%AA.95d] {} {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .AA = %AA.decl
+// CHECK:STDOUT:   witness = file.%impl_witness.loc17
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @impl.c94: %C.ref as %B.ref {
+// CHECK:STDOUT:   %BB.decl: %BB.type.24d = fn_decl @BB.2 [concrete = constants.%BB.fe8] {} {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .BB = %BB.decl
+// CHECK:STDOUT:   witness = file.%impl_witness.loc20
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic impl @impl.f92(imports.%Core.import_ref.5ab3ec.1: type) [from "core.carbon"] {
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T.8b3)]
+// CHECK:STDOUT:   %T.patt: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt (constants.%T.patt.e01)]
+// CHECK:STDOUT:   %impl_witness: <witness> = impl_witness (imports.%Core.import_ref.1e6), @impl.f92(%T) [symbolic = %impl_witness (constants.%impl_witness.db8)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %Op.type: type = fn_type @Op.1, @impl.f92(%T) [symbolic = %Op.type (constants.%Op.type.f99)]
+// CHECK:STDOUT:   %Op: @impl.f92.%Op.type (%Op.type.f99) = struct_value () [symbolic = %Op (constants.%Op.05a)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type @impl.f92.%T (%T.8b3) [symbolic = %require_complete (constants.%require_complete.4ae)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   impl: imports.%Core.import_ref.583 as imports.%Core.import_ref.9c1 {
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     witness = imports.%Core.import_ref.51c
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357]
+// CHECK:STDOUT:   complete_type_witness = %complete_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = constants.%C
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @AA.1(@A.%Self: %A.type) {
+// CHECK:STDOUT:   fn();
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @BB.1(@B.%Self: %B.type) {
+// CHECK:STDOUT:   fn();
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @AA.2() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @BB.2() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @Op.1(imports.%Core.import_ref.5ab3ec.2: type) [from "core.carbon"] {
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T.8b3)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn[%self.param_patt: @Op.1.%T (%T.8b3)](%other.param_patt: @Op.1.%T (%T.8b3)) -> @Op.1.%T (%T.8b3) = "type.and";
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @Op.2(imports.%Core.import_ref.040: %BitAnd.type) [from "core.carbon"] {
+// CHECK:STDOUT:   %Self: %BitAnd.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self.25f)]
+// CHECK:STDOUT:   %Self.as_type: type = facet_access_type %Self [symbolic = %Self.as_type (constants.%Self.as_type)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn[%self.param_patt: @Op.2.%Self.as_type (%Self.as_type)](%other.param_patt: @Op.2.%Self.as_type (%Self.as_type)) -> @Op.2.%Self.as_type (%Self.as_type);
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @G(%T.loc24_6.1: %facet_type.242) {
+// CHECK:STDOUT:   %T.loc24_6.2: %facet_type.242 = bind_symbolic_name T, 0 [symbolic = %T.loc24_6.2 (constants.%T.2df)]
+// CHECK:STDOUT:   %T.patt.loc24_6.2: %facet_type.242 = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc24_6.2 (constants.%T.patt.fd9)]
+// CHECK:STDOUT:   %T.as_type.loc24_28.2: type = facet_access_type %T.loc24_6.2 [symbolic = %T.as_type.loc24_28.2 (constants.%T.as_type)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type @G.%T.as_type.loc24_28.2 (%T.as_type) [symbolic = %require_complete (constants.%require_complete.383)]
+// CHECK:STDOUT:   %T.as_wit.loc25_4.2: <witness> = facet_access_witness %T.loc24_6.2 [symbolic = %T.as_wit.loc25_4.2 (constants.%T.as_wit)]
+// CHECK:STDOUT:   %A.facet: %A.type = facet_value %T.as_type.loc24_28.2, %T.as_wit.loc25_4.2 [symbolic = %A.facet (constants.%A.facet.d6d)]
+// CHECK:STDOUT:   %.loc25_4.2: type = fn_type_with_self_type constants.%AA.type.b97, %A.facet [symbolic = %.loc25_4.2 (constants.%.124)]
+// CHECK:STDOUT:   %impl.elem0.loc25_4.2: @G.%.loc25_4.2 (%.124) = impl_witness_access %T.as_wit.loc25_4.2, element0 [symbolic = %impl.elem0.loc25_4.2 (constants.%impl.elem0.2b1)]
+// CHECK:STDOUT:   %specific_fn.loc25_4.2: <specific function> = specific_function %impl.elem0.loc25_4.2, @AA.1(%A.facet) [symbolic = %specific_fn.loc25_4.2 (constants.%specific_fn.80f)]
+// CHECK:STDOUT:   %B.facet: %B.type = facet_value %T.as_type.loc24_28.2, %T.as_wit.loc25_4.2 [symbolic = %B.facet (constants.%B.facet.1c2)]
+// CHECK:STDOUT:   %.loc26_4.2: type = fn_type_with_self_type constants.%BB.type.64d, %B.facet [symbolic = %.loc26_4.2 (constants.%.e3a)]
+// CHECK:STDOUT:   %impl.elem0.loc26_4.2: @G.%.loc26_4.2 (%.e3a) = impl_witness_access %T.as_wit.loc25_4.2, element0 [symbolic = %impl.elem0.loc26_4.2 (constants.%impl.elem0.f5b)]
+// CHECK:STDOUT:   %specific_fn.loc26_4.2: <specific function> = specific_function %impl.elem0.loc26_4.2, @BB.1(%B.facet) [symbolic = %specific_fn.loc26_4.2 (constants.%specific_fn.62f)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn[%T.patt.loc24_6.1: %facet_type.242](%t.param_patt: @G.%T.as_type.loc24_28.2 (%T.as_type)) {
+// CHECK:STDOUT:   !entry:
+// CHECK:STDOUT:     %t.ref.loc25: @G.%T.as_type.loc24_28.2 (%T.as_type) = name_ref t, %t
+// CHECK:STDOUT:     %AA.ref.loc25: %A.assoc_type = name_ref AA, @A.%assoc0 [concrete = constants.%assoc0.f33]
+// CHECK:STDOUT:     %T.as_type.loc25: type = facet_access_type constants.%T.2df [symbolic = %T.as_type.loc24_28.2 (constants.%T.as_type)]
+// CHECK:STDOUT:     %.loc25_4.1: type = converted constants.%T.2df, %T.as_type.loc25 [symbolic = %T.as_type.loc24_28.2 (constants.%T.as_type)]
+// CHECK:STDOUT:     %T.as_wit.loc25_4.1: <witness> = facet_access_witness constants.%T.2df [symbolic = %T.as_wit.loc25_4.2 (constants.%T.as_wit)]
+// CHECK:STDOUT:     %impl.elem0.loc25_4.1: @G.%.loc25_4.2 (%.124) = impl_witness_access %T.as_wit.loc25_4.1, element0 [symbolic = %impl.elem0.loc25_4.2 (constants.%impl.elem0.2b1)]
+// CHECK:STDOUT:     %specific_fn.loc25_4.1: <specific function> = specific_function %impl.elem0.loc25_4.1, @AA.1(constants.%A.facet.d6d) [symbolic = %specific_fn.loc25_4.2 (constants.%specific_fn.80f)]
+// CHECK:STDOUT:     %AA.call.loc25: init %empty_tuple.type = call %specific_fn.loc25_4.1()
+// CHECK:STDOUT:     %t.ref.loc26: @G.%T.as_type.loc24_28.2 (%T.as_type) = name_ref t, %t
+// CHECK:STDOUT:     %BB.ref.loc26: %B.assoc_type = name_ref BB, @B.%assoc0 [concrete = constants.%assoc0.019]
+// CHECK:STDOUT:     %T.as_type.loc26: type = facet_access_type constants.%T.2df [symbolic = %T.as_type.loc24_28.2 (constants.%T.as_type)]
+// CHECK:STDOUT:     %.loc26_4.1: type = converted constants.%T.2df, %T.as_type.loc26 [symbolic = %T.as_type.loc24_28.2 (constants.%T.as_type)]
+// CHECK:STDOUT:     %T.as_wit.loc26: <witness> = facet_access_witness constants.%T.2df [symbolic = %T.as_wit.loc25_4.2 (constants.%T.as_wit)]
+// CHECK:STDOUT:     %impl.elem0.loc26_4.1: @G.%.loc26_4.2 (%.e3a) = impl_witness_access %T.as_wit.loc26, element0 [symbolic = %impl.elem0.loc26_4.2 (constants.%impl.elem0.f5b)]
+// CHECK:STDOUT:     %specific_fn.loc26_4.1: <specific function> = specific_function %impl.elem0.loc26_4.1, @BB.1(constants.%B.facet.1c2) [symbolic = %specific_fn.loc26_4.2 (constants.%specific_fn.62f)]
+// CHECK:STDOUT:     %BB.call.loc26: init %empty_tuple.type = call %specific_fn.loc26_4.1()
+// CHECK:STDOUT:     %T.ref.loc28: %facet_type.242 = name_ref T, %T.loc24_6.1 [symbolic = %T.loc24_6.2 (constants.%T.2df)]
+// CHECK:STDOUT:     %AA.ref.loc28: %A.assoc_type = name_ref AA, @A.%assoc0 [concrete = constants.%assoc0.f33]
+// CHECK:STDOUT:     %T.as_type.loc28: type = facet_access_type %T.ref.loc28 [symbolic = %T.as_type.loc24_28.2 (constants.%T.as_type)]
+// CHECK:STDOUT:     %.loc28: type = converted %T.ref.loc28, %T.as_type.loc28 [symbolic = %T.as_type.loc24_28.2 (constants.%T.as_type)]
+// CHECK:STDOUT:     %T.as_wit.loc28: <witness> = facet_access_witness %T.ref.loc28 [symbolic = %T.as_wit.loc25_4.2 (constants.%T.as_wit)]
+// CHECK:STDOUT:     %impl.elem0.loc28: @G.%.loc25_4.2 (%.124) = impl_witness_access %T.as_wit.loc28, element0 [symbolic = %impl.elem0.loc25_4.2 (constants.%impl.elem0.2b1)]
+// CHECK:STDOUT:     %specific_fn.loc28: <specific function> = specific_function %impl.elem0.loc28, @AA.1(constants.%A.facet.d6d) [symbolic = %specific_fn.loc25_4.2 (constants.%specific_fn.80f)]
+// CHECK:STDOUT:     %AA.call.loc28: init %empty_tuple.type = call %specific_fn.loc28()
+// CHECK:STDOUT:     %T.ref.loc29: %facet_type.242 = name_ref T, %T.loc24_6.1 [symbolic = %T.loc24_6.2 (constants.%T.2df)]
+// CHECK:STDOUT:     %BB.ref.loc29: %B.assoc_type = name_ref BB, @B.%assoc0 [concrete = constants.%assoc0.019]
+// CHECK:STDOUT:     %T.as_type.loc29: type = facet_access_type %T.ref.loc29 [symbolic = %T.as_type.loc24_28.2 (constants.%T.as_type)]
+// CHECK:STDOUT:     %.loc29: type = converted %T.ref.loc29, %T.as_type.loc29 [symbolic = %T.as_type.loc24_28.2 (constants.%T.as_type)]
+// CHECK:STDOUT:     %T.as_wit.loc29: <witness> = facet_access_witness %T.ref.loc29 [symbolic = %T.as_wit.loc25_4.2 (constants.%T.as_wit)]
+// CHECK:STDOUT:     %impl.elem0.loc29: @G.%.loc26_4.2 (%.e3a) = impl_witness_access %T.as_wit.loc29, element0 [symbolic = %impl.elem0.loc26_4.2 (constants.%impl.elem0.f5b)]
+// CHECK:STDOUT:     %specific_fn.loc29: <specific function> = specific_function %impl.elem0.loc29, @BB.1(constants.%B.facet.1c2) [symbolic = %specific_fn.loc26_4.2 (constants.%specific_fn.62f)]
+// CHECK:STDOUT:     %BB.call.loc29: init %empty_tuple.type = call %specific_fn.loc29()
+// CHECK:STDOUT:     %T.ref.loc38: %facet_type.242 = name_ref T, %T.loc24_6.1 [symbolic = %T.loc24_6.2 (constants.%T.2df)]
+// CHECK:STDOUT:     %A.ref.loc38: type = name_ref A, file.%A.decl [concrete = constants.%A.type]
+// CHECK:STDOUT:     %AA.ref.loc38: %A.assoc_type = name_ref AA, @A.%assoc0 [concrete = constants.%assoc0.f33]
+// CHECK:STDOUT:     %T.ref.loc46: %facet_type.242 = name_ref T, %T.loc24_6.1 [symbolic = %T.loc24_6.2 (constants.%T.2df)]
+// CHECK:STDOUT:     %B.ref.loc46: type = name_ref B, file.%B.decl [concrete = constants.%B.type]
+// CHECK:STDOUT:     %BB.ref.loc46: %B.assoc_type = name_ref BB, @B.%assoc0 [concrete = constants.%assoc0.019]
+// CHECK:STDOUT:     return
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @F() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]
+// CHECK:STDOUT:   %.loc61_6.1: %empty_struct_type = struct_literal ()
+// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:   %.loc61_6.2: ref %C = temporary_storage
+// CHECK:STDOUT:   %.loc61_6.3: init %C = class_init (), %.loc61_6.2 [concrete = constants.%C.val]
+// CHECK:STDOUT:   %.loc61_6.4: ref %C = temporary %.loc61_6.2, %.loc61_6.3
+// CHECK:STDOUT:   %.loc61_8.1: ref %C = converted %.loc61_6.1, %.loc61_6.4
+// CHECK:STDOUT:   %facet_value.loc61_12.1: %facet_type.242 = facet_value constants.%C, constants.%impl_witness.1bc [concrete = constants.%facet_value]
+// CHECK:STDOUT:   %.loc61_12.1: %facet_type.242 = converted constants.%C, %facet_value.loc61_12.1 [concrete = constants.%facet_value]
+// CHECK:STDOUT:   %facet_value.loc61_12.2: %facet_type.242 = facet_value constants.%C, constants.%impl_witness.1bc [concrete = constants.%facet_value]
+// CHECK:STDOUT:   %.loc61_12.2: %facet_type.242 = converted constants.%C, %facet_value.loc61_12.2 [concrete = constants.%facet_value]
+// CHECK:STDOUT:   %G.specific_fn: <specific function> = specific_function %G.ref, @G(constants.%facet_value) [concrete = constants.%G.specific_fn]
+// CHECK:STDOUT:   %.loc61_8.2: %C = bind_value %.loc61_8.1
+// CHECK:STDOUT:   %G.call: init %empty_tuple.type = call %G.specific_fn(%.loc61_8.2)
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @AA.1(constants.%Self.31d) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @BB.1(constants.%Self.783) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @AA.1(constants.%A.facet.afe) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @BB.1(constants.%B.facet.3a2) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @impl.f92(constants.%T.8b3) {
+// CHECK:STDOUT:   %T => constants.%T.8b3
+// CHECK:STDOUT:   %T.patt => constants.%T.8b3
+// CHECK:STDOUT:   %impl_witness => constants.%impl_witness.db8
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @impl.f92(%T) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Op.1(constants.%T.8b3) {
+// CHECK:STDOUT:   %T => constants.%T.8b3
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @impl.f92(type) {
+// CHECK:STDOUT:   %T => type
+// CHECK:STDOUT:   %T.patt => type
+// CHECK:STDOUT:   %impl_witness => constants.%impl_witness.3ea
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %Op.type => constants.%Op.type.eb8
+// CHECK:STDOUT:   %Op => constants.%Op.444
+// CHECK:STDOUT:   %require_complete => constants.%complete_type.473
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Op.2(constants.%Self.25f) {
+// CHECK:STDOUT:   %Self => constants.%Self.25f
+// CHECK:STDOUT:   %Self.as_type => constants.%Self.as_type
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Op.1(type) {
+// CHECK:STDOUT:   %T => type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @G(constants.%T.2df) {
+// CHECK:STDOUT:   %T.loc24_6.2 => constants.%T.2df
+// CHECK:STDOUT:   %T.patt.loc24_6.2 => constants.%T.2df
+// CHECK:STDOUT:   %T.as_type.loc24_28.2 => constants.%T.as_type
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @AA.1(constants.%A.facet.d6d) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @BB.1(constants.%B.facet.1c2) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @AA.1(@G.%A.facet) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @BB.1(@G.%B.facet) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @G(constants.%facet_value) {
+// CHECK:STDOUT:   %T.loc24_6.2 => constants.%facet_value
+// CHECK:STDOUT:   %T.patt.loc24_6.2 => constants.%facet_value
+// CHECK:STDOUT:   %T.as_type.loc24_28.2 => constants.%C
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %require_complete => constants.%complete_type.357
+// CHECK:STDOUT:   %T.as_wit.loc25_4.2 => constants.%impl_witness.1bc
+// CHECK:STDOUT:   %A.facet => constants.%A.facet.beb
+// CHECK:STDOUT:   %.loc25_4.2 => constants.%.778
+// CHECK:STDOUT:   %impl.elem0.loc25_4.2 => <error>
+// CHECK:STDOUT:   %specific_fn.loc25_4.2 => <error>
+// CHECK:STDOUT:   %B.facet => constants.%B.facet.5e0
+// CHECK:STDOUT:   %.loc26_4.2 => constants.%.555
+// CHECK:STDOUT:   %impl.elem0.loc26_4.2 => <error>
+// CHECK:STDOUT:   %specific_fn.loc26_4.2 => <error>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 286 - 21
toolchain/check/testdata/impl/fail_todo_use_assoc_const.carbon

@@ -43,7 +43,7 @@ impl C as J where .U = C {
   fn F[self: Self](u: C) -> C { return self; }
 }
 
-// --- fail_todo_use_non-type_in_function.carbon
+// --- use_non-type_in_function.carbon
 library "[[@TEST_NAME]]";
 
 interface M {
@@ -53,13 +53,29 @@ interface M {
 
 impl () as M where .Z = {.b = {}} {
   fn G() -> {} {
-    // CHECK:STDERR: fail_todo_use_non-type_in_function.carbon:[[@LINE+7]]:13: error: cannot convert value of type `type` to `M` with `as` [ExplicitAsConversionFailure]
-    // CHECK:STDERR:     return (Self as M).Z.b;
-    // CHECK:STDERR:             ^~~~~~~~~
-    // CHECK:STDERR: fail_todo_use_non-type_in_function.carbon:[[@LINE+4]]:13: note: type `type` does not implement interface `Core.As(M)` [MissingImplInMemberAccessNote]
-    // CHECK:STDERR:     return (Self as M).Z.b;
-    // CHECK:STDERR:             ^~~~~~~~~
-    // CHECK:STDERR:
+    return (Self as M).Z.b;
+  }
+}
+
+// --- self_as_uses_correct_rewrite_constraint.carbon
+
+library "[[@TEST_NAME]]";
+
+class C(T:! type) {}
+
+interface M {
+  let Z:! {.b: type};
+  fn G() -> type;
+}
+
+impl C({}) as M where .Z = {.b = {}} {
+  fn G() -> type {
+    return (Self as M).Z.b;
+  }
+}
+
+impl C(()) as M where .Z = {.b = ()} {
+  fn G() -> type {
     return (Self as M).Z.b;
   }
 }
@@ -316,16 +332,16 @@ impl () as I where .N = 2 {
 // CHECK:STDOUT:   %Self.as_type.loc19_14.1 => constants.%C
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- fail_todo_use_non-type_in_function.carbon
+// CHECK:STDOUT: --- use_non-type_in_function.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %M.type: type = facet_type <@M> [concrete]
-// CHECK:STDOUT:   %Self.bcc: %M.type = bind_symbolic_name Self, 0 [symbolic]
+// CHECK:STDOUT:   %Self: %M.type = bind_symbolic_name Self, 0 [symbolic]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
 // CHECK:STDOUT:   %struct_type.b.347: type = struct_type {.b: %empty_struct_type} [concrete]
 // CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %M.assoc_type: type = assoc_entity_type %M.type [concrete]
-// CHECK:STDOUT:   %assoc0.e3d: %M.assoc_type = assoc_entity element0, @M.%Z [concrete]
+// CHECK:STDOUT:   %assoc0: %M.assoc_type = assoc_entity element0, @M.%Z [concrete]
 // CHECK:STDOUT:   %G.type.020: type = fn_type @G.1 [concrete]
 // CHECK:STDOUT:   %G.91c: %G.type.020 = struct_value () [concrete]
 // CHECK:STDOUT:   %assoc1: %M.assoc_type = assoc_entity element1, @M.%G.decl [concrete]
@@ -345,7 +361,6 @@ impl () as I where .N = 2 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
-// CHECK:STDOUT:     .As = %Core.As
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -364,7 +379,7 @@ impl () as I where .N = 2 {
 // CHECK:STDOUT:     %M.ref: type = name_ref M, file.%M.decl [concrete = constants.%M.type]
 // CHECK:STDOUT:     %.Self: %M.type = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
 // CHECK:STDOUT:     %.Self.ref: %M.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]
-// CHECK:STDOUT:     %Z.ref: %M.assoc_type = name_ref Z, @Z.%assoc0 [concrete = constants.%assoc0.e3d]
+// CHECK:STDOUT:     %Z.ref: %M.assoc_type = name_ref Z, @Z.%assoc0 [concrete = constants.%assoc0]
 // 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:     %.Self.as_wit: <witness> = facet_access_witness %.Self.ref [symbolic_self = constants.%.Self.as_wit]
@@ -383,9 +398,9 @@ impl () as I where .N = 2 {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: interface @M {
-// CHECK:STDOUT:   %Self: %M.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.bcc]
+// CHECK:STDOUT:   %Self: %M.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self]
 // CHECK:STDOUT:   %Z: %struct_type.b.347 = assoc_const_decl @Z [concrete] {
-// CHECK:STDOUT:     %assoc0: %M.assoc_type = assoc_entity element0, @M.%Z [concrete = constants.%assoc0.e3d]
+// CHECK:STDOUT:     %assoc0: %M.assoc_type = assoc_entity element0, @M.%Z [concrete = constants.%assoc0]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %G.decl: %G.type.020 = fn_decl @G.1 [concrete = constants.%G.91c] {
 // CHECK:STDOUT:     %return.patt: %empty_struct_type = return_slot_pattern
@@ -434,20 +449,270 @@ impl () as I where .N = 2 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Self.ref: type = name_ref Self, @impl.%.loc8_7.2 [concrete = constants.%empty_tuple.type]
 // CHECK:STDOUT:   %M.ref: type = name_ref M, file.%M.decl [concrete = constants.%M.type]
-// CHECK:STDOUT:   %.loc17: %M.type = converted %Self.ref, <error> [concrete = <error>]
-// CHECK:STDOUT:   %Z.ref: <error> = name_ref Z, <error> [concrete = <error>]
-// CHECK:STDOUT:   %b.ref: <error> = name_ref b, <error> [concrete = <error>]
-// CHECK:STDOUT:   return <error>
+// CHECK:STDOUT:   %M.facet: %M.type = facet_value constants.%empty_tuple.type, constants.%impl_witness [concrete = constants.%M.facet.940]
+// CHECK:STDOUT:   %.loc10_18: %M.type = converted %Self.ref, %M.facet [concrete = constants.%M.facet.940]
+// CHECK:STDOUT:   %Z.ref: %M.assoc_type = name_ref Z, @Z.%assoc0 [concrete = constants.%assoc0]
+// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc10_18 [concrete = constants.%empty_tuple.type]
+// CHECK:STDOUT:   %.loc10_23: type = converted %.loc10_18, %as_type [concrete = constants.%empty_tuple.type]
+// CHECK:STDOUT:   %as_wit: <witness> = facet_access_witness %.loc10_18 [concrete = constants.%impl_witness]
+// CHECK:STDOUT:   %impl.elem0: %struct_type.b.347 = impl_witness_access %as_wit, element0 [concrete = constants.%struct]
+// CHECK:STDOUT:   %.loc10_25: %empty_struct_type = struct_access %impl.elem0, element0 [concrete = constants.%empty_struct]
+// CHECK:STDOUT:   return %.loc10_25
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @Z(constants.%Self.bcc) {}
+// CHECK:STDOUT: specific @Z(constants.%Self) {}
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @G.1(constants.%Self.bcc) {}
+// CHECK:STDOUT: specific @G.1(constants.%Self) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @Z(constants.%M.facet.ba5) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @G.1(constants.%M.facet.940) {}
 // CHECK:STDOUT:
+// CHECK:STDOUT: specific @Z(constants.%M.facet.940) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- self_as_uses_correct_rewrite_constraint.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %T.patt: type = symbolic_binding_pattern T, 0 [symbolic]
+// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
+// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]
+// CHECK:STDOUT:   %C.f2e: type = class_type @C, @C(%T) [symbolic]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %M.type: type = facet_type <@M> [concrete]
+// CHECK:STDOUT:   %Self: %M.type = bind_symbolic_name Self, 0 [symbolic]
+// CHECK:STDOUT:   %struct_type.b.86f: type = struct_type {.b: type} [concrete]
+// CHECK:STDOUT:   %M.assoc_type: type = assoc_entity_type %M.type [concrete]
+// CHECK:STDOUT:   %assoc0: %M.assoc_type = assoc_entity element0, @M.%Z [concrete]
+// CHECK:STDOUT:   %G.type.020: type = fn_type @G.1 [concrete]
+// CHECK:STDOUT:   %G.91c: %G.type.020 = struct_value () [concrete]
+// CHECK:STDOUT:   %assoc1: %M.assoc_type = assoc_entity element1, @M.%G.decl [concrete]
+// CHECK:STDOUT:   %C.7a7: type = class_type @C, @C(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %.Self: %M.type = bind_symbolic_name .Self [symbolic_self]
+// CHECK:STDOUT:   %.Self.as_type: type = facet_access_type %.Self [symbolic_self]
+// CHECK:STDOUT:   %.Self.as_wit: <witness> = facet_access_witness %.Self [symbolic_self]
+// CHECK:STDOUT:   %M.facet.ba5: %M.type = facet_value %.Self.as_type, %.Self.as_wit [symbolic_self]
+// CHECK:STDOUT:   %impl.elem0: %struct_type.b.86f = impl_witness_access %.Self.as_wit, element0 [symbolic_self]
+// CHECK:STDOUT:   %struct_type.b.347: type = struct_type {.b: %empty_struct_type} [concrete]
+// CHECK:STDOUT:   %struct.0f3: %struct_type.b.86f = struct_value (%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %M_where.type.fd0: type = facet_type <@M where %impl.elem0 = %struct.0f3> [concrete]
+// CHECK:STDOUT:   %impl_witness.046: <witness> = impl_witness (%struct.0f3, @impl.b80.%G.decl) [concrete]
+// CHECK:STDOUT:   %G.type.bce: type = fn_type @G.2 [concrete]
+// CHECK:STDOUT:   %G.8af: %G.type.bce = struct_value () [concrete]
+// CHECK:STDOUT:   %M.facet.f90: %M.type = facet_value %C.7a7, %impl_witness.046 [concrete]
+// CHECK:STDOUT:   %C.3a0: type = class_type @C, @C(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %struct_type.b.161: type = struct_type {.b: %empty_tuple.type} [concrete]
+// CHECK:STDOUT:   %struct.c94: %struct_type.b.86f = struct_value (%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %M_where.type.b49: type = facet_type <@M where %impl.elem0 = %struct.c94> [concrete]
+// CHECK:STDOUT:   %impl_witness.e37: <witness> = impl_witness (%struct.c94, @impl.be1.%G.decl) [concrete]
+// CHECK:STDOUT:   %G.type.875: type = fn_type @G.3 [concrete]
+// CHECK:STDOUT:   %G.702: %G.type.875 = struct_value () [concrete]
+// CHECK:STDOUT:   %M.facet.2a4: %M.type = facet_value %C.3a0, %impl_witness.e37 [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
+// CHECK:STDOUT:     import Core//prelude
+// CHECK:STDOUT:     import Core//prelude/...
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .Core = imports.%Core
+// CHECK:STDOUT:     .C = %C.decl
+// CHECK:STDOUT:     .M = %M.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {
+// CHECK:STDOUT:     %T.patt.loc4_9.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_9.2 (constants.%T.patt)]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %T.loc4_9.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_9.2 (constants.%T)]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %M.decl: type = interface_decl @M [concrete = constants.%M.type] {} {}
+// CHECK:STDOUT:   impl_decl @impl.b80 [concrete] {} {
+// CHECK:STDOUT:     %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]
+// CHECK:STDOUT:     %.loc11_9: %empty_struct_type = struct_literal ()
+// CHECK:STDOUT:     %.loc11_10: type = converted %.loc11_9, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
+// CHECK:STDOUT:     %C: type = class_type @C, @C(constants.%empty_struct_type) [concrete = constants.%C.7a7]
+// CHECK:STDOUT:     %M.ref: type = name_ref M, file.%M.decl [concrete = constants.%M.type]
+// CHECK:STDOUT:     %.Self: %M.type = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %.Self.ref: %M.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %Z.ref: %M.assoc_type = name_ref Z, @Z.%assoc0 [concrete = constants.%assoc0]
+// CHECK:STDOUT:     %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
+// CHECK:STDOUT:     %.loc11_23: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
+// CHECK:STDOUT:     %.Self.as_wit: <witness> = facet_access_witness %.Self.ref [symbolic_self = constants.%.Self.as_wit]
+// CHECK:STDOUT:     %impl.elem0: %struct_type.b.86f = impl_witness_access %.Self.as_wit, element0 [symbolic_self = constants.%impl.elem0]
+// CHECK:STDOUT:     %.loc11_35: %empty_struct_type = struct_literal ()
+// CHECK:STDOUT:     %.loc11_36.1: %struct_type.b.347 = struct_literal (%.loc11_35)
+// CHECK:STDOUT:     %.loc11_36.2: type = converted %.loc11_35, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
+// CHECK:STDOUT:     %struct: %struct_type.b.86f = struct_value (%.loc11_36.2) [concrete = constants.%struct.0f3]
+// CHECK:STDOUT:     %.loc11_36.3: %struct_type.b.86f = converted %.loc11_36.1, %struct [concrete = constants.%struct.0f3]
+// CHECK:STDOUT:     %.loc11_17: type = where_expr %.Self [concrete = constants.%M_where.type.fd0] {
+// CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc11_36.3
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %impl_witness.loc11: <witness> = impl_witness (constants.%struct.0f3, @impl.b80.%G.decl) [concrete = constants.%impl_witness.046]
+// CHECK:STDOUT:   impl_decl @impl.be1 [concrete] {} {
+// CHECK:STDOUT:     %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]
+// CHECK:STDOUT:     %.loc17_9: %empty_tuple.type = tuple_literal ()
+// CHECK:STDOUT:     %.loc17_10: type = converted %.loc17_9, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
+// CHECK:STDOUT:     %C: type = class_type @C, @C(constants.%empty_tuple.type) [concrete = constants.%C.3a0]
+// CHECK:STDOUT:     %M.ref: type = name_ref M, file.%M.decl [concrete = constants.%M.type]
+// CHECK:STDOUT:     %.Self: %M.type = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %.Self.ref: %M.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %Z.ref: %M.assoc_type = name_ref Z, @Z.%assoc0 [concrete = constants.%assoc0]
+// CHECK:STDOUT:     %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type]
+// CHECK:STDOUT:     %.loc17_23: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type]
+// CHECK:STDOUT:     %.Self.as_wit: <witness> = facet_access_witness %.Self.ref [symbolic_self = constants.%.Self.as_wit]
+// CHECK:STDOUT:     %impl.elem0: %struct_type.b.86f = impl_witness_access %.Self.as_wit, element0 [symbolic_self = constants.%impl.elem0]
+// CHECK:STDOUT:     %.loc17_35: %empty_tuple.type = tuple_literal ()
+// CHECK:STDOUT:     %.loc17_36.1: %struct_type.b.161 = struct_literal (%.loc17_35)
+// CHECK:STDOUT:     %.loc17_36.2: type = converted %.loc17_35, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
+// CHECK:STDOUT:     %struct: %struct_type.b.86f = struct_value (%.loc17_36.2) [concrete = constants.%struct.c94]
+// CHECK:STDOUT:     %.loc17_36.3: %struct_type.b.86f = converted %.loc17_36.1, %struct [concrete = constants.%struct.c94]
+// CHECK:STDOUT:     %.loc17_17: type = where_expr %.Self [concrete = constants.%M_where.type.b49] {
+// CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc17_36.3
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %impl_witness.loc17: <witness> = impl_witness (constants.%struct.c94, @impl.be1.%G.decl) [concrete = constants.%impl_witness.e37]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @M {
+// CHECK:STDOUT:   %Self: %M.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self]
+// CHECK:STDOUT:   %Z: %struct_type.b.86f = assoc_const_decl @Z [concrete] {
+// CHECK:STDOUT:     %assoc0: %M.assoc_type = assoc_entity element0, @M.%Z [concrete = constants.%assoc0]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %G.decl: %G.type.020 = fn_decl @G.1 [concrete = constants.%G.91c] {
+// CHECK:STDOUT:     %return.patt: type = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: type = out_param_pattern %return.patt, call_param0
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %return.param: ref type = out_param call_param0
+// CHECK:STDOUT:     %return: ref type = return_slot %return.param
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %assoc1: %M.assoc_type = assoc_entity element1, %G.decl [concrete = constants.%assoc1]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = %Self
+// CHECK:STDOUT:   .Z = @Z.%assoc0
+// CHECK:STDOUT:   .G = %assoc1
+// CHECK:STDOUT:   witness = (%Z, %G.decl)
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic assoc_const @Z(@M.%Self: %M.type) {
+// CHECK:STDOUT:   assoc_const Z:! %struct_type.b.86f;
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @impl.b80: %C as %.loc11_17 {
+// CHECK:STDOUT:   %G.decl: %G.type.bce = fn_decl @G.2 [concrete = constants.%G.8af] {
+// CHECK:STDOUT:     %return.patt: type = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: type = out_param_pattern %return.patt, call_param0
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %return.param: ref type = out_param call_param0
+// CHECK:STDOUT:     %return: ref type = return_slot %return.param
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .G = %G.decl
+// CHECK:STDOUT:   .M = <poisoned>
+// CHECK:STDOUT:   witness = file.%impl_witness.loc11
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @impl.be1: %C as %.loc17_17 {
+// CHECK:STDOUT:   %G.decl: %G.type.875 = fn_decl @G.3 [concrete = constants.%G.702] {
+// CHECK:STDOUT:     %return.patt: type = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: type = out_param_pattern %return.patt, call_param0
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %return.param: ref type = out_param call_param0
+// CHECK:STDOUT:     %return: ref type = return_slot %return.param
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .G = %G.decl
+// CHECK:STDOUT:   .M = <poisoned>
+// CHECK:STDOUT:   witness = file.%impl_witness.loc17
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic class @C(%T.loc4_9.1: type) {
+// CHECK:STDOUT:   %T.loc4_9.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_9.2 (constants.%T)]
+// CHECK:STDOUT:   %T.patt.loc4_9.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_9.2 (constants.%T.patt)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:
+// CHECK:STDOUT:   class {
+// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:     complete_type_witness = %complete_type
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = constants.%C.f2e
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic fn @G.1(@M.%Self: %M.type) {
+// CHECK:STDOUT:   fn() -> type;
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @G.2() -> type {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %Self.ref: type = name_ref Self, @impl.b80.%C [concrete = constants.%C.7a7]
+// CHECK:STDOUT:   %M.ref: type = name_ref M, file.%M.decl [concrete = constants.%M.type]
+// CHECK:STDOUT:   %M.facet: %M.type = facet_value constants.%C.7a7, constants.%impl_witness.046 [concrete = constants.%M.facet.f90]
+// CHECK:STDOUT:   %.loc13_18: %M.type = converted %Self.ref, %M.facet [concrete = constants.%M.facet.f90]
+// CHECK:STDOUT:   %Z.ref: %M.assoc_type = name_ref Z, @Z.%assoc0 [concrete = constants.%assoc0]
+// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc13_18 [concrete = constants.%C.7a7]
+// CHECK:STDOUT:   %.loc13_23: type = converted %.loc13_18, %as_type [concrete = constants.%C.7a7]
+// CHECK:STDOUT:   %as_wit: <witness> = facet_access_witness %.loc13_18 [concrete = constants.%impl_witness.046]
+// CHECK:STDOUT:   %impl.elem0: %struct_type.b.86f = impl_witness_access %as_wit, element0 [concrete = constants.%struct.0f3]
+// CHECK:STDOUT:   %.loc13_25: type = struct_access %impl.elem0, element0 [concrete = constants.%empty_struct_type]
+// CHECK:STDOUT:   return %.loc13_25
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @G.3() -> type {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %Self.ref: type = name_ref Self, @impl.be1.%C [concrete = constants.%C.3a0]
+// CHECK:STDOUT:   %M.ref: type = name_ref M, file.%M.decl [concrete = constants.%M.type]
+// CHECK:STDOUT:   %M.facet: %M.type = facet_value constants.%C.3a0, constants.%impl_witness.e37 [concrete = constants.%M.facet.2a4]
+// CHECK:STDOUT:   %.loc19_18: %M.type = converted %Self.ref, %M.facet [concrete = constants.%M.facet.2a4]
+// CHECK:STDOUT:   %Z.ref: %M.assoc_type = name_ref Z, @Z.%assoc0 [concrete = constants.%assoc0]
+// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc19_18 [concrete = constants.%C.3a0]
+// CHECK:STDOUT:   %.loc19_23: type = converted %.loc19_18, %as_type [concrete = constants.%C.3a0]
+// CHECK:STDOUT:   %as_wit: <witness> = facet_access_witness %.loc19_18 [concrete = constants.%impl_witness.e37]
+// CHECK:STDOUT:   %impl.elem0: %struct_type.b.86f = impl_witness_access %as_wit, element0 [concrete = constants.%struct.c94]
+// CHECK:STDOUT:   %.loc19_25: type = struct_access %impl.elem0, element0 [concrete = constants.%empty_tuple.type]
+// CHECK:STDOUT:   return %.loc19_25
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @C(constants.%T) {
+// CHECK:STDOUT:   %T.loc4_9.2 => constants.%T
+// CHECK:STDOUT:   %T.patt.loc4_9.2 => constants.%T
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Z(constants.%Self) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @G.1(constants.%Self) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @C(constants.%empty_struct_type) {
+// CHECK:STDOUT:   %T.loc4_9.2 => constants.%empty_struct_type
+// CHECK:STDOUT:   %T.patt.loc4_9.2 => constants.%empty_struct_type
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Z(constants.%M.facet.ba5) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @G.1(constants.%M.facet.f90) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Z(constants.%M.facet.f90) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @C(constants.%empty_tuple.type) {
+// CHECK:STDOUT:   %T.loc4_9.2 => constants.%empty_tuple.type
+// CHECK:STDOUT:   %T.patt.loc4_9.2 => constants.%empty_tuple.type
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @G.1(constants.%M.facet.2a4) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Z(constants.%M.facet.2a4) {}
+// CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_todo_associated_int_in_array.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {

+ 15 - 0
toolchain/check/testdata/impl/no_prelude/impl_cycle.carbon

@@ -181,6 +181,21 @@ fn F() {
   // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   // CHECK:STDERR:
   Compare({} as C, {} as D);
+
+  // CHECK:STDERR: fail_impl_cycle_one_generic_param.carbon:[[@LINE+13]]:3: error: cycle found in search for impl of `ComparableWith(D)` for type `C` [ImplLookupCycle]
+  // CHECK:STDERR:   Compare({} as D, {} as C);
+  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~
+  // CHECK:STDERR: fail_impl_cycle_one_generic_param.carbon:[[@LINE-50]]:1: note: determining if this impl clause matches [ImplLookupCycleNote]
+  // CHECK:STDERR: impl forall [U:! type, T:! ComparableWith(U)]
+  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  // CHECK:STDERR: fail_impl_cycle_one_generic_param.carbon:[[@LINE-53]]:1: note: determining if this impl clause matches [ImplLookupCycleNote]
+  // CHECK:STDERR: impl forall [U:! type, T:! ComparableWith(U)]
+  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  // CHECK:STDERR: fail_impl_cycle_one_generic_param.carbon:[[@LINE-49]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
+  // CHECK:STDERR: fn Compare[T:! type, U:! ComparableWith(T)](t: T, u: U) {}
+  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  // CHECK:STDERR:
+  Compare({} as D, {} as C);
 }
 
 // --- impl_recurse_with_simpler_type_no_cycle.carbon

+ 0 - 7
toolchain/sem_ir/constant.h

@@ -118,13 +118,6 @@ class ConstantValueStore {
     return GetInstId(Get(inst_id));
   }
 
-  // Returns whether two constant IDs represent the same constant value. This
-  // includes the case where they might be in different generics and thus might
-  // have different ConstantIds, but are still symbolically equal.
-  auto AreEqualAcrossDeclarations(ConstantId a, ConstantId b) const -> bool {
-    return GetInstId(a) == GetInstId(b);
-  }
-
   auto AddSymbolicConstant(SymbolicConstant constant) -> ConstantId {
     symbolic_constants_.push_back(constant);
     return ConstantId::ForSymbolicConstantIndex(symbolic_constants_.size() - 1);