Explorar el Código

Type completion of facet types is separate from Identifying (#6385)

Identifying a facet type is an operation on a pair of (self type, facet
type). It substitutes that self in as the `Self` of any require
declarations in order to form the set of (self type, SpecificInterface)
pairs that constitute the requirements of the IdentifiedFacetType.
Currently we don't pass around any self type, and assume all require
declarations are written against `Self` but this will change in the
future.

By contrast, type completion is done in the abstract and does not form
specifics for the require declarations. The purpose of type completion
is to enumerate the scopes where name lookup can occur and ensure they
are completed.

With this change, type completion is:
- No longer built on top of identification for facet types.
- Recursively ensures all `extend` scopes are complete since name lookup
can find symbols in them.

We add some test cases that demonstrate consistency between a resolving
the specific of a generic class, and a generic interface/constraint,
both used in a type position. In all cases, an invalid specific is not
materialized for the type completion when the specific's arguments are
used in a non-extend context. But they specific is materialized and
checked for type completion when in an extend context (extend impl or
extend require).

Type completion itself does not need to recurse into named constraints
or interfaces as the `extend require` declarations require the type to
be complete immediately, just as for `extend impl` in a class.

We had a test (`fail_incomplete_where.carbon`) with `impl as J where
.Self impls K` and `J` is incomplete, which used to be diagnosed but no
longer is, because we don't require non-extend interfaces to be complete
in type completion, nor in identification. The test was trying to test
the presence of rewrite constraints though, which it didn't even use. So
we remove the diagnostic that we can't hit anymore and replaced it with
a TODO, and add a test that should reach that TODO once qualified
rewrite constraints work.
Dana Jansens hace 5 meses
padre
commit
201e408252

+ 8 - 0
toolchain/check/eval.cpp

@@ -867,6 +867,14 @@ static auto ResolveSpecificDeclForInst(EvalContext& eval_context,
         for (const auto& interface : info.self_impls_constraints) {
           ResolveSpecificDeclForSpecificId(eval_context, interface.specific_id);
         }
+        for (const auto& constraint : info.extend_named_constraints) {
+          ResolveSpecificDeclForSpecificId(eval_context,
+                                           constraint.specific_id);
+        }
+        for (const auto& constraint : info.self_impls_named_constraints) {
+          ResolveSpecificDeclForSpecificId(eval_context,
+                                           constraint.specific_id);
+        }
         break;
       }
       case CARBON_KIND(SemIR::SpecificId specific_id): {

+ 12 - 14
toolchain/check/facet_type.cpp

@@ -55,20 +55,15 @@ static auto WitnessQueryMatchesInterface(
 static auto IncompleteFacetTypeDiagnosticBuilder(
     Context& context, SemIR::LocId loc_id, SemIR::TypeInstId facet_type_inst_id,
     bool is_definition) -> DiagnosticBuilder {
-  if (is_definition) {
-    CARBON_DIAGNOSTIC(ImplAsIncompleteFacetTypeDefinition, Error,
-                      "definition of impl as incomplete facet type {0}",
-                      InstIdAsType);
-    return context.emitter().Build(loc_id, ImplAsIncompleteFacetTypeDefinition,
-                                   facet_type_inst_id);
-  } else {
-    CARBON_DIAGNOSTIC(
-        ImplAsIncompleteFacetTypeRewrites, Error,
-        "declaration of impl as incomplete facet type {0} with rewrites",
-        InstIdAsType);
-    return context.emitter().Build(loc_id, ImplAsIncompleteFacetTypeRewrites,
-                                   facet_type_inst_id);
-  }
+  // TODO: Remove this parameter. Facet types don't need to be complete for impl
+  // declarations, unless there's a rewrite into `.Self`. But that completeness
+  // is checked/required by the member access of the rewrite.
+  CARBON_CHECK(is_definition);
+  CARBON_DIAGNOSTIC(ImplAsIncompleteFacetTypeDefinition, Error,
+                    "definition of impl as incomplete facet type {0}",
+                    InstIdAsType);
+  return context.emitter().Build(loc_id, ImplAsIncompleteFacetTypeDefinition,
+                                 facet_type_inst_id);
 }
 
 auto GetImplWitnessAccessWithoutSubstitution(Context& context,
@@ -105,6 +100,9 @@ auto InitialFacetTypeImplWitness(
          .specific_id = self_specific_id});
   }
 
+  // The presence of any rewrite constraints requires that we know how many
+  // entries to allocate in the witness table, which requires the entire facet
+  // type to be complete, even if this was a declaration.
   if (!RequireCompleteType(
           context, facet_type_id, SemIR::LocId(facet_type_inst_id), [&] {
             return IncompleteFacetTypeDiagnosticBuilder(

+ 30 - 7
toolchain/check/handle_require.cpp

@@ -154,6 +154,7 @@ static auto TypeStructureReferencesSelf(
 
 struct ValidateRequireResult {
   SemIR::FacetType facet_type;
+  SemIR::TypeId facet_type_type_id;
   const SemIR::IdentifiedFacetType* identified;
 };
 
@@ -164,12 +165,14 @@ static auto ValidateRequire(Context& context, SemIR::LocId loc_id,
                             SemIR::InstId constraint_inst_id,
                             SemIR::InstId scope_inst_id)
     -> std::optional<ValidateRequireResult> {
-  auto constraint_constant_value_inst_id =
-      context.constant_values().GetConstantInstId(constraint_inst_id);
-  auto constraint_facet_type = context.insts().TryGetAs<SemIR::FacetType>(
-      constraint_constant_value_inst_id);
+  auto constraint_constant_value_id =
+      context.constant_values().Get(constraint_inst_id);
+  auto constraint_type_id =
+      SemIR::TypeId::ForTypeConstant(constraint_constant_value_id);
+  auto constraint_facet_type =
+      context.types().TryGetAs<SemIR::FacetType>(constraint_type_id);
   if (!constraint_facet_type) {
-    if (constraint_constant_value_inst_id != SemIR::ErrorInst::InstId) {
+    if (constraint_constant_value_id != SemIR::ErrorInst::ConstantId) {
       CARBON_DIAGNOSTIC(
           RequireImplsMissingFacetType, Error,
           "`require` declaration constrained by a non-facet type; "
@@ -218,6 +221,7 @@ static auto ValidateRequire(Context& context, SemIR::LocId loc_id,
   }
 
   return ValidateRequireResult{.facet_type = *constraint_facet_type,
+                               .facet_type_type_id = constraint_type_id,
                                .identified = &identified};
 }
 
@@ -244,7 +248,7 @@ auto HandleParseNode(Context& context, Parse::RequireDeclId node_id) -> bool {
     return true;
   }
 
-  auto [constraint_facet_type, identified] = *validated;
+  auto [constraint_facet_type, constraint_type_id, identified] = *validated;
   if (identified->required_interfaces().empty()) {
     // A `require T impls type` adds no actual constraints, so nothing to do.
     DiscardGenericDecl(context);
@@ -271,8 +275,27 @@ auto HandleParseNode(Context& context, Parse::RequireDeclId node_id) -> bool {
   require_impls_decl.require_impls_id = require_impls_id;
   ReplaceInstBeforeConstantUse(context, decl_id, require_impls_decl);
 
-  context.require_impls_stack().AppendToTop(require_impls_id);
+  // We look for a complete type after BuildGenericDecl, so that the resulting
+  // RequireCompleteType instruction is part of the enclosing interface or named
+  // constraint generic definition. Then requiring enclosing entity to be
+  // complete will resolve that definition (via ResolveSpecificDefinition()) and
+  // also construct a specific for the `constraint_inst_id`, finding any
+  // monomorphization errors that result.
+  if (extend) {
+    if (!RequireCompleteType(
+            context, constraint_type_id, SemIR::LocId(constraint_inst_id), [&] {
+              CARBON_DIAGNOSTIC(RequireImplsIncompleteFacetType, Error,
+                                "`extend require` of incomplete facet type {0}",
+                                InstIdAsType);
+              return context.emitter().Build(constraint_inst_id,
+                                             RequireImplsIncompleteFacetType,
+                                             constraint_inst_id);
+            })) {
+      return true;
+    }
+  }
 
+  context.require_impls_stack().AppendToTop(require_impls_id);
   return true;
 }
 

+ 1 - 1
toolchain/check/interface.cpp

@@ -122,7 +122,7 @@ static auto GetGenericArgsWithSelfType(Context& context,
   arg_ids.reserve(std::max(reserve_args_size, interface_args.size() + 1));
 
   // Start with the enclosing arguments from the interface.
-  arg_ids.assign(interface_args.begin(), interface_args.end());
+  llvm::append_range(arg_ids, interface_args);
 
   // Add the `Self` argument.
   arg_ids.push_back(GetSelfFacet(context, interface_specific_id, generic_id,

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

@@ -10,99 +10,6 @@
 // TIP: To dump output, run:
 // TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/fail_incomplete.carbon
 
-// --- fail_incomplete_interface.carbon
-library "[[@TEST_NAME]]";
-
-interface X;
-class C {}
-
-// Requires X identified.
-impl C as X;
-
-// Requires X complete.
-// CHECK:STDERR: fail_incomplete_interface.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `X` [ImplAsIncompleteFacetTypeDefinition]
-// CHECK:STDERR: impl C as X {}
-// CHECK:STDERR: ^~~~~~~~~~~~~
-// CHECK:STDERR: fail_incomplete_interface.carbon:[[@LINE-10]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
-// CHECK:STDERR: interface X;
-// CHECK:STDERR: ^~~~~~~~~~~~
-// CHECK:STDERR:
-impl C as X {}
-
-// --- fail_incomplete_interface_without_forward_decl.carbon
-library "[[@TEST_NAME]]";
-
-interface X;
-class C {}
-
-// Requires X complete.
-// CHECK:STDERR: fail_incomplete_interface_without_forward_decl.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `X` [ImplAsIncompleteFacetTypeDefinition]
-// CHECK:STDERR: impl C as X {}
-// CHECK:STDERR: ^~~~~~~~~~~~~
-// CHECK:STDERR: fail_incomplete_interface_without_forward_decl.carbon:[[@LINE-7]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
-// CHECK:STDERR: interface X;
-// CHECK:STDERR: ^~~~~~~~~~~~
-// CHECK:STDERR:
-impl C as X {}
-
-// --- fail_unidentified_constraint.carbon
-library "[[@TEST_NAME]]";
-
-constraint X;
-class C {}
-
-// Requires X identified.
-// CHECK:STDERR: fail_unidentified_constraint.carbon:[[@LINE+7]]:1: error: facet type `X` cannot be identified in `impl as` [ImplOfUnidentifiedFacetType]
-// CHECK:STDERR: impl C as X;
-// CHECK:STDERR: ^~~~~~~~~~~~
-// CHECK:STDERR: fail_unidentified_constraint.carbon:[[@LINE-7]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
-// CHECK:STDERR: constraint X;
-// CHECK:STDERR: ^~~~~~~~~~~~~
-// CHECK:STDERR:
-impl C as X;
-
-// --- nested_require_incomplete_interface.carbon
-library "[[@TEST_NAME]]";
-
-interface Z;
-constraint Y {
-  require impls Z;
-}
-interface X {
-  require impls Y;
-}
-
-class C {}
-
-// Requires X identified.
-impl C as X;
-
-// Requires X complete.
-impl C as X {}
-
-// --- fail_incomplete_through_constraint.carbon
-library "[[@TEST_NAME]]";
-
-interface Z;
-constraint Y {
-  extend require impls Z;
-}
-
-class C {}
-
-// Requires Y identified.
-impl C as Y;
-
-// Requires Y complete.
-// CHECK:STDERR: fail_incomplete_through_constraint.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `Y` [ImplAsIncompleteFacetTypeDefinition]
-// CHECK:STDERR: impl C as Y {}
-// CHECK:STDERR: ^~~~~~~~~~~~~
-// CHECK:STDERR: fail_incomplete_through_constraint.carbon:[[@LINE-14]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
-// CHECK:STDERR: interface Z;
-// CHECK:STDERR: ^~~~~~~~~~~~
-// CHECK:STDERR:
-impl C as Y {}
-
 // --- fail_impl_lookup_incomplete.carbon
 library "[[@TEST_NAME]]";
 

+ 139 - 0
toolchain/check/testdata/generic/extend_type_completion.carbon

@@ -0,0 +1,139 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/extend_type_completion.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/extend_type_completion.carbon
+
+// --- class_impl_doesnt_need_complete_interface.carbon
+library "[[@TEST_NAME]]";
+
+interface K(T:! type) {}
+
+class C(N:! i32) {
+  impl as K(array(i32, N)) {}
+}
+
+// C does not extend K so the type of K is not completed. No error.
+var v: C(-1);
+
+// --- fail_class_extend_impl_does_need_complete_interface.carbon
+library "[[@TEST_NAME]]";
+
+interface K(T:! type) {}
+
+class C(N:! i32) {
+  // CHECK:STDERR: fail_class_extend_impl_does_need_complete_interface.carbon:[[@LINE+3]]:18: error: array bound of -1 is negative [ArrayBoundNegative]
+  // CHECK:STDERR:   extend impl as K(array(i32, N)) {}
+  // CHECK:STDERR:                  ^~~~~~~~~~~~~~~~
+  extend impl as K(array(i32, N)) {}
+}
+
+// C extends K so the type of K is completed, but is invalid.
+// CHECK:STDERR: fail_class_extend_impl_does_need_complete_interface.carbon:[[@LINE+4]]:8: note: in `C(-1)` used here [ResolvingSpecificHere]
+// CHECK:STDERR: var v: C(-1);
+// CHECK:STDERR:        ^~~~~
+// CHECK:STDERR:
+var v: C(-1);
+
+// --- interface_require_impls_doesnt_need_complete_interface.carbon
+library "[[@TEST_NAME]]";
+
+interface K(T:! type) {}
+interface J(N:! i32) {
+  require impls K(array(i32, N));
+}
+
+// J does not extend K so the type of K is not completed. No error.
+var v: J(-1);
+
+// --- fail_interface_extend_require_impls_does_need_complete_interface.carbon
+library "[[@TEST_NAME]]";
+
+interface K(T:! type) {}
+interface J(N:! i32) {
+  // CHECK:STDERR: fail_interface_extend_require_impls_does_need_complete_interface.carbon:[[@LINE+3]]:24: error: array bound of -1 is negative [ArrayBoundNegative]
+  // CHECK:STDERR:   extend require impls K(array(i32, N));
+  // CHECK:STDERR:                        ^~~~~~~~~~~~~~~~
+  extend require impls K(array(i32, N));
+}
+interface I(N:! i32) {
+  // CHECK:STDERR: fail_interface_extend_require_impls_does_need_complete_interface.carbon:[[@LINE+3]]:24: note: in `J(-1)` used here [ResolvingSpecificHere]
+  // CHECK:STDERR:   extend require impls J(N);
+  // CHECK:STDERR:                        ^~~~
+  extend require impls J(N);
+}
+
+// I extends J extends K so the type of K is completed, but is invalid.
+//
+// TODO: The error location should be the type, like in the class case above. We
+// need a location for the type in context.bind_name_map() to use as the
+// location to Convert().
+//
+// CHECK:STDERR: fail_interface_extend_require_impls_does_need_complete_interface.carbon:[[@LINE+4]]:1: note: in `I(-1)` used here [ResolvingSpecificHere]
+// CHECK:STDERR: var v: I(-1);
+// CHECK:STDERR: ^~~~~~~~~~~~
+// CHECK:STDERR:
+var v: I(-1);
+
+// --- constraint_require_impls_doesnt_need_complete_interface.carbon
+library "[[@TEST_NAME]]";
+
+interface K(T:! type) {}
+constraint J(N:! i32) {
+  require impls K(array(i32, N));
+}
+
+// J does not extend K so the type of K is not completed. No error.
+var v: J(-1);
+
+// --- fail_constraint_extend_require_impls_does_need_complete_interface.carbon
+library "[[@TEST_NAME]]";
+
+interface K(T:! type) {}
+constraint J(N:! i32) {
+  // CHECK:STDERR: fail_constraint_extend_require_impls_does_need_complete_interface.carbon:[[@LINE+3]]:24: error: array bound of -1 is negative [ArrayBoundNegative]
+  // CHECK:STDERR:   extend require impls K(array(i32, N));
+  // CHECK:STDERR:                        ^~~~~~~~~~~~~~~~
+  extend require impls K(array(i32, N));
+}
+constraint I(N:! i32) {
+  // CHECK:STDERR: fail_constraint_extend_require_impls_does_need_complete_interface.carbon:[[@LINE+3]]:24: note: in `{}` used here [ResolvingSpecificHere]
+  // CHECK:STDERR:   extend require impls J(N);
+  // CHECK:STDERR:                        ^~~~
+  extend require impls J(N);
+}
+
+// I extends J extends K so the type of K is completed, but is invalid.
+// CHECK:STDERR: fail_constraint_extend_require_impls_does_need_complete_interface.carbon:[[@LINE+4]]:1: note: in `{}` used here [ResolvingSpecificHere]
+// CHECK:STDERR: var v: I(-1);
+// CHECK:STDERR: ^~~~~~~~~~~~
+// CHECK:STDERR:
+var v: I(-1);
+
+// --- interface_require_impls_doesnt_need_complete_self.carbon
+library "[[@TEST_NAME]]";
+
+interface K {}
+interface J(N:! i32) {
+  require array(Self, N) impls K;
+}
+
+// J does not extend K so the type of Self impling K is not completed. No error.
+var v: J(-1);
+
+// --- constraint_require_impls_doesnt_need_complete_self.carbon
+library "[[@TEST_NAME]]";
+
+interface K {}
+constraint J(N:! i32) {
+  require array(Self, N) impls K;
+}
+
+// J does not extend K so the type of Self impling K is not completed. No error.
+var v: J(-1);

+ 0 - 290
toolchain/check/testdata/impl/fail_undefined_interface.carbon

@@ -1,290 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon
-// TODO: Add ranges and switch to "--dump-sem-ir-ranges=only".
-// EXTRA-ARGS: --dump-sem-ir-ranges=if-present
-//
-// AUTOUPDATE
-// TIP: To test this file alone, run:
-// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_undefined_interface.carbon
-// TIP: To dump output, run:
-// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_undefined_interface.carbon
-
-// --- fail_empty_struct.carbon
-
-library "[[@TEST_NAME]]";
-
-interface I;
-// CHECK:STDERR: fail_empty_struct.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `I` [ImplAsIncompleteFacetTypeDefinition]
-// CHECK:STDERR: impl {} as I {}
-// CHECK:STDERR: ^~~~~~~~~~~~~~
-// CHECK:STDERR: fail_empty_struct.carbon:[[@LINE-4]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
-// CHECK:STDERR: interface I;
-// CHECK:STDERR: ^~~~~~~~~~~~
-// CHECK:STDERR:
-impl {} as I {}
-
-// --- fail_class.carbon
-
-library "[[@TEST_NAME]]";
-
-interface J;
-class C {}
-// CHECK:STDERR: fail_class.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `J` [ImplAsIncompleteFacetTypeDefinition]
-// CHECK:STDERR: impl C as J {}
-// CHECK:STDERR: ^~~~~~~~~~~~~
-// CHECK:STDERR: fail_class.carbon:[[@LINE-5]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
-// CHECK:STDERR: interface J;
-// CHECK:STDERR: ^~~~~~~~~~~~
-// CHECK:STDERR:
-impl C as J {}
-
-// --- fail_incomplete_where.carbon
-library "[[@TEST_NAME]]";
-
-class C {}
-
-interface I {}
-interface Incomplete;
-
-// CHECK:STDERR: fail_incomplete_where.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `I where .Self impls Incomplete` [ImplAsIncompleteFacetTypeDefinition]
-// CHECK:STDERR: impl C as I where .Self impls Incomplete {}
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// CHECK:STDERR: fail_incomplete_where.carbon:[[@LINE-5]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
-// CHECK:STDERR: interface Incomplete;
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~
-// CHECK:STDERR:
-impl C as I where .Self impls Incomplete {}
-
-// --- fail_declaration_incomplete_where_rewrite.carbon
-library "[[@TEST_NAME]]";
-
-class C {}
-
-interface J { let T:! type; }
-interface Incomplete;
-
-// CHECK:STDERR: fail_declaration_incomplete_where_rewrite.carbon:[[@LINE+7]]:1: error: declaration of impl as incomplete facet type `J where .Self impls Incomplete and .(J.T) = ()` with rewrites [ImplAsIncompleteFacetTypeRewrites]
-// CHECK:STDERR: impl C as J where .Self impls Incomplete and .T = ();
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// CHECK:STDERR: fail_declaration_incomplete_where_rewrite.carbon:[[@LINE-5]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
-// CHECK:STDERR: interface Incomplete;
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~
-// CHECK:STDERR:
-impl C as J where .Self impls Incomplete and .T = ();
-
-// CHECK:STDOUT: --- fail_empty_struct.carbon
-// CHECK:STDOUT:
-// CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]
-// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: file {
-// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
-// CHECK:STDOUT:     .I = %I.decl
-// CHECK:STDOUT:   }
-// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}
-// CHECK:STDOUT:   impl_decl @empty_struct_type.as.I.impl [concrete] {} {
-// CHECK:STDOUT:     %.loc12_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
-// CHECK:STDOUT:     %.loc12_7.2: type = converted %.loc12_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
-// CHECK:STDOUT:   }
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: interface @I;
-// CHECK:STDOUT:
-// CHECK:STDOUT: impl @empty_struct_type.as.I.impl: %.loc12_7.2 as %I.ref {
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   witness = <error>
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: --- fail_class.carbon
-// CHECK:STDOUT:
-// CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %J.type: type = facet_type <@J> [concrete]
-// CHECK:STDOUT:   %C: type = class_type @C [concrete]
-// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: file {
-// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
-// CHECK:STDOUT:     .J = %J.decl
-// CHECK:STDOUT:     .C = %C.decl
-// CHECK:STDOUT:   }
-// CHECK:STDOUT:   %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}
-// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
-// CHECK:STDOUT:   impl_decl @C.as.J.impl [concrete] {} {
-// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
-// CHECK:STDOUT:     %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
-// CHECK:STDOUT:   }
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: interface @J;
-// CHECK:STDOUT:
-// CHECK:STDOUT: impl @C.as.J.impl: %C.ref as %J.ref {
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   witness = <error>
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
-// CHECK:STDOUT:   complete_type_witness = %complete_type
-// CHECK:STDOUT:
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Self = constants.%C
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: --- fail_incomplete_where.carbon
-// CHECK:STDOUT:
-// CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %C: type = class_type @C [concrete]
-// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
-// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]
-// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]
-// CHECK:STDOUT:   %Incomplete.type: type = facet_type <@Incomplete> [concrete]
-// CHECK:STDOUT:   %.Self: %I.type = symbolic_binding .Self [symbolic_self]
-// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]
-// CHECK:STDOUT:   %I_where.type: type = facet_type <@I where .Self impls @Incomplete> [concrete]
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: file {
-// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
-// CHECK:STDOUT:     .C = %C.decl
-// CHECK:STDOUT:     .I = %I.decl
-// CHECK:STDOUT:     .Incomplete = %Incomplete.decl
-// CHECK:STDOUT:   }
-// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
-// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}
-// CHECK:STDOUT:   %Incomplete.decl: type = interface_decl @Incomplete [concrete = constants.%Incomplete.type] {} {}
-// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {
-// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
-// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
-// CHECK:STDOUT:     %.Self: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]
-// CHECK:STDOUT:     %.Self.ref: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]
-// CHECK:STDOUT:     %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type]
-// CHECK:STDOUT:     %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.binding.as_type]
-// CHECK:STDOUT:     %.loc15_19: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.binding.as_type]
-// CHECK:STDOUT:     %.loc15_13: type = where_expr %.Self [concrete = constants.%I_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
-// CHECK:STDOUT:       requirement_impls %.loc15_19, %Incomplete.ref
-// CHECK:STDOUT:     }
-// CHECK:STDOUT:   }
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: interface @I {
-// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
-// CHECK:STDOUT:
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Self = %Self
-// CHECK:STDOUT:   witness = ()
-// CHECK:STDOUT:
-// CHECK:STDOUT: !requires:
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: interface @Incomplete;
-// CHECK:STDOUT:
-// CHECK:STDOUT: impl @C.as.I.impl: %C.ref as %.loc15_13 {
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   witness = <error>
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
-// CHECK:STDOUT:   complete_type_witness = %complete_type
-// CHECK:STDOUT:
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Self = constants.%C
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: --- fail_declaration_incomplete_where_rewrite.carbon
-// CHECK:STDOUT:
-// CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %C: type = class_type @C [concrete]
-// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
-// CHECK:STDOUT:   %J.type: type = facet_type <@J> [concrete]
-// CHECK:STDOUT:   %Self: %J.type = symbolic_binding Self, 0 [symbolic]
-// CHECK:STDOUT:   %J.assoc_type: type = assoc_entity_type @J [concrete]
-// CHECK:STDOUT:   %assoc0: %J.assoc_type = assoc_entity element0, @J.%T [concrete]
-// CHECK:STDOUT:   %Incomplete.type: type = facet_type <@Incomplete> [concrete]
-// CHECK:STDOUT:   %.Self: %J.type = symbolic_binding .Self [symbolic_self]
-// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]
-// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
-// CHECK:STDOUT:   %J.lookup_impl_witness: <witness> = lookup_impl_witness %.Self, @J [symbolic_self]
-// CHECK:STDOUT:   %impl.elem0: type = impl_witness_access %J.lookup_impl_witness, element0 [symbolic_self]
-// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
-// CHECK:STDOUT:   %J_where.type: type = facet_type <@J where .Self impls @Incomplete and %impl.elem0 = %empty_tuple.type> [concrete]
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: file {
-// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
-// CHECK:STDOUT:     .C = %C.decl
-// CHECK:STDOUT:     .J = %J.decl
-// CHECK:STDOUT:     .Incomplete = %Incomplete.decl
-// CHECK:STDOUT:   }
-// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
-// CHECK:STDOUT:   %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}
-// CHECK:STDOUT:   %Incomplete.decl: type = interface_decl @Incomplete [concrete = constants.%Incomplete.type] {} {}
-// CHECK:STDOUT:   impl_decl @C.as.J.impl [concrete] {} {
-// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
-// CHECK:STDOUT:     %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
-// CHECK:STDOUT:     %.Self: %J.type = symbolic_binding .Self [symbolic_self = constants.%.Self]
-// CHECK:STDOUT:     %.Self.ref.loc15_19: %J.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]
-// CHECK:STDOUT:     %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type]
-// CHECK:STDOUT:     %.Self.as_type.loc15_19: type = facet_access_type %.Self.ref.loc15_19 [symbolic_self = constants.%.Self.binding.as_type]
-// CHECK:STDOUT:     %.loc15_19: type = converted %.Self.ref.loc15_19, %.Self.as_type.loc15_19 [symbolic_self = constants.%.Self.binding.as_type]
-// CHECK:STDOUT:     %.Self.ref.loc15_46: %J.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]
-// CHECK:STDOUT:     %T.ref: %J.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]
-// CHECK:STDOUT:     %.Self.as_type.loc15_46: type = facet_access_type %.Self.ref.loc15_46 [symbolic_self = constants.%.Self.binding.as_type]
-// CHECK:STDOUT:     %.loc15_46: type = converted %.Self.ref.loc15_46, %.Self.as_type.loc15_46 [symbolic_self = constants.%.Self.binding.as_type]
-// CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%J.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
-// CHECK:STDOUT:     %.loc15_52.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
-// CHECK:STDOUT:     %.loc15_52.2: type = converted %.loc15_52.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
-// CHECK:STDOUT:     %.loc15_13: type = where_expr %.Self [concrete = constants.%J_where.type] {
-// CHECK:STDOUT:       requirement_base_facet_type constants.%J.type
-// CHECK:STDOUT:       requirement_impls %.loc15_19, %Incomplete.ref
-// CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc15_52.2
-// CHECK:STDOUT:     }
-// CHECK:STDOUT:   }
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: interface @J {
-// CHECK:STDOUT:   %Self: %J.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
-// CHECK:STDOUT:   %T: type = assoc_const_decl @T [concrete] {
-// CHECK:STDOUT:     %assoc0: %J.assoc_type = assoc_entity element0, @J.%T [concrete = constants.%assoc0]
-// CHECK:STDOUT:   }
-// CHECK:STDOUT:
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Self = %Self
-// CHECK:STDOUT:   .T = @T.%assoc0
-// CHECK:STDOUT:   witness = (%T)
-// CHECK:STDOUT:
-// CHECK:STDOUT: !requires:
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: interface @Incomplete;
-// CHECK:STDOUT:
-// CHECK:STDOUT: generic assoc_const @T(@J.%Self: %J.type) {
-// CHECK:STDOUT:   assoc_const T:! type;
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: impl @C.as.J.impl: %C.ref as %.loc15_13;
-// CHECK:STDOUT:
-// CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
-// CHECK:STDOUT:   complete_type_witness = %complete_type
-// CHECK:STDOUT:
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Self = constants.%C
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: specific @T(constants.%Self) {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: specific @T(constants.%.Self) {}
-// CHECK:STDOUT:

+ 3 - 9
toolchain/check/testdata/impl/impl_as_named_constraint.carbon

@@ -24,8 +24,8 @@ impl () as A {}
 // --- fail_too_many_interfaces_in_constraint.carbon
 library "[[@TEST_NAME]]";
 
-interface A1;
-interface A2;
+interface A1 {}
+interface A2 {}
 constraint B {
   extend require impls A1;
   extend require impls A2;
@@ -40,17 +40,11 @@ impl () as B {}
 // --- one_extend_impls_interface_in_constraint.carbon
 library "[[@TEST_NAME]]";
 
-interface A;
+interface A {}
 constraint B {
   extend require impls A;
 }
 
-// Requries B identified.
-impl () as B;
-
-interface A {}
-
-// Requries B complete.
 impl () as B {}
 
 // --- fail_one_impls_interface_in_constraint.carbon

+ 599 - 14
toolchain/check/testdata/impl/import_generic.carbon

@@ -12,6 +12,32 @@
 // TIP: To dump output, run:
 // TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/import_generic.carbon
 
+// --- basic_import_generic_interface.carbon
+library "[[@TEST_NAME]]";
+
+interface I(T:! type) {}
+interface J(T:! type) {
+  extend require impls I(T);
+}
+
+// --- basic_import_generic_interface.impl.carbon
+impl library "[[@TEST_NAME]]";
+
+impl {} as J({}) {}
+
+// --- basic_import_generic_constraint.carbon
+library "[[@TEST_NAME]]";
+
+interface I(T:! type) {}
+constraint J(T:! type) {
+  extend require impls I(T);
+}
+
+// --- basic_import_generic_constraint.impl.carbon
+impl library "[[@TEST_NAME]]";
+
+impl {} as J({}) {}
+
 // --- import_generic.carbon
 
 library "[[@TEST_NAME]]";
@@ -157,6 +183,520 @@ impl forall [T:! type] D as N(T) {}
 // CHECK:STDERR:
 impl forall [T:! type] D as N(T*) {}
 
+// CHECK:STDOUT: --- basic_import_generic_interface.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]
+// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]
+// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]
+// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]
+// CHECK:STDOUT:   %I.type.dac: type = generic_interface_type @I [concrete]
+// CHECK:STDOUT:   %I.generic: %I.type.dac = struct_value () [concrete]
+// CHECK:STDOUT:   %I.type.070: type = facet_type <@I, @I(%T)> [symbolic]
+// CHECK:STDOUT:   %Self.269: %I.type.070 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %J.type.2b8: type = generic_interface_type @J [concrete]
+// CHECK:STDOUT:   %J.generic: %J.type.2b8 = struct_value () [concrete]
+// CHECK:STDOUT:   %J.type.8ec: type = facet_type <@J, @J(%T)> [symbolic]
+// CHECK:STDOUT:   %Self.f68: %J.type.8ec = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.f68 [symbolic]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type.070 [symbolic]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .I = %I.decl
+// CHECK:STDOUT:     .J = %J.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %I.decl: %I.type.dac = interface_decl @I [concrete = constants.%I.generic] {
+// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %T.loc3_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc3_13.1 (constants.%T)]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %J.decl: %J.type.2b8 = interface_decl @J [concrete = constants.%J.generic] {
+// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %T.loc4_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic interface @I(%T.loc3_13.2: type) {
+// CHECK:STDOUT:   %T.loc3_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc3_13.1 (constants.%T)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T.loc3_13.1)> [symbolic = %I.type (constants.%I.type.070)]
+// CHECK:STDOUT:   %Self.loc3_23.2: @I.%I.type (%I.type.070) = symbolic_binding Self, 1 [symbolic = %Self.loc3_23.2 (constants.%Self.269)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   interface {
+// CHECK:STDOUT:     %Self.loc3_23.1: @I.%I.type (%I.type.070) = symbolic_binding Self, 1 [symbolic = %Self.loc3_23.2 (constants.%Self.269)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = %Self.loc3_23.1
+// CHECK:STDOUT:     witness = ()
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !requires:
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic interface @J(%T.loc4_13.2: type) {
+// CHECK:STDOUT:   %T.loc4_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T.loc4_13.1)> [symbolic = %J.type (constants.%J.type.8ec)]
+// CHECK:STDOUT:   %Self.loc4_23.2: @J.%J.type (%J.type.8ec) = symbolic_binding Self, 1 [symbolic = %Self.loc4_23.2 (constants.%Self.f68)]
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T.loc4_13.1)> [symbolic = %I.type (constants.%I.type.070)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type [symbolic = %require_complete (constants.%require_complete)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   interface {
+// CHECK:STDOUT:     %Self.loc4_23.1: @J.%J.type (%J.type.8ec) = symbolic_binding Self, 1 [symbolic = %Self.loc4_23.2 (constants.%Self.f68)]
+// CHECK:STDOUT:     %J.require0.decl = require_decl @J.require0 [concrete] {
+// CHECK:STDOUT:       require %Self.as_type impls <@I, @I(constants.%T)>
+// CHECK:STDOUT:     } {
+// CHECK:STDOUT:       %Self.as_type: type = facet_access_type @J.%Self.loc4_23.1 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
+// 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, @J.%T.loc4_13.2 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:       %I.type.loc5_27.1: type = facet_type <@I, @I(constants.%T)> [symbolic = %I.type.loc5_27.2 (constants.%I.type.070)]
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = %Self.loc4_23.1
+// CHECK:STDOUT:     .I = <poisoned>
+// CHECK:STDOUT:     .T = <poisoned>
+// CHECK:STDOUT:     witness = ()
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !requires:
+// CHECK:STDOUT:     @J.require0 {
+// CHECK:STDOUT:       require @J.require0.%Self.as_type impls <@I, @I(constants.%T)>
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic require @J.require0(@J.%T.loc4_13.2: type, @J.%Self.loc4_23.1: @J.%J.type (%J.type.8ec)) {
+// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.8ec)]
+// CHECK:STDOUT:   %Self: @J.require0.%J.type (%J.type.8ec) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.f68)]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
+// CHECK:STDOUT:   %I.type.loc5_27.2: type = facet_type <@I, @I(%T)> [symbolic = %I.type.loc5_27.2 (constants.%I.type.070)]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(constants.%T) {
+// CHECK:STDOUT:   %T.loc3_13.1 => constants.%T
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type => constants.%I.type.070
+// CHECK:STDOUT:   %Self.loc3_23.2 => constants.%Self.269
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @J(constants.%T) {
+// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @J.require0(constants.%T, constants.%Self.f68) {
+// CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT:   %J.type => constants.%J.type.8ec
+// CHECK:STDOUT:   %Self => constants.%Self.f68
+// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type
+// CHECK:STDOUT:   %I.type.loc5_27.2 => constants.%I.type.070
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- basic_import_generic_interface.impl.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]
+// CHECK:STDOUT:   %J.type.2b8: type = generic_interface_type @J [concrete]
+// CHECK:STDOUT:   %J.generic: %J.type.2b8 = struct_value () [concrete]
+// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]
+// CHECK:STDOUT:   %J.type.8ec: type = facet_type <@J, @J(%T)> [symbolic]
+// CHECK:STDOUT:   %Self.f68: %J.type.8ec = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %I.type.070: type = facet_type <@I, @I(%T)> [symbolic]
+// CHECK:STDOUT:   %Self.269: %I.type.070 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.f68 [symbolic]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type.070 [symbolic]
+// CHECK:STDOUT:   %J.type.457: type = facet_type <@J, @J(%empty_struct_type)> [concrete]
+// CHECK:STDOUT:   %Self.07b: %J.type.457 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %I.type.399: type = facet_type <@I, @I(%empty_struct_type)> [concrete]
+// CHECK:STDOUT:   %Self.32d: %I.type.399 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %I.type.399 [concrete]
+// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness file.%J.impl_witness_table [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Main.I = import_ref Main//basic_import_generic_interface, I, unloaded
+// CHECK:STDOUT:   %Main.J: %J.type.2b8 = import_ref Main//basic_import_generic_interface, J, loaded [concrete = constants.%J.generic]
+// CHECK:STDOUT:   %Main.import_ref.769 = import_ref Main//basic_import_generic_interface, loc3_23, unloaded
+// CHECK:STDOUT:   %Main.import_ref.efcd44.1: type = import_ref Main//basic_import_generic_interface, loc3_13, loaded [symbolic = @I.%T (constants.%T)]
+// CHECK:STDOUT:   %Main.import_ref.ce5: type = import_ref Main//basic_import_generic_interface, loc5_18, loaded [symbolic = constants.%Self.binding.as_type]
+// CHECK:STDOUT:   %Main.import_ref.efcd44.2: type = import_ref Main//basic_import_generic_interface, loc4_13, loaded [symbolic = @J.%T (constants.%T)]
+// CHECK:STDOUT:   %Main.import_ref.cc4: @J.%J.type (%J.type.8ec) = import_ref Main//basic_import_generic_interface, loc4_23, loaded [symbolic = @J.%Self (constants.%Self.f68)]
+// CHECK:STDOUT:   %Main.import_ref.b3b = import_ref Main//basic_import_generic_interface, loc4_23, unloaded
+// CHECK:STDOUT:   %Main.import_ref.efcd44.3: type = import_ref Main//basic_import_generic_interface, loc4_13, loaded [symbolic = @J.%T (constants.%T)]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .I = imports.%Main.I
+// CHECK:STDOUT:     .J = imports.%Main.J
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %default.import.loc1_46.1 = import <none>
+// CHECK:STDOUT:   %default.import.loc1_46.2 = import <none>
+// CHECK:STDOUT:   impl_decl @empty_struct_type.as.J.impl [concrete] {} {
+// CHECK:STDOUT:     %.loc3_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
+// CHECK:STDOUT:     %.loc3_7.2: type = converted %.loc3_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
+// CHECK:STDOUT:     %J.ref: %J.type.2b8 = name_ref J, imports.%Main.J [concrete = constants.%J.generic]
+// CHECK:STDOUT:     %.loc3_15: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
+// CHECK:STDOUT:     %.loc3_16: type = converted %.loc3_15, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
+// CHECK:STDOUT:     %J.type: type = facet_type <@J, @J(constants.%empty_struct_type)> [concrete = constants.%J.type.457]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %J.impl_witness_table = impl_witness_table (), @empty_struct_type.as.J.impl [concrete]
+// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic interface @J(imports.%Main.import_ref.efcd44.3: type) [from "basic_import_generic_interface.carbon"] {
+// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.8ec)]
+// CHECK:STDOUT:   %Self: @J.%J.type (%J.type.8ec) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.f68)]
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.070)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type [symbolic = %require_complete (constants.%require_complete)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   interface {
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = imports.%Main.import_ref.b3b
+// CHECK:STDOUT:     witness = ()
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !requires:
+// CHECK:STDOUT:     @J.require0 {
+// CHECK:STDOUT:       require imports.%Main.import_ref.ce5 impls <@I, @I(constants.%T)>
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic interface @I(imports.%Main.import_ref.efcd44.1: type) [from "basic_import_generic_interface.carbon"] {
+// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.070)]
+// CHECK:STDOUT:   %Self: @I.%I.type (%I.type.070) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.269)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   interface {
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = imports.%Main.import_ref.769
+// CHECK:STDOUT:     witness = ()
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !requires:
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic require @J.require0(imports.%Main.import_ref.efcd44.2: type, imports.%Main.import_ref.cc4: @J.%J.type (%J.type.8ec)) [from "basic_import_generic_interface.carbon"] {
+// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.8ec)]
+// CHECK:STDOUT:   %Self: @J.require0.%J.type (%J.type.8ec) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.f68)]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.070)]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @empty_struct_type.as.J.impl: %.loc3_7.2 as %J.type {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   witness = file.%J.impl_witness
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @J(constants.%T) {
+// CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(constants.%T) {
+// CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type => constants.%I.type.070
+// CHECK:STDOUT:   %Self => constants.%Self.269
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @J.require0(constants.%T, constants.%Self.f68) {
+// CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT:   %J.type => constants.%J.type.8ec
+// CHECK:STDOUT:   %Self => constants.%Self.f68
+// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type
+// CHECK:STDOUT:   %I.type => constants.%I.type.070
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @J(constants.%empty_struct_type) {
+// CHECK:STDOUT:   %T => constants.%empty_struct_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %J.type => constants.%J.type.457
+// CHECK:STDOUT:   %Self => constants.%Self.07b
+// CHECK:STDOUT:   %I.type => constants.%I.type.399
+// CHECK:STDOUT:   %require_complete => constants.%complete_type
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(constants.%empty_struct_type) {
+// CHECK:STDOUT:   %T => constants.%empty_struct_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type => constants.%I.type.399
+// CHECK:STDOUT:   %Self => constants.%Self.32d
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- basic_import_generic_constraint.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]
+// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]
+// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]
+// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]
+// CHECK:STDOUT:   %I.type.dac: type = generic_interface_type @I [concrete]
+// CHECK:STDOUT:   %I.generic: %I.type.dac = struct_value () [concrete]
+// CHECK:STDOUT:   %I.type.070: type = facet_type <@I, @I(%T)> [symbolic]
+// CHECK:STDOUT:   %Self.269: %I.type.070 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %J.type.267: type = generic_named_constaint_type @J [concrete]
+// CHECK:STDOUT:   %empty_struct: %J.type.267 = struct_value () [concrete]
+// CHECK:STDOUT:   %J.type.b8d: type = facet_type <@J, @J(%T)> [symbolic]
+// CHECK:STDOUT:   %Self.aa1: %J.type.b8d = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.aa1 [symbolic]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type.070 [symbolic]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .I = %I.decl
+// CHECK:STDOUT:     .J = %J.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %I.decl: %I.type.dac = interface_decl @I [concrete = constants.%I.generic] {
+// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %T.loc3_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc3_13.1 (constants.%T)]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %J.decl: %J.type.267 = constraint_decl @J [concrete = constants.%empty_struct] {
+// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %T.loc4_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_14.1 (constants.%T)]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic interface @I(%T.loc3_13.2: type) {
+// CHECK:STDOUT:   %T.loc3_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc3_13.1 (constants.%T)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T.loc3_13.1)> [symbolic = %I.type (constants.%I.type.070)]
+// CHECK:STDOUT:   %Self.loc3_23.2: @I.%I.type (%I.type.070) = symbolic_binding Self, 1 [symbolic = %Self.loc3_23.2 (constants.%Self.269)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   interface {
+// CHECK:STDOUT:     %Self.loc3_23.1: @I.%I.type (%I.type.070) = symbolic_binding Self, 1 [symbolic = %Self.loc3_23.2 (constants.%Self.269)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = %Self.loc3_23.1
+// CHECK:STDOUT:     witness = ()
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !requires:
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic constraint @J(%T.loc4_14.2: type) {
+// CHECK:STDOUT:   %T.loc4_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_14.1 (constants.%T)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T.loc4_14.1)> [symbolic = %J.type (constants.%J.type.b8d)]
+// CHECK:STDOUT:   %Self.loc4_24.2: @J.%J.type (%J.type.b8d) = symbolic_binding Self, 1 [symbolic = %Self.loc4_24.2 (constants.%Self.aa1)]
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T.loc4_14.1)> [symbolic = %I.type (constants.%I.type.070)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type [symbolic = %require_complete (constants.%require_complete)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   constraint {
+// CHECK:STDOUT:     %Self.loc4_24.1: @J.%J.type (%J.type.b8d) = symbolic_binding Self, 1 [symbolic = %Self.loc4_24.2 (constants.%Self.aa1)]
+// CHECK:STDOUT:     %J.require0.decl = require_decl @J.require0 [concrete] {
+// CHECK:STDOUT:       require %Self.as_type impls <@I, @I(constants.%T)>
+// CHECK:STDOUT:     } {
+// CHECK:STDOUT:       %Self.as_type: type = facet_access_type @J.%Self.loc4_24.1 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
+// 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, @J.%T.loc4_14.2 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:       %I.type.loc5_27.1: type = facet_type <@I, @I(constants.%T)> [symbolic = %I.type.loc5_27.2 (constants.%I.type.070)]
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = %Self.loc4_24.1
+// CHECK:STDOUT:     .I = <poisoned>
+// CHECK:STDOUT:     .T = <poisoned>
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !requires:
+// CHECK:STDOUT:     @J.require0 {
+// CHECK:STDOUT:       require @J.require0.%Self.as_type impls <@I, @I(constants.%T)>
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic require @J.require0(@J.%T.loc4_14.2: type, @J.%Self.loc4_24.1: @J.%J.type (%J.type.b8d)) {
+// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.b8d)]
+// CHECK:STDOUT:   %Self: @J.require0.%J.type (%J.type.b8d) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.aa1)]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
+// CHECK:STDOUT:   %I.type.loc5_27.2: type = facet_type <@I, @I(%T)> [symbolic = %I.type.loc5_27.2 (constants.%I.type.070)]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(constants.%T) {
+// CHECK:STDOUT:   %T.loc3_13.1 => constants.%T
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type => constants.%I.type.070
+// CHECK:STDOUT:   %Self.loc3_23.2 => constants.%Self.269
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @J(constants.%T) {
+// CHECK:STDOUT:   %T.loc4_14.1 => constants.%T
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @J.require0(constants.%T, constants.%Self.aa1) {
+// CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT:   %J.type => constants.%J.type.b8d
+// CHECK:STDOUT:   %Self => constants.%Self.aa1
+// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type
+// CHECK:STDOUT:   %I.type.loc5_27.2 => constants.%I.type.070
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- basic_import_generic_constraint.impl.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %empty_struct.a40: %empty_struct_type = struct_value () [concrete]
+// CHECK:STDOUT:   %J.type.267: type = generic_named_constaint_type @J [concrete]
+// CHECK:STDOUT:   %empty_struct.b6f: %J.type.267 = struct_value () [concrete]
+// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]
+// CHECK:STDOUT:   %J.type.b8d23b.1: type = facet_type <@J, @J(%T)> [symbolic]
+// CHECK:STDOUT:   %Self.aa1546.1: %J.type.b8d23b.1 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %I.type.070: type = facet_type <@I, @I(%T)> [symbolic]
+// CHECK:STDOUT:   %Self.269: %I.type.070 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.aa1546.1 [symbolic]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type.070 [symbolic]
+// CHECK:STDOUT:   %J.type.b8d23b.2: type = facet_type <@J, @J(%empty_struct_type)> [concrete]
+// CHECK:STDOUT:   %Self.aa1546.2: %J.type.b8d23b.2 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %I.type.399: type = facet_type <@I, @I(%empty_struct_type)> [concrete]
+// CHECK:STDOUT:   %Self.32d: %I.type.399 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %I.type.399 [concrete]
+// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness file.%I.impl_witness_table [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Main.I = import_ref Main//basic_import_generic_constraint, I, unloaded
+// CHECK:STDOUT:   %Main.J: %J.type.267 = import_ref Main//basic_import_generic_constraint, J, loaded [concrete = constants.%empty_struct.b6f]
+// CHECK:STDOUT:   %Main.import_ref.769 = import_ref Main//basic_import_generic_constraint, loc3_23, unloaded
+// CHECK:STDOUT:   %Main.import_ref.efcd44.1: type = import_ref Main//basic_import_generic_constraint, loc3_13, loaded [symbolic = @I.%T (constants.%T)]
+// CHECK:STDOUT:   %Main.import_ref.f92: type = import_ref Main//basic_import_generic_constraint, loc5_18, loaded [symbolic = constants.%Self.binding.as_type]
+// CHECK:STDOUT:   %Main.import_ref.efcd44.2: type = import_ref Main//basic_import_generic_constraint, loc4_14, loaded [symbolic = @J.%T (constants.%T)]
+// CHECK:STDOUT:   %Main.import_ref.d4d: @J.%J.type (%J.type.b8d23b.1) = import_ref Main//basic_import_generic_constraint, loc4_24, loaded [symbolic = @J.%Self (constants.%Self.aa1546.1)]
+// CHECK:STDOUT:   %Main.import_ref.388 = import_ref Main//basic_import_generic_constraint, loc4_24, unloaded
+// CHECK:STDOUT:   %Main.import_ref.efcd44.3: type = import_ref Main//basic_import_generic_constraint, loc4_14, loaded [symbolic = @J.%T (constants.%T)]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .I = imports.%Main.I
+// CHECK:STDOUT:     .J = imports.%Main.J
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %default.import.loc1_47.1 = import <none>
+// CHECK:STDOUT:   %default.import.loc1_47.2 = import <none>
+// CHECK:STDOUT:   impl_decl @empty_struct_type.as.I.impl [concrete] {} {
+// CHECK:STDOUT:     %.loc3_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct.a40]
+// CHECK:STDOUT:     %.loc3_7.2: type = converted %.loc3_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
+// CHECK:STDOUT:     %J.ref: %J.type.267 = name_ref J, imports.%Main.J [concrete = constants.%empty_struct.b6f]
+// CHECK:STDOUT:     %.loc3_15: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct.a40]
+// CHECK:STDOUT:     %.loc3_16: type = converted %.loc3_15, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
+// CHECK:STDOUT:     %J.type: type = facet_type <@J, @J(constants.%empty_struct_type)> [concrete = constants.%J.type.b8d23b.2]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @empty_struct_type.as.I.impl [concrete]
+// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic interface @I(imports.%Main.import_ref.efcd44.1: type) [from "basic_import_generic_constraint.carbon"] {
+// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.070)]
+// CHECK:STDOUT:   %Self: @I.%I.type (%I.type.070) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.269)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   interface {
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = imports.%Main.import_ref.769
+// CHECK:STDOUT:     witness = ()
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !requires:
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic constraint @J(imports.%Main.import_ref.efcd44.3: type) [from "basic_import_generic_constraint.carbon"] {
+// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.b8d23b.1)]
+// CHECK:STDOUT:   %Self: @J.%J.type (%J.type.b8d23b.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.aa1546.1)]
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.070)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type [symbolic = %require_complete (constants.%require_complete)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   constraint {
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = imports.%Main.import_ref.388
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !requires:
+// CHECK:STDOUT:     @J.require0 {
+// CHECK:STDOUT:       require imports.%Main.import_ref.f92 impls <@I, @I(constants.%T)>
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic require @J.require0(imports.%Main.import_ref.efcd44.2: type, imports.%Main.import_ref.d4d: @J.%J.type (%J.type.b8d23b.1)) [from "basic_import_generic_constraint.carbon"] {
+// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.b8d23b.1)]
+// CHECK:STDOUT:   %Self: @J.require0.%J.type (%J.type.b8d23b.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.aa1546.1)]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.070)]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @empty_struct_type.as.I.impl: %.loc3_7.2 as %J.type {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   witness = file.%I.impl_witness
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @J(constants.%T) {
+// CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(constants.%T) {
+// CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type => constants.%I.type.070
+// CHECK:STDOUT:   %Self => constants.%Self.269
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @J.require0(constants.%T, constants.%Self.aa1546.1) {
+// CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT:   %J.type => constants.%J.type.b8d23b.1
+// CHECK:STDOUT:   %Self => constants.%Self.aa1546.1
+// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type
+// CHECK:STDOUT:   %I.type => constants.%I.type.070
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @J(constants.%empty_struct_type) {
+// CHECK:STDOUT:   %T => constants.%empty_struct_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %J.type => constants.%J.type.b8d23b.2
+// CHECK:STDOUT:   %Self => constants.%Self.aa1546.2
+// CHECK:STDOUT:   %I.type => constants.%I.type.399
+// CHECK:STDOUT:   %require_complete => constants.%complete_type
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(constants.%empty_struct_type) {
+// CHECK:STDOUT:   %T => constants.%empty_struct_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %I.type => constants.%I.type.399
+// CHECK:STDOUT:   %Self => constants.%Self.32d
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
 // CHECK:STDOUT: --- import_generic.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
@@ -265,6 +805,8 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T.loc14_14.1)> [symbolic = %N.type (constants.%N.type.b8d)]
 // CHECK:STDOUT:   %Self.loc14_24.2: @N.%N.type (%N.type.b8d) = symbolic_binding Self, 1 [symbolic = %Self.loc14_24.2 (constants.%Self.aa1)]
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T.loc14_14.1)> [symbolic = %I.type (constants.%I.type.070)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type [symbolic = %require_complete (constants.%require_complete.c94)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   constraint {
 // CHECK:STDOUT:     %Self.loc14_24.1: @N.%N.type (%N.type.b8d) = symbolic_binding Self, 1 [symbolic = %Self.loc14_24.2 (constants.%Self.aa1)]
@@ -531,6 +1073,8 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.b8d23b.1)]
 // CHECK:STDOUT:   %Self: @N.%N.type (%N.type.b8d23b.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.aa1)]
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.070)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type [symbolic = %require_complete (constants.%require_complete.c94)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   constraint {
 // CHECK:STDOUT:   !members:
@@ -805,6 +1349,8 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T.loc9_14.1)> [symbolic = %N.type (constants.%N.type.b8d)]
 // CHECK:STDOUT:   %Self.loc9_24.2: @N.%N.type (%N.type.b8d) = symbolic_binding Self, 1 [symbolic = %Self.loc9_24.2 (constants.%Self.aa1)]
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T.loc9_14.1)> [symbolic = %I.type (constants.%I.type.070)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type [symbolic = %require_complete (constants.%require_complete)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   constraint {
 // CHECK:STDOUT:     %Self.loc9_24.1: @N.%N.type (%N.type.b8d) = symbolic_binding Self, 1 [symbolic = %Self.loc9_24.2 (constants.%Self.aa1)]
@@ -910,10 +1456,13 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %N.type.673: type = generic_named_constaint_type @N [concrete]
 // CHECK:STDOUT:   %empty_struct: %N.type.673 = struct_value () [concrete]
 // CHECK:STDOUT:   %N.type.b8d23b.1: type = facet_type <@N, @N(%T)> [symbolic]
-// CHECK:STDOUT:   %Self.aa1: %N.type.b8d23b.1 = symbolic_binding Self, 1 [symbolic]
-// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.aa1 [symbolic]
+// CHECK:STDOUT:   %Self.aa1546.1: %N.type.b8d23b.1 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.aa1546.1 [symbolic]
 // CHECK:STDOUT:   %ptr.3f2: type = ptr_type %ptr.4f0 [symbolic]
 // CHECK:STDOUT:   %N.type.b8d23b.2: type = facet_type <@N, @N(%ptr.3f2)> [symbolic]
+// CHECK:STDOUT:   %Self.aa1546.2: %N.type.b8d23b.2 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %I.type.71a: type = facet_type <@I, @I(%ptr.3f2)> [symbolic]
+// CHECK:STDOUT:   %require_complete.08c: <witness> = require_complete_type %I.type.71a [symbolic]
 // CHECK:STDOUT:   %require_complete.a37: <witness> = require_complete_type %N.type.b8d23b.2 [symbolic]
 // CHECK:STDOUT:   %I.impl_witness.524: <witness> = impl_witness file.%I.impl_witness_table.loc6, @C.as.I.impl.3f8(%T) [symbolic]
 // CHECK:STDOUT: }
@@ -933,7 +1482,7 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %Main.import_ref.efcd44.2: type = import_ref Main//import_generic_with_different_specific, loc7_14, loaded [symbolic = @C.as.I.impl.f3e.%T (constants.%T)]
 // CHECK:STDOUT:   %Main.import_ref.f92: type = import_ref Main//import_generic_with_different_specific, loc10_18, loaded [symbolic = constants.%Self.binding.as_type]
 // CHECK:STDOUT:   %Main.import_ref.efcd44.3: type = import_ref Main//import_generic_with_different_specific, loc9_14, loaded [symbolic = @N.%T (constants.%T)]
-// CHECK:STDOUT:   %Main.import_ref.d4d: @N.%N.type (%N.type.b8d23b.1) = import_ref Main//import_generic_with_different_specific, loc9_24, loaded [symbolic = @N.%Self (constants.%Self.aa1)]
+// CHECK:STDOUT:   %Main.import_ref.d4d: @N.%N.type (%N.type.b8d23b.1) = import_ref Main//import_generic_with_different_specific, loc9_24, loaded [symbolic = @N.%Self (constants.%Self.aa1546.1)]
 // CHECK:STDOUT:   %Main.import_ref.388 = import_ref Main//import_generic_with_different_specific, loc9_24, unloaded
 // CHECK:STDOUT:   %Main.import_ref.efcd44.4: type = import_ref Main//import_generic_with_different_specific, loc9_14, loaded [symbolic = @N.%T (constants.%T)]
 // CHECK:STDOUT: }
@@ -996,7 +1545,9 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.b8d23b.1)]
-// CHECK:STDOUT:   %Self: @N.%N.type (%N.type.b8d23b.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.aa1)]
+// CHECK:STDOUT:   %Self: @N.%N.type (%N.type.b8d23b.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.aa1546.1)]
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.070)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type [symbolic = %require_complete (constants.%require_complete.c94)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   constraint {
 // CHECK:STDOUT:   !members:
@@ -1012,7 +1563,7 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT: generic require @N.require0(imports.%Main.import_ref.efcd44.3: type, imports.%Main.import_ref.d4d: @N.%N.type (%N.type.b8d23b.1)) [from "import_generic_with_different_specific.carbon"] {
 // CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]
 // CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.b8d23b.1)]
-// CHECK:STDOUT:   %Self: @N.require0.%N.type (%N.type.b8d23b.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.aa1)]
+// CHECK:STDOUT:   %Self: @N.require0.%N.type (%N.type.b8d23b.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.aa1546.1)]
 // CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
 // CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.070)]
 // CHECK:STDOUT: }
@@ -1104,16 +1655,22 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %T => constants.%T
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @N.require0(constants.%T, constants.%Self.aa1) {
+// CHECK:STDOUT: specific @N.require0(constants.%T, constants.%Self.aa1546.1) {
 // CHECK:STDOUT:   %T => constants.%T
 // CHECK:STDOUT:   %N.type => constants.%N.type.b8d23b.1
-// CHECK:STDOUT:   %Self => constants.%Self.aa1
+// CHECK:STDOUT:   %Self => constants.%Self.aa1546.1
 // CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type
 // CHECK:STDOUT:   %I.type => constants.%I.type.070
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @N(constants.%ptr.3f2) {
 // CHECK:STDOUT:   %T => constants.%ptr.3f2
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %N.type => constants.%N.type.b8d23b.2
+// CHECK:STDOUT:   %Self => constants.%Self.aa1546.2
+// CHECK:STDOUT:   %I.type => constants.%I.type.71a
+// CHECK:STDOUT:   %require_complete => constants.%require_complete.08c
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @C.as.I.impl.3f8(constants.%T) {
@@ -1125,6 +1682,10 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %I.impl_witness => constants.%I.impl_witness.524
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: specific @I(constants.%ptr.3f2) {
+// CHECK:STDOUT:   %T => constants.%ptr.3f2
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_import_generic_decl.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
@@ -1144,6 +1705,7 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %N.type.b8d: type = facet_type <@N, @N(%T)> [symbolic]
 // CHECK:STDOUT:   %Self.aa1: %N.type.b8d = symbolic_binding Self, 1 [symbolic]
 // CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.aa1 [symbolic]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %J.type.8ec [symbolic]
 // CHECK:STDOUT:   %J.impl_witness.224: <witness> = impl_witness file.%J.impl_witness_table.loc15, @D.as.J.impl.b47(%T) [symbolic]
 // CHECK:STDOUT:   %ptr: type = ptr_type %T [symbolic]
 // CHECK:STDOUT:   %J.type.4fa: type = facet_type <@J, @J(%ptr)> [symbolic]
@@ -1220,6 +1782,8 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T.loc7_14.1)> [symbolic = %N.type (constants.%N.type.b8d)]
 // CHECK:STDOUT:   %Self.loc7_24.2: @N.%N.type (%N.type.b8d) = symbolic_binding Self, 1 [symbolic = %Self.loc7_24.2 (constants.%Self.aa1)]
+// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T.loc7_14.1)> [symbolic = %J.type (constants.%J.type.8ec)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %J.type [symbolic = %require_complete (constants.%require_complete)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   constraint {
 // CHECK:STDOUT:     %Self.loc7_24.1: @N.%N.type (%N.type.b8d) = symbolic_binding Self, 1 [symbolic = %Self.loc7_24.2 (constants.%Self.aa1)]
@@ -1279,6 +1843,10 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @J(constants.%T) {
 // CHECK:STDOUT:   %T.loc5_13.1 => constants.%T
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %J.type => constants.%J.type.8ec
+// CHECK:STDOUT:   %Self.loc5_23.2 => constants.%Self.f68
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @N(constants.%T) {
@@ -1331,11 +1899,14 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %N.type.673: type = generic_named_constaint_type @N [concrete]
 // CHECK:STDOUT:   %empty_struct: %N.type.673 = struct_value () [concrete]
 // CHECK:STDOUT:   %N.type.b8d23b.1: type = facet_type <@N, @N(%T)> [symbolic]
-// CHECK:STDOUT:   %Self.aa1: %N.type.b8d23b.1 = symbolic_binding Self, 1 [symbolic]
-// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.aa1 [symbolic]
+// CHECK:STDOUT:   %Self.aa1546.1: %N.type.b8d23b.1 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.aa1546.1 [symbolic]
+// CHECK:STDOUT:   %require_complete.387: <witness> = require_complete_type %J.type.8ec [symbolic]
 // CHECK:STDOUT:   %require_complete.a37d6c.1: <witness> = require_complete_type %N.type.b8d23b.1 [symbolic]
 // CHECK:STDOUT:   %J.impl_witness.b5245e.1: <witness> = impl_witness file.%J.impl_witness_table.loc29, @D.as.J.impl.3b0484.1(%T) [symbolic]
 // CHECK:STDOUT:   %N.type.b8d23b.2: type = facet_type <@N, @N(%ptr)> [symbolic]
+// CHECK:STDOUT:   %Self.aa1546.2: %N.type.b8d23b.2 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %require_complete.d4d: <witness> = require_complete_type %J.type.4fa [symbolic]
 // CHECK:STDOUT:   %require_complete.a37d6c.2: <witness> = require_complete_type %N.type.b8d23b.2 [symbolic]
 // CHECK:STDOUT:   %J.impl_witness.b5245e.2: <witness> = impl_witness file.%J.impl_witness_table.loc39, @D.as.J.impl.3b0484.2(%T) [symbolic]
 // CHECK:STDOUT: }
@@ -1358,7 +1929,7 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:   %Main.import_ref.efcd44.3: type = import_ref Main//import_generic_decl, loc21_14, loaded [symbolic = @D.as.J.impl.265db6.1.%T (constants.%T)]
 // CHECK:STDOUT:   %Main.import_ref.f92: type = import_ref Main//import_generic_decl, loc8_18, loaded [symbolic = constants.%Self.binding.as_type]
 // CHECK:STDOUT:   %Main.import_ref.efcd44.4: type = import_ref Main//import_generic_decl, loc7_14, loaded [symbolic = @N.%T (constants.%T)]
-// CHECK:STDOUT:   %Main.import_ref.d4d: @N.%N.type (%N.type.b8d23b.1) = import_ref Main//import_generic_decl, loc7_24, loaded [symbolic = @N.%Self (constants.%Self.aa1)]
+// CHECK:STDOUT:   %Main.import_ref.d4d: @N.%N.type (%N.type.b8d23b.1) = import_ref Main//import_generic_decl, loc7_24, loaded [symbolic = @N.%Self (constants.%Self.aa1546.1)]
 // CHECK:STDOUT:   %Main.import_ref.388 = import_ref Main//import_generic_decl, loc7_24, unloaded
 // CHECK:STDOUT:   %Main.import_ref.efcd44.5: type = import_ref Main//import_generic_decl, loc7_14, loaded [symbolic = @N.%T (constants.%T)]
 // CHECK:STDOUT: }
@@ -1461,7 +2032,9 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.b8d23b.1)]
-// CHECK:STDOUT:   %Self: @N.%N.type (%N.type.b8d23b.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.aa1)]
+// CHECK:STDOUT:   %Self: @N.%N.type (%N.type.b8d23b.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.aa1546.1)]
+// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.8ec)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %J.type [symbolic = %require_complete (constants.%require_complete.387)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   constraint {
 // CHECK:STDOUT:   !members:
@@ -1477,7 +2050,7 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT: generic require @N.require0(imports.%Main.import_ref.efcd44.4: type, imports.%Main.import_ref.d4d: @N.%N.type (%N.type.b8d23b.1)) [from "fail_import_generic_decl.carbon"] {
 // CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]
 // CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.b8d23b.1)]
-// CHECK:STDOUT:   %Self: @N.require0.%N.type (%N.type.b8d23b.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.aa1)]
+// CHECK:STDOUT:   %Self: @N.require0.%N.type (%N.type.b8d23b.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.aa1546.1)]
 // CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
 // CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.8ec)]
 // CHECK:STDOUT: }
@@ -1624,12 +2197,18 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @N(constants.%T) {
 // CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %N.type => constants.%N.type.b8d23b.1
+// CHECK:STDOUT:   %Self => constants.%Self.aa1546.1
+// CHECK:STDOUT:   %J.type => constants.%J.type.8ec
+// CHECK:STDOUT:   %require_complete => constants.%require_complete.387
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @N.require0(constants.%T, constants.%Self.aa1) {
+// CHECK:STDOUT: specific @N.require0(constants.%T, constants.%Self.aa1546.1) {
 // CHECK:STDOUT:   %T => constants.%T
 // CHECK:STDOUT:   %N.type => constants.%N.type.b8d23b.1
-// CHECK:STDOUT:   %Self => constants.%Self.aa1
+// CHECK:STDOUT:   %Self => constants.%Self.aa1546.1
 // CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type
 // CHECK:STDOUT:   %J.type => constants.%J.type.8ec
 // CHECK:STDOUT: }
@@ -1643,6 +2222,12 @@ impl forall [T:! type] D as N(T*) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @N(constants.%ptr) {
 // CHECK:STDOUT:   %T => constants.%ptr
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %N.type => constants.%N.type.b8d23b.2
+// CHECK:STDOUT:   %Self => constants.%Self.aa1546.2
+// CHECK:STDOUT:   %J.type => constants.%J.type.4fa
+// CHECK:STDOUT:   %require_complete => constants.%require_complete.d4d
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @D.as.J.impl.3b0484.2(constants.%T) {

+ 862 - 0
toolchain/check/testdata/impl/incomplete.carbon

@@ -0,0 +1,862 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon
+// TODO: Add ranges and switch to "--dump-sem-ir-ranges=only".
+// EXTRA-ARGS: --dump-sem-ir-ranges=if-present
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/incomplete.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/incomplete.carbon
+
+// --- fail_empty_struct.carbon
+library "[[@TEST_NAME]]";
+
+interface I;
+
+// Requires I identified.
+impl {} as I;
+
+// CHECK:STDERR: fail_empty_struct.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `I` [ImplAsIncompleteFacetTypeDefinition]
+// CHECK:STDERR: impl {} as I {}
+// CHECK:STDERR: ^~~~~~~~~~~~~~
+// CHECK:STDERR: fail_empty_struct.carbon:[[@LINE-8]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
+// CHECK:STDERR: interface I;
+// CHECK:STDERR: ^~~~~~~~~~~~
+// CHECK:STDERR:
+impl {} as I {}
+
+// --- fail_class.carbon
+library "[[@TEST_NAME]]";
+
+interface J;
+class C {}
+
+// Requires I identified.
+// CHECK:STDERR: fail_class.carbon:[[@LINE+4]]:11: error: name `I` not found [NameNotFound]
+// CHECK:STDERR: impl C as I;
+// CHECK:STDERR:           ^
+// CHECK:STDERR:
+impl C as I;
+
+// CHECK:STDERR: fail_class.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `J` [ImplAsIncompleteFacetTypeDefinition]
+// CHECK:STDERR: impl C as J {}
+// CHECK:STDERR: ^~~~~~~~~~~~~
+// CHECK:STDERR: fail_class.carbon:[[@LINE-13]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
+// CHECK:STDERR: interface J;
+// CHECK:STDERR: ^~~~~~~~~~~~
+// CHECK:STDERR:
+impl C as J {}
+
+// --- fail_class_no_forward_decl.carbon
+library "[[@TEST_NAME]]";
+
+interface J;
+class C {}
+
+// CHECK:STDERR: fail_class_no_forward_decl.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `J` [ImplAsIncompleteFacetTypeDefinition]
+// CHECK:STDERR: impl C as J {}
+// CHECK:STDERR: ^~~~~~~~~~~~~
+// CHECK:STDERR: fail_class_no_forward_decl.carbon:[[@LINE-6]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
+// CHECK:STDERR: interface J;
+// CHECK:STDERR: ^~~~~~~~~~~~
+// CHECK:STDERR:
+impl C as J {}
+
+// --- fail_class_with_rewrite.carbon
+library "[[@TEST_NAME]]";
+
+interface J;
+class C {}
+
+// CHECK:STDERR: fail_class_with_rewrite.carbon:[[@LINE+7]]:19: error: member access into object of incomplete type `J` [IncompleteTypeInMemberAccess]
+// CHECK:STDERR: impl C as J where .X = ();
+// CHECK:STDERR:                   ^~
+// CHECK:STDERR: fail_class_with_rewrite.carbon:[[@LINE-6]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
+// CHECK:STDERR: interface J;
+// CHECK:STDERR: ^~~~~~~~~~~~
+// CHECK:STDERR:
+impl C as J where .X = ();
+
+// CHECK:STDERR: fail_class_with_rewrite.carbon:[[@LINE+7]]:19: error: member access into object of incomplete type `J` [IncompleteTypeInMemberAccess]
+// CHECK:STDERR: impl C as J where .X = () {}
+// CHECK:STDERR:                   ^~
+// CHECK:STDERR: fail_class_with_rewrite.carbon:[[@LINE-15]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
+// CHECK:STDERR: interface J;
+// CHECK:STDERR: ^~~~~~~~~~~~
+// CHECK:STDERR:
+impl C as J where .X = () {}
+
+// --- fail_todo_class_with_qualified_rewrite.carbon
+library "[[@TEST_NAME]]";
+
+interface J;
+interface K { let X:! type; }
+class C {}
+
+// TODO: There should be no error here.
+//
+// CHECK:STDERR: fail_todo_class_with_qualified_rewrite.carbon:[[@LINE+8]]:38: error: expected identifier or `Self` after `.` [ExpectedIdentifierOrSelfAfterPeriod]
+// CHECK:STDERR: impl C as J where .Self impls K and .(K.X) = ();
+// CHECK:STDERR:                                      ^
+// CHECK:STDERR:
+// CHECK:STDERR: fail_todo_class_with_qualified_rewrite.carbon:[[@LINE+4]]:38: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo]
+// CHECK:STDERR: impl C as J where .Self impls K and .(K.X) = ();
+// CHECK:STDERR:                                      ^
+// CHECK:STDERR:
+impl C as J where .Self impls K and .(K.X) = ();
+
+// TODO: The failure here should be that J is incomplete, once the rewrite of
+// `.(K.X)` works. Since any rewrite in the decl requires us to know the size of
+// the witness table which requires all interfaces to be complete.
+//
+// CHECK:STDERR: fail_todo_class_with_qualified_rewrite.carbon:[[@LINE+4]]:38: error: expected identifier or `Self` after `.` [ExpectedIdentifierOrSelfAfterPeriod]
+// CHECK:STDERR: impl C as J where .Self impls K and .(K.X) = () {}
+// CHECK:STDERR:                                      ^
+// CHECK:STDERR:
+impl C as J where .Self impls K and .(K.X) = () {}
+
+// --- incomplete_where.carbon
+library "[[@TEST_NAME]]";
+
+class C {}
+
+interface I {}
+interface Incomplete;
+
+impl C as I where .Self impls Incomplete {}
+
+// --- declaration_incomplete_where_rewrite.carbon
+library "[[@TEST_NAME]]";
+
+class C {}
+
+interface J { let T:! type; }
+interface Incomplete;
+
+impl C as J where .Self impls Incomplete and .T = ();
+
+impl C as J where .Self impls Incomplete and .T = () {}
+
+// --- fail_declaration_lookup_into_incomplete.carbon
+library "[[@TEST_NAME]]";
+
+class C {}
+
+interface I {}
+interface Incomplete;
+
+impl C as I where .Self impls Incomplete {
+  // CHECK:STDERR: fail_declaration_lookup_into_incomplete.carbon:[[@LINE+7]]:19: error: member access into incomplete facet type `Incomplete` [QualifiedExprInIncompleteFacetTypeScope]
+  // CHECK:STDERR:   fn F() -> Self.(Incomplete.T);
+  // CHECK:STDERR:                   ^~~~~~~~~~~~
+  // CHECK:STDERR: fail_declaration_lookup_into_incomplete.carbon:[[@LINE-6]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
+  // CHECK:STDERR: interface Incomplete;
+  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~
+  // CHECK:STDERR:
+  fn F() -> Self.(Incomplete.T);
+};
+
+// --- fail_unidentified_constraint.carbon
+library "[[@TEST_NAME]]";
+
+constraint X;
+class C {}
+
+// Requires X identified.
+// CHECK:STDERR: fail_unidentified_constraint.carbon:[[@LINE+7]]:1: error: facet type `X` cannot be identified in `impl as` [ImplOfUnidentifiedFacetType]
+// CHECK:STDERR: impl C as X;
+// CHECK:STDERR: ^~~~~~~~~~~~
+// CHECK:STDERR: fail_unidentified_constraint.carbon:[[@LINE-7]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
+// CHECK:STDERR: constraint X;
+// CHECK:STDERR: ^~~~~~~~~~~~~
+// CHECK:STDERR:
+impl C as X;
+
+// --- nested_require_incomplete_interface.carbon
+library "[[@TEST_NAME]]";
+
+interface Z;
+constraint Y {
+  // Not extend, so only required to be identified.
+  require impls Z;
+}
+interface X {
+  // Not extend, so only required to be identified.
+  require impls Y;
+}
+
+class C {}
+impl C as X {}
+
+// --- fail_incomplete_constraint.carbon
+library "[[@TEST_NAME]]";
+
+constraint A;
+
+interface B {
+  // CHECK:STDERR: fail_incomplete_constraint.carbon:[[@LINE+7]]:17: error: facet type `A` cannot be identified in `require` declaration [RequireImplsUnidentifiedFacetType]
+  // CHECK:STDERR:   require impls A;
+  // CHECK:STDERR:                 ^
+  // CHECK:STDERR: fail_incomplete_constraint.carbon:[[@LINE-6]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
+  // CHECK:STDERR: constraint A;
+  // CHECK:STDERR: ^~~~~~~~~~~~~
+  // CHECK:STDERR:
+  require impls A;
+}
+
+// CHECK:STDOUT: --- fail_empty_struct.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]
+// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness file.%I.impl_witness_table [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .I = %I.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}
+// CHECK:STDOUT:   impl_decl @empty_struct_type.as.I.impl [concrete] {} {
+// CHECK:STDOUT:     %.loc6_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
+// CHECK:STDOUT:     %.loc6_7.2: type = converted %.loc6_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
+// CHECK:STDOUT:     %I.ref.loc6: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @empty_struct_type.as.I.impl [concrete]
+// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]
+// CHECK:STDOUT:   impl_decl @empty_struct_type.as.I.impl [concrete] {} {
+// CHECK:STDOUT:     %.loc15_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
+// CHECK:STDOUT:     %.loc15_7.2: type = converted %.loc15_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
+// CHECK:STDOUT:     %I.ref.loc15: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @I;
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @empty_struct_type.as.I.impl: %.loc6_7.2 as %I.ref.loc6 {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   witness = <error>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- fail_class.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %J.type: type = facet_type <@J> [concrete]
+// CHECK:STDOUT:   %C: type = class_type @C [concrete]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .J = %J.decl
+// CHECK:STDOUT:     .C = %C.decl
+// CHECK:STDOUT:     .I = <poisoned>
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
+// CHECK:STDOUT:   impl_decl @C.as.<error>.impl [concrete] {} {
+// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %I.ref: <error> = name_ref I, <error> [concrete = <error>]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   impl_decl @C.as.J.impl [concrete] {} {
+// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @J;
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @C.as.<error>.impl: %C.ref as <error>;
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @C.as.J.impl: %C.ref as %J.ref {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   witness = <error>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:   complete_type_witness = %complete_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = constants.%C
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- fail_class_no_forward_decl.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %J.type: type = facet_type <@J> [concrete]
+// CHECK:STDOUT:   %C: type = class_type @C [concrete]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .J = %J.decl
+// CHECK:STDOUT:     .C = %C.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
+// CHECK:STDOUT:   impl_decl @C.as.J.impl [concrete] {} {
+// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @J;
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @C.as.J.impl: %C.ref as %J.ref {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   witness = <error>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:   complete_type_witness = %complete_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = constants.%C
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- fail_class_with_rewrite.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %J.type: type = facet_type <@J> [concrete]
+// CHECK:STDOUT:   %C: type = class_type @C [concrete]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %.Self: %J.type = symbolic_binding .Self [symbolic_self]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
+// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .J = %J.decl
+// CHECK:STDOUT:     .C = %C.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
+// CHECK:STDOUT:   impl_decl @C.as.<error>.impl [concrete] {} {
+// CHECK:STDOUT:     %C.ref.loc13: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %J.ref.loc13: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
+// CHECK:STDOUT:     %.Self.2: %J.type = symbolic_binding .Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %.Self.ref.loc13: %J.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %.loc13_25: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
+// CHECK:STDOUT:     %.loc13_13: type = where_expr %.Self.2 [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:       requirement_rewrite <error>, <error>
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   impl_decl @C.as.<error>.impl [concrete] {} {
+// CHECK:STDOUT:     %C.ref.loc22: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %J.ref.loc22: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
+// CHECK:STDOUT:     %.Self.1: %J.type = symbolic_binding .Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %.Self.ref.loc22: %J.type = name_ref .Self, %.Self.1 [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %.loc22_25: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
+// CHECK:STDOUT:     %.loc22_13: type = where_expr %.Self.1 [concrete = <error>] {
+// CHECK:STDOUT:       requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:       requirement_rewrite <error>, <error>
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @J;
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @C.as.<error>.impl: %C.ref.loc13 as %.loc13_13 {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   witness = <error>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:   complete_type_witness = %complete_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = constants.%C
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- fail_todo_class_with_qualified_rewrite.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %K.type: type = facet_type <@K> [concrete]
+// CHECK:STDOUT:   %Self: %K.type = symbolic_binding Self, 0 [symbolic]
+// CHECK:STDOUT:   %K.assoc_type: type = assoc_entity_type @K [concrete]
+// CHECK:STDOUT:   %assoc0: %K.assoc_type = assoc_entity element0, @K.%X [concrete]
+// CHECK:STDOUT:   %C: type = class_type @C [concrete]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @J;
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @K {
+// CHECK:STDOUT:   %Self: %K.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
+// CHECK:STDOUT:   %X: type = assoc_const_decl @X [concrete] {
+// CHECK:STDOUT:     %assoc0: %K.assoc_type = assoc_entity element0, @K.%X [concrete = constants.%assoc0]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = %Self
+// CHECK:STDOUT:   .X = @X.%assoc0
+// CHECK:STDOUT:   witness = (%X)
+// CHECK:STDOUT:
+// CHECK:STDOUT: !requires:
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic assoc_const @X(@K.%Self: %K.type) {
+// CHECK:STDOUT:   assoc_const X:! type;
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:   complete_type_witness = %complete_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = constants.%C
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @X(constants.%Self) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- incomplete_where.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %C: type = class_type @C [concrete]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]
+// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]
+// CHECK:STDOUT:   %Incomplete.type: type = facet_type <@Incomplete> [concrete]
+// CHECK:STDOUT:   %.Self: %I.type = symbolic_binding .Self [symbolic_self]
+// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]
+// CHECK:STDOUT:   %I_where.type: type = facet_type <@I where .Self impls @Incomplete> [concrete]
+// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness file.%I.impl_witness_table [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .C = %C.decl
+// CHECK:STDOUT:     .I = %I.decl
+// CHECK:STDOUT:     .Incomplete = %Incomplete.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
+// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}
+// CHECK:STDOUT:   %Incomplete.decl: type = interface_decl @Incomplete [concrete = constants.%Incomplete.type] {} {}
+// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {
+// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
+// CHECK:STDOUT:     %.Self: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %.Self.ref: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type]
+// CHECK:STDOUT:     %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.binding.as_type]
+// CHECK:STDOUT:     %.loc8_19: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.binding.as_type]
+// CHECK:STDOUT:     %.loc8_13: type = where_expr %.Self [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:       requirement_impls %.loc8_19, %Incomplete.ref
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @C.as.I.impl [concrete]
+// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @I {
+// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = %Self
+// CHECK:STDOUT:   witness = ()
+// CHECK:STDOUT:
+// CHECK:STDOUT: !requires:
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @Incomplete;
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @C.as.I.impl: %C.ref as %.loc8_13 {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   witness = file.%I.impl_witness
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:   complete_type_witness = %complete_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = constants.%C
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- declaration_incomplete_where_rewrite.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %C: type = class_type @C [concrete]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %J.type: type = facet_type <@J> [concrete]
+// CHECK:STDOUT:   %Self: %J.type = symbolic_binding Self, 0 [symbolic]
+// CHECK:STDOUT:   %J.assoc_type: type = assoc_entity_type @J [concrete]
+// CHECK:STDOUT:   %assoc0: %J.assoc_type = assoc_entity element0, @J.%T [concrete]
+// CHECK:STDOUT:   %Incomplete.type: type = facet_type <@Incomplete> [concrete]
+// CHECK:STDOUT:   %.Self: %J.type = symbolic_binding .Self [symbolic_self]
+// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
+// CHECK:STDOUT:   %J.lookup_impl_witness: <witness> = lookup_impl_witness %.Self, @J [symbolic_self]
+// CHECK:STDOUT:   %impl.elem0: type = impl_witness_access %J.lookup_impl_witness, element0 [symbolic_self]
+// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
+// CHECK:STDOUT:   %J_where.type: type = facet_type <@J where .Self impls @Incomplete and %impl.elem0 = %empty_tuple.type> [concrete]
+// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness file.%J.impl_witness_table [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .C = %C.decl
+// CHECK:STDOUT:     .J = %J.decl
+// CHECK:STDOUT:     .Incomplete = %Incomplete.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
+// CHECK:STDOUT:   %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}
+// CHECK:STDOUT:   %Incomplete.decl: type = interface_decl @Incomplete [concrete = constants.%Incomplete.type] {} {}
+// CHECK:STDOUT:   impl_decl @C.as.J.impl [concrete] {} {
+// CHECK:STDOUT:     %C.ref.loc8: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %J.ref.loc8: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
+// CHECK:STDOUT:     %.Self.2: %J.type = symbolic_binding .Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %.Self.ref.loc8_19: %J.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %Incomplete.ref.loc8: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type]
+// CHECK:STDOUT:     %.Self.as_type.loc8_19: type = facet_access_type %.Self.ref.loc8_19 [symbolic_self = constants.%.Self.binding.as_type]
+// CHECK:STDOUT:     %.loc8_19: type = converted %.Self.ref.loc8_19, %.Self.as_type.loc8_19 [symbolic_self = constants.%.Self.binding.as_type]
+// CHECK:STDOUT:     %.Self.ref.loc8_46: %J.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %T.ref.loc8: %J.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]
+// CHECK:STDOUT:     %.Self.as_type.loc8_46: type = facet_access_type %.Self.ref.loc8_46 [symbolic_self = constants.%.Self.binding.as_type]
+// CHECK:STDOUT:     %.loc8_46: type = converted %.Self.ref.loc8_46, %.Self.as_type.loc8_46 [symbolic_self = constants.%.Self.binding.as_type]
+// CHECK:STDOUT:     %impl.elem0.loc8: type = impl_witness_access constants.%J.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
+// CHECK:STDOUT:     %.loc8_52.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
+// CHECK:STDOUT:     %.loc8_52.2: type = converted %.loc8_52.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
+// CHECK:STDOUT:     %.loc8_13: type = where_expr %.Self.2 [concrete = constants.%J_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:       requirement_impls %.loc8_19, %Incomplete.ref.loc8
+// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc8, %.loc8_52.2
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %J.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant), @C.as.J.impl [concrete]
+// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness]
+// CHECK:STDOUT:   %impl_witness_assoc_constant: type = impl_witness_assoc_constant constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
+// CHECK:STDOUT:   impl_decl @C.as.J.impl [concrete] {} {
+// CHECK:STDOUT:     %C.ref.loc10: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %J.ref.loc10: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
+// CHECK:STDOUT:     %.Self.1: %J.type = symbolic_binding .Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %.Self.ref.loc10_19: %J.type = name_ref .Self, %.Self.1 [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %Incomplete.ref.loc10: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type]
+// CHECK:STDOUT:     %.Self.as_type.loc10_19: type = facet_access_type %.Self.ref.loc10_19 [symbolic_self = constants.%.Self.binding.as_type]
+// CHECK:STDOUT:     %.loc10_19: type = converted %.Self.ref.loc10_19, %.Self.as_type.loc10_19 [symbolic_self = constants.%.Self.binding.as_type]
+// CHECK:STDOUT:     %.Self.ref.loc10_46: %J.type = name_ref .Self, %.Self.1 [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %T.ref.loc10: %J.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]
+// CHECK:STDOUT:     %.Self.as_type.loc10_46: type = facet_access_type %.Self.ref.loc10_46 [symbolic_self = constants.%.Self.binding.as_type]
+// CHECK:STDOUT:     %.loc10_46: type = converted %.Self.ref.loc10_46, %.Self.as_type.loc10_46 [symbolic_self = constants.%.Self.binding.as_type]
+// CHECK:STDOUT:     %impl.elem0.loc10: type = impl_witness_access constants.%J.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]
+// CHECK:STDOUT:     %.loc10_52.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
+// CHECK:STDOUT:     %.loc10_52.2: type = converted %.loc10_52.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
+// CHECK:STDOUT:     %.loc10_13: type = where_expr %.Self.1 [concrete = constants.%J_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type constants.%J.type
+// CHECK:STDOUT:       requirement_impls %.loc10_19, %Incomplete.ref.loc10
+// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc10, %.loc10_52.2
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @J {
+// CHECK:STDOUT:   %Self: %J.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
+// CHECK:STDOUT:   %T: type = assoc_const_decl @T [concrete] {
+// CHECK:STDOUT:     %assoc0: %J.assoc_type = assoc_entity element0, @J.%T [concrete = constants.%assoc0]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = %Self
+// CHECK:STDOUT:   .T = @T.%assoc0
+// CHECK:STDOUT:   witness = (%T)
+// CHECK:STDOUT:
+// CHECK:STDOUT: !requires:
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @Incomplete;
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic assoc_const @T(@J.%Self: %J.type) {
+// CHECK:STDOUT:   assoc_const T:! type;
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @C.as.J.impl: %C.ref.loc8 as %.loc8_13 {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   witness = file.%J.impl_witness
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:   complete_type_witness = %complete_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = constants.%C
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @T(constants.%Self) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @T(constants.%.Self) {}
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- fail_declaration_lookup_into_incomplete.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %C: type = class_type @C [concrete]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]
+// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]
+// CHECK:STDOUT:   %Incomplete.type: type = facet_type <@Incomplete> [concrete]
+// CHECK:STDOUT:   %.Self: %I.type = symbolic_binding .Self [symbolic_self]
+// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]
+// CHECK:STDOUT:   %I_where.type: type = facet_type <@I where .Self impls @Incomplete> [concrete]
+// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness file.%I.impl_witness_table [concrete]
+// CHECK:STDOUT:   %C.as.I.impl.F.type: type = fn_type @C.as.I.impl.F [concrete]
+// CHECK:STDOUT:   %C.as.I.impl.F: %C.as.I.impl.F.type = struct_value () [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .C = %C.decl
+// CHECK:STDOUT:     .I = %I.decl
+// CHECK:STDOUT:     .Incomplete = %Incomplete.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
+// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}
+// CHECK:STDOUT:   %Incomplete.decl: type = interface_decl @Incomplete [concrete = constants.%Incomplete.type] {} {}
+// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {
+// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
+// CHECK:STDOUT:     %.Self: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %.Self.ref: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type]
+// CHECK:STDOUT:     %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.binding.as_type]
+// CHECK:STDOUT:     %.loc8_19: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.binding.as_type]
+// CHECK:STDOUT:     %.loc8_13: type = where_expr %.Self [concrete = constants.%I_where.type] {
+// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type
+// CHECK:STDOUT:       requirement_impls %.loc8_19, %Incomplete.ref
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @C.as.I.impl [concrete]
+// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @I {
+// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = %Self
+// CHECK:STDOUT:   witness = ()
+// CHECK:STDOUT:
+// CHECK:STDOUT: !requires:
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @Incomplete;
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @C.as.I.impl: %C.ref as %.loc8_13 {
+// CHECK:STDOUT:   %C.as.I.impl.F.decl: %C.as.I.impl.F.type = fn_decl @C.as.I.impl.F [concrete = constants.%C.as.I.impl.F] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern [concrete]
+// CHECK:STDOUT:     %return.param_patt: <error> = out_param_pattern %return.patt, call_param0 [concrete]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %Self.ref: type = name_ref Self, @C.as.I.impl.%C.ref [concrete = constants.%C]
+// CHECK:STDOUT:     %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type]
+// CHECK:STDOUT:     %T.ref: <error> = name_ref T, <error> [concrete = <error>]
+// CHECK:STDOUT:     %return.param: ref <error> = out_param call_param0
+// CHECK:STDOUT:     %return: ref <error> = return_slot %return.param
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Incomplete = <poisoned>
+// CHECK:STDOUT:   .F = %C.as.I.impl.F.decl
+// CHECK:STDOUT:   witness = file.%I.impl_witness
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:   complete_type_witness = %complete_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = constants.%C
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @C.as.I.impl.F() -> <error>;
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- fail_unidentified_constraint.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %X.type: type = facet_type <@X> [concrete]
+// CHECK:STDOUT:   %C: type = class_type @C [concrete]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .X = %X.decl
+// CHECK:STDOUT:     .C = %C.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %X.decl: type = constraint_decl @X [concrete = constants.%X.type] {} {}
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
+// CHECK:STDOUT:   impl_decl @C.as.<error>.impl [concrete] {} {
+// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %X.ref: type = name_ref X, file.%X.decl [concrete = constants.%X.type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: constraint @X;
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @C.as.<error>.impl: %C.ref as %X.ref;
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:   complete_type_witness = %complete_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = constants.%C
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- nested_require_incomplete_interface.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %Z.type: type = facet_type <@Z> [concrete]
+// CHECK:STDOUT:   %Y.type: type = facet_type <@Y> [concrete]
+// CHECK:STDOUT:   %Self.861: %Y.type = symbolic_binding Self, 0 [symbolic]
+// CHECK:STDOUT:   %Self.binding.as_type.1a1: type = symbolic_binding_type Self, 0, %Self.861 [symbolic]
+// CHECK:STDOUT:   %X.type: type = facet_type <@X> [concrete]
+// CHECK:STDOUT:   %Self.40f: %X.type = symbolic_binding Self, 0 [symbolic]
+// CHECK:STDOUT:   %Self.binding.as_type.dcc: type = symbolic_binding_type Self, 0, %Self.40f [symbolic]
+// CHECK:STDOUT:   %C: type = class_type @C [concrete]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %X.impl_witness: <witness> = impl_witness file.%X.impl_witness_table [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .Z = %Z.decl
+// CHECK:STDOUT:     .Y = %Y.decl
+// CHECK:STDOUT:     .X = %X.decl
+// CHECK:STDOUT:     .C = %C.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %Z.decl: type = interface_decl @Z [concrete = constants.%Z.type] {} {}
+// CHECK:STDOUT:   %Y.decl: type = constraint_decl @Y [concrete = constants.%Y.type] {} {}
+// CHECK:STDOUT:   %X.decl: type = interface_decl @X [concrete = constants.%X.type] {} {}
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
+// CHECK:STDOUT:   impl_decl @C.as.X.impl [concrete] {} {
+// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
+// CHECK:STDOUT:     %X.ref: type = name_ref X, file.%X.decl [concrete = constants.%X.type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %X.impl_witness_table = impl_witness_table (), @C.as.X.impl [concrete]
+// CHECK:STDOUT:   %X.impl_witness: <witness> = impl_witness %X.impl_witness_table [concrete = constants.%X.impl_witness]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @Z;
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @X {
+// CHECK:STDOUT:   %Self: %X.type = symbolic_binding Self, 0 [symbolic = constants.%Self.40f]
+// CHECK:STDOUT:   %X.require1.decl = require_decl @X.require1 [concrete] {
+// CHECK:STDOUT:     require %Self.as_type impls <@Y>
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %Self.as_type: type = facet_access_type @X.%Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.dcc)]
+// CHECK:STDOUT:     %Y.ref: type = name_ref Y, file.%Y.decl [concrete = constants.%Y.type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = %Self
+// CHECK:STDOUT:   .Y = <poisoned>
+// CHECK:STDOUT:   witness = ()
+// CHECK:STDOUT:
+// CHECK:STDOUT: !requires:
+// CHECK:STDOUT:   @X.require1 {
+// CHECK:STDOUT:     require @X.require1.%Self.as_type impls <@Y>
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: constraint @Y {
+// CHECK:STDOUT:   %Self: %Y.type = symbolic_binding Self, 0 [symbolic = constants.%Self.861]
+// CHECK:STDOUT:   %Y.require0.decl = require_decl @Y.require0 [concrete] {
+// CHECK:STDOUT:     require %Self.as_type impls <@Z>
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %Self.as_type: type = facet_access_type @Y.%Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.1a1)]
+// CHECK:STDOUT:     %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = %Self
+// CHECK:STDOUT:   .Z = <poisoned>
+// CHECK:STDOUT:
+// CHECK:STDOUT: !requires:
+// CHECK:STDOUT:   @Y.require0 {
+// CHECK:STDOUT:     require @Y.require0.%Self.as_type impls <@Z>
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic require @Y.require0(@Y.%Self: %Y.type) {
+// CHECK:STDOUT:   %Self: %Y.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self.861)]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.1a1)]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: generic require @X.require1(@X.%Self: %X.type) {
+// CHECK:STDOUT:   %Self: %X.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self.40f)]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.dcc)]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: impl @C.as.X.impl: %C.ref as %X.ref {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   witness = file.%X.impl_witness
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:   complete_type_witness = %complete_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = constants.%C
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @Y.require0(constants.%Self.861) {
+// CHECK:STDOUT:   %Self => constants.%Self.861
+// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.1a1
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @X.require1(constants.%Self.40f) {
+// CHECK:STDOUT:   %Self => constants.%Self.40f
+// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.dcc
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- fail_incomplete_constraint.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %A.type: type = facet_type <@A> [concrete]
+// CHECK:STDOUT:   %B.type: type = facet_type <@B> [concrete]
+// CHECK:STDOUT:   %Self: %B.type = symbolic_binding Self, 0 [symbolic]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
+// CHECK:STDOUT:     .A = %A.decl
+// CHECK:STDOUT:     .B = %B.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %A.decl: type = constraint_decl @A [concrete = constants.%A.type] {} {}
+// CHECK:STDOUT:   %B.decl: type = interface_decl @B [concrete = constants.%B.type] {} {}
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: interface @B {
+// CHECK:STDOUT:   %Self: %B.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = %Self
+// CHECK:STDOUT:   .A = <poisoned>
+// CHECK:STDOUT:   witness = ()
+// CHECK:STDOUT:
+// CHECK:STDOUT: !requires:
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: constraint @A;
+// CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/impl/use_assoc_const.carbon → toolchain/check/testdata/impl/use_assoc_entity.carbon

@@ -8,9 +8,9 @@
 //
 // AUTOUPDATE
 // TIP: To test this file alone, run:
-// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/use_assoc_const.carbon
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/use_assoc_entity.carbon
 // TIP: To dump output, run:
-// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/use_assoc_const.carbon
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/use_assoc_entity.carbon
 
 // --- associated_type_in_method_signature.carbon
 library "[[@TEST_NAME]]";

+ 99 - 55
toolchain/check/testdata/interface/incomplete.carbon

@@ -28,45 +28,48 @@ interface I {
   let T:! C;
 }
 
-// --- fail_incomplete_constraint.carbon
+// --- fail_incomplete_extend_constraint.carbon
 library "[[@TEST_NAME]]";
 
 constraint A;
 
 interface B {
-  // CHECK:STDERR: fail_incomplete_constraint.carbon:[[@LINE+7]]:17: error: facet type `A` cannot be identified in `require` declaration [RequireImplsUnidentifiedFacetType]
-  // CHECK:STDERR:   require impls A;
-  // CHECK:STDERR:                 ^
-  // CHECK:STDERR: fail_incomplete_constraint.carbon:[[@LINE-6]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
+  // CHECK:STDERR: fail_incomplete_extend_constraint.carbon:[[@LINE+7]]:24: error: facet type `A` cannot be identified in `require` declaration [RequireImplsUnidentifiedFacetType]
+  // CHECK:STDERR:   extend require impls A;
+  // CHECK:STDERR:                        ^
+  // CHECK:STDERR: fail_incomplete_extend_constraint.carbon:[[@LINE-6]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
   // CHECK:STDERR: constraint A;
   // CHECK:STDERR: ^~~~~~~~~~~~~
   // CHECK:STDERR:
-  require impls A;
+  extend require impls A;
 }
 
-// --- incomplete_interface.carbon
+// --- fail_extend_require_enclosing.carbon
 library "[[@TEST_NAME]]";
 
-interface A;
-
-interface B {
-  require impls A;
+interface A {
+  // CHECK:STDERR: fail_extend_require_enclosing.carbon:[[@LINE+7]]:24: error: `extend require` of incomplete facet type `A` [RequireImplsIncompleteFacetType]
+  // CHECK:STDERR:   extend require impls A;
+  // CHECK:STDERR:                        ^
+  // CHECK:STDERR: fail_extend_require_enclosing.carbon:[[@LINE-4]]:1: note: interface is currently being defined [InterfaceIncompleteWithinDefinition]
+  // CHECK:STDERR: interface A {
+  // CHECK:STDERR: ^~~~~~~~~~~~~
+  // CHECK:STDERR:
+  extend require impls A;
 }
 
-// --- fail_incomplete_interface_in_where.carbon
+// --- fail_extend_require_enclosing_generic.carbon
 library "[[@TEST_NAME]]";
 
-interface A;
-
-interface B {
-  // CHECK:STDERR: fail_incomplete_interface_in_where.carbon:[[@LINE+7]]:25: error: member access into object of incomplete type `A` [IncompleteTypeInMemberAccess]
-  // CHECK:STDERR:   require impls A where .X = {};
-  // CHECK:STDERR:                         ^~
-  // CHECK:STDERR: fail_incomplete_interface_in_where.carbon:[[@LINE-6]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
-  // CHECK:STDERR: interface A;
-  // CHECK:STDERR: ^~~~~~~~~~~~
+interface A(T:! type) {
+  // CHECK:STDERR: fail_extend_require_enclosing_generic.carbon:[[@LINE+7]]:24: error: `extend require` of incomplete facet type `A({})` [RequireImplsIncompleteFacetType]
+  // CHECK:STDERR:   extend require impls A({});
+  // CHECK:STDERR:                        ^~~~~
+  // CHECK:STDERR: fail_extend_require_enclosing_generic.carbon:[[@LINE-4]]:1: note: interface is currently being defined [InterfaceIncompleteWithinDefinition]
+  // CHECK:STDERR: interface A(T:! type) {
+  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~
   // CHECK:STDERR:
-  require impls A where .X = {};
+  extend require impls A({});
 }
 
 // CHECK:STDOUT: --- fail_incomplete_type.carbon
@@ -111,7 +114,7 @@ interface B {
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @T(constants.%Self) {}
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- fail_incomplete_constraint.carbon
+// CHECK:STDOUT: --- fail_incomplete_extend_constraint.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %A.type: type = facet_type <@A> [concrete]
@@ -141,32 +144,27 @@ interface B {
 // CHECK:STDOUT:
 // CHECK:STDOUT: constraint @A;
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- incomplete_interface.carbon
+// CHECK:STDOUT: --- fail_extend_require_enclosing.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %A.type: type = facet_type <@A> [concrete]
-// CHECK:STDOUT:   %B.type: type = facet_type <@B> [concrete]
-// CHECK:STDOUT:   %Self: %B.type = symbolic_binding Self, 0 [symbolic]
+// CHECK:STDOUT:   %Self: %A.type = symbolic_binding Self, 0 [symbolic]
 // CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
 // CHECK:STDOUT:     .A = %A.decl
-// CHECK:STDOUT:     .B = %B.decl
 // CHECK:STDOUT:   }
 // 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: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: interface @A;
-// CHECK:STDOUT:
-// CHECK:STDOUT: interface @B {
-// CHECK:STDOUT:   %Self: %B.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
-// CHECK:STDOUT:   %B.require0.decl = require_decl @B.require0 [concrete] {
+// CHECK:STDOUT: interface @A {
+// CHECK:STDOUT:   %Self: %A.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
+// CHECK:STDOUT:   %A.require0.decl = require_decl @A.require0 [concrete] {
 // CHECK:STDOUT:     require %Self.as_type impls <@A>
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %Self.as_type: type = facet_access_type @B.%Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
+// CHECK:STDOUT:     %Self.as_type: type = facet_access_type @A.%Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
 // CHECK:STDOUT:     %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A.type]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:
@@ -176,48 +174,94 @@ interface B {
 // CHECK:STDOUT:   witness = ()
 // CHECK:STDOUT:
 // CHECK:STDOUT: !requires:
-// CHECK:STDOUT:   @B.require0 {
-// CHECK:STDOUT:     require @B.require0.%Self.as_type impls <@A>
-// CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: generic require @B.require0(@B.%Self: %B.type) {
-// CHECK:STDOUT:   %Self: %B.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self)]
+// CHECK:STDOUT: generic require @A.require0(@A.%Self: %A.type) {
+// CHECK:STDOUT:   %Self: %A.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self)]
 // CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @B.require0(constants.%Self) {
+// CHECK:STDOUT: specific @A.require0(constants.%Self) {
 // CHECK:STDOUT:   %Self => constants.%Self
 // CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- fail_incomplete_interface_in_where.carbon
+// CHECK:STDOUT: --- fail_extend_require_enclosing_generic.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %A.type: type = facet_type <@A> [concrete]
-// CHECK:STDOUT:   %B.type: type = facet_type <@B> [concrete]
-// CHECK:STDOUT:   %Self: %B.type = symbolic_binding Self, 0 [symbolic]
+// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]
+// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]
+// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]
+// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]
+// CHECK:STDOUT:   %A.type.495: type = generic_interface_type @A [concrete]
+// CHECK:STDOUT:   %A.generic: %A.type.495 = struct_value () [concrete]
+// CHECK:STDOUT:   %A.type.c1c: type = facet_type <@A, @A(%T)> [symbolic]
+// CHECK:STDOUT:   %Self: %A.type.c1c = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic]
+// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
+// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]
+// CHECK:STDOUT:   %A.type.23f: type = facet_type <@A, @A(%empty_struct_type)> [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
 // CHECK:STDOUT:     .A = %A.decl
-// CHECK:STDOUT:     .B = %B.decl
 // CHECK:STDOUT:   }
-// 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:   %A.decl: %A.type.495 = interface_decl @A [concrete = constants.%A.generic] {
+// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]
+// CHECK:STDOUT:     %T.loc3_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc3_13.1 (constants.%T)]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: interface @A;
+// CHECK:STDOUT: generic interface @A(%T.loc3_13.2: type) {
+// CHECK:STDOUT:   %T.loc3_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc3_13.1 (constants.%T)]
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %A.type: type = facet_type <@A, @A(%T.loc3_13.1)> [symbolic = %A.type (constants.%A.type.c1c)]
+// CHECK:STDOUT:   %Self.loc3_23.2: @A.%A.type (%A.type.c1c) = symbolic_binding Self, 1 [symbolic = %Self.loc3_23.2 (constants.%Self)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   interface {
+// CHECK:STDOUT:     %Self.loc3_23.1: @A.%A.type (%A.type.c1c) = symbolic_binding Self, 1 [symbolic = %Self.loc3_23.2 (constants.%Self)]
+// CHECK:STDOUT:     %A.require0.decl = require_decl @A.require0 [concrete] {
+// CHECK:STDOUT:       require %Self.as_type impls <@A, @A(constants.%empty_struct_type)>
+// CHECK:STDOUT:     } {
+// CHECK:STDOUT:       %Self.as_type: type = facet_access_type @A.%Self.loc3_23.1 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
+// CHECK:STDOUT:       %A.ref: %A.type.495 = name_ref A, file.%A.decl [concrete = constants.%A.generic]
+// CHECK:STDOUT:       %.loc11_27: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
+// CHECK:STDOUT:       %.loc11_28: type = converted %.loc11_27, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
+// CHECK:STDOUT:       %A.type.loc11_28: type = facet_type <@A, @A(constants.%empty_struct_type)> [concrete = constants.%A.type.23f]
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !members:
+// CHECK:STDOUT:     .Self = %Self.loc3_23.1
+// CHECK:STDOUT:     .A = <poisoned>
+// CHECK:STDOUT:     witness = ()
+// CHECK:STDOUT:
+// CHECK:STDOUT:   !requires:
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: interface @B {
-// CHECK:STDOUT:   %Self: %B.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
+// CHECK:STDOUT: generic require @A.require0(@A.%T.loc3_13.2: type, @A.%Self.loc3_23.1: @A.%A.type (%A.type.c1c)) {
+// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:   %A.type.loc11_18: type = facet_type <@A, @A(%T)> [symbolic = %A.type.loc11_18 (constants.%A.type.c1c)]
+// CHECK:STDOUT:   %Self: @A.require0.%A.type.loc11_18 (%A.type.c1c) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self)]
+// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
+// CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Self = %Self
-// CHECK:STDOUT:   .A = <poisoned>
-// CHECK:STDOUT:   witness = ()
+// CHECK:STDOUT: specific @A(constants.%T) {
+// CHECK:STDOUT:   %T.loc3_13.1 => constants.%T
+// CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: !requires:
+// CHECK:STDOUT: specific @A(constants.%empty_struct_type) {
+// CHECK:STDOUT:   %T.loc3_13.1 => constants.%empty_struct_type
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: specific @A.require0(constants.%T, constants.%Self) {
+// CHECK:STDOUT:   %T => constants.%T
+// CHECK:STDOUT:   %A.type.loc11_18 => constants.%A.type.c1c
+// CHECK:STDOUT:   %Self => constants.%Self
+// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 8 - 3
toolchain/check/testdata/named_constraint/empty_generic.carbon

@@ -36,7 +36,7 @@ fn G(T:! Z, U:! Empty(T), V:! type) {
 // CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %empty_struct.4bc: %Empty.type.a8a = struct_value () [concrete]
 // CHECK:STDOUT:   %Empty.type.b8d23b.1: type = facet_type <@Empty, @Empty(%T.d9f)> [symbolic]
-// CHECK:STDOUT:   %Self.aa1: %Empty.type.b8d23b.1 = symbolic_binding Self, 1 [symbolic]
+// CHECK:STDOUT:   %Self.aa1546.1: %Empty.type.b8d23b.1 = symbolic_binding Self, 1 [symbolic]
 // CHECK:STDOUT:   %U.aa1546.1: %Empty.type.b8d23b.1 = symbolic_binding U, 1 [symbolic]
 // CHECK:STDOUT:   %pattern_type.e25e9f.1: type = pattern_type %Empty.type.b8d23b.1 [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
@@ -58,6 +58,7 @@ fn G(T:! Z, U:! Empty(T), V:! type) {
 // CHECK:STDOUT:   %F.specific_fn.55c: <specific function> = specific_function %F, @F(%T.binding.as_type, %Empty.facet.832) [symbolic]
 // CHECK:STDOUT:   %Empty.facet.146: %Empty.type.b8d23b.2 = facet_value %T.binding.as_type, () [symbolic]
 // CHECK:STDOUT:   %F.specific_fn.d3f: <specific function> = specific_function %F, @F(%T.binding.as_type, %Empty.facet.146) [symbolic]
+// CHECK:STDOUT:   %Self.aa1546.2: %Empty.type.b8d23b.2 = symbolic_binding Self, 1 [symbolic]
 // CHECK:STDOUT:   %F.specific_fn.4af: <specific function> = specific_function %F, @F(%T.binding.as_type, %U.aa1546.2) [symbolic]
 // CHECK:STDOUT:   %Empty.facet.920: %Empty.type.b8d23b.2 = facet_value %V, () [symbolic]
 // CHECK:STDOUT:   %F.specific_fn.905: <specific function> = specific_function %F, @F(%T.binding.as_type, %Empty.facet.920) [symbolic]
@@ -113,10 +114,10 @@ fn G(T:! Z, U:! Empty(T), V:! type) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %Empty.type: type = facet_type <@Empty, @Empty(%T.loc16_18.1)> [symbolic = %Empty.type (constants.%Empty.type.b8d23b.1)]
-// CHECK:STDOUT:   %Self.loc16_28.2: @Empty.%Empty.type (%Empty.type.b8d23b.1) = symbolic_binding Self, 1 [symbolic = %Self.loc16_28.2 (constants.%Self.aa1)]
+// CHECK:STDOUT:   %Self.loc16_28.2: @Empty.%Empty.type (%Empty.type.b8d23b.1) = symbolic_binding Self, 1 [symbolic = %Self.loc16_28.2 (constants.%Self.aa1546.1)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   constraint {
-// CHECK:STDOUT:     %Self.loc16_28.1: @Empty.%Empty.type (%Empty.type.b8d23b.1) = symbolic_binding Self, 1 [symbolic = %Self.loc16_28.2 (constants.%Self.aa1)]
+// CHECK:STDOUT:     %Self.loc16_28.1: @Empty.%Empty.type (%Empty.type.b8d23b.1) = symbolic_binding Self, 1 [symbolic = %Self.loc16_28.2 (constants.%Self.aa1546.1)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   !members:
 // CHECK:STDOUT:     .Self = %Self.loc16_28.1
@@ -221,6 +222,10 @@ fn G(T:! Z, U:! Empty(T), V:! type) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @Empty(constants.%T.binding.as_type) {
 // CHECK:STDOUT:   %T.loc16_18.1 => constants.%T.binding.as_type
+// CHECK:STDOUT:
+// CHECK:STDOUT: !definition:
+// CHECK:STDOUT:   %Empty.type => constants.%Empty.type.b8d23b.2
+// CHECK:STDOUT:   %Self.loc16_28.2 => constants.%Self.aa1546.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @G(constants.%T.3b3, constants.%U.aa1546.2, constants.%V) {

+ 57 - 45
toolchain/check/type_completion.cpp

@@ -14,7 +14,9 @@
 #include "toolchain/check/type.h"
 #include "toolchain/diagnostics/format_providers.h"
 #include "toolchain/sem_ir/constant.h"
+#include "toolchain/sem_ir/generic.h"
 #include "toolchain/sem_ir/ids.h"
+#include "toolchain/sem_ir/specific_interface.h"
 #include "toolchain/sem_ir/specific_named_constraint.h"
 #include "toolchain/sem_ir/type_info.h"
 #include "toolchain/sem_ir/typed_insts.h"
@@ -70,16 +72,47 @@ static auto NoteIncompleteNamedConstraint(
   }
 }
 
-template <typename T>
-  requires SameAsOneOf<T, SemIR::Interface, SemIR::NamedConstraint>
-static auto ForEachRequireImpls(
-    Context& context, const T& entity,
-    llvm::function_ref<auto(const SemIR::RequireImpls&)->void> f) -> void {
-  for (auto require_impls_id :
-       context.require_impls_blocks().Get(entity.require_impls_block_id)) {
-    const auto& require = context.require_impls().Get(require_impls_id);
-    f(require);
+static auto RequireCompleteFacetType(Context& context, SemIR::LocId loc_id,
+                                     const SemIR::FacetType& facet_type,
+                                     MakeDiagnosticBuilderFn diagnoser)
+    -> bool {
+  const auto& facet_type_info =
+      context.facet_types().Get(facet_type.facet_type_id);
+
+  for (auto extends : facet_type_info.extend_constraints) {
+    auto interface_id = extends.interface_id;
+    const auto& interface = context.interfaces().Get(interface_id);
+    if (!interface.is_complete()) {
+      if (diagnoser) {
+        auto builder = diagnoser();
+        NoteIncompleteInterface(context, interface_id, builder);
+        builder.Emit();
+      }
+      return false;
+    }
+    if (interface.generic_id.has_value()) {
+      ResolveSpecificDefinition(context, loc_id, extends.specific_id);
+    }
   }
+
+  for (auto extends : facet_type_info.extend_named_constraints) {
+    auto named_constraint_id = extends.named_constraint_id;
+    const auto& constraint =
+        context.named_constraints().Get(named_constraint_id);
+    if (!constraint.is_complete()) {
+      if (diagnoser) {
+        auto builder = diagnoser();
+        NoteIncompleteNamedConstraint(context, named_constraint_id, builder);
+        builder.Emit();
+      }
+      return false;
+    }
+    if (constraint.generic_id.has_value()) {
+      ResolveSpecificDefinition(context, loc_id, extends.specific_id);
+    }
+  }
+
+  return true;
 }
 
 namespace {
@@ -396,32 +429,9 @@ auto TypeCompleter::AddNestedIncompleteTypes(SemIR::Inst type_inst) -> bool {
       break;
     }
     case CARBON_KIND(SemIR::FacetType inst): {
-      auto identified_id =
-          RequireIdentifiedFacetType(*context_, inst, diagnoser_);
-      if (!identified_id.has_value()) {
+      if (!RequireCompleteFacetType(*context_, loc_id_, inst, diagnoser_)) {
         return false;
       }
-
-      const auto& identified =
-          context_->identified_facet_types().Get(identified_id);
-
-      for (auto req_interface : identified.required_interfaces()) {
-        auto interface_id = req_interface.interface_id;
-        const auto& interface = context_->interfaces().Get(interface_id);
-        if (!interface.is_complete()) {
-          if (diagnoser_) {
-            auto builder = diagnoser_();
-            NoteIncompleteInterface(*context_, interface_id, builder);
-            builder.Emit();
-          }
-          return false;
-        }
-
-        if (req_interface.specific_id.has_value()) {
-          ResolveSpecificDefinition(*context_, loc_id_,
-                                    req_interface.specific_id);
-        }
-      }
       break;
     }
 
@@ -844,23 +854,25 @@ auto RequireIdentifiedFacetType(Context& context,
     for (auto extend : facet_type_info.extend_named_constraints) {
       const auto& constraint =
           context.named_constraints().Get(extend.named_constraint_id);
-      ForEachRequireImpls(
-          context, constraint, [&](const SemIR::RequireImpls& require) {
-            if (facet_type_extends && require.extend_self) {
-              extend_facet_types.push_back(require.facet_type_id);
-            } else {
-              impls_facet_types.push_back(require.facet_type_id);
-            }
-          });
+      for (auto require_impls_id : context.require_impls_blocks().Get(
+               constraint.require_impls_block_id)) {
+        const auto& require = context.require_impls().Get(require_impls_id);
+        if (facet_type_extends && require.extend_self) {
+          extend_facet_types.push_back(require.facet_type_id);
+        } else {
+          impls_facet_types.push_back(require.facet_type_id);
+        }
+      }
     }
 
     for (auto impls : facet_type_info.self_impls_named_constraints) {
       const auto& constraint =
           context.named_constraints().Get(impls.named_constraint_id);
-      ForEachRequireImpls(context, constraint,
-                          [&](const SemIR::RequireImpls& require) {
-                            impls_facet_types.push_back(require.facet_type_id);
-                          });
+      for (auto require_impls_id : context.require_impls_blocks().Get(
+               constraint.require_impls_block_id)) {
+        const auto& require = context.require_impls().Get(require_impls_id);
+        impls_facet_types.push_back(require.facet_type_id);
+      }
     }
   }
 

+ 1 - 1
toolchain/diagnostics/diagnostic_kind.def

@@ -328,7 +328,6 @@ CARBON_DIAGNOSTIC_KIND(ExtendImplSelfAs)
 CARBON_DIAGNOSTIC_KIND(ExtendImplSelfAsDefault)
 CARBON_DIAGNOSTIC_KIND(ImplAccessMemberBeforeSet)
 CARBON_DIAGNOSTIC_KIND(ImplAsIncompleteFacetTypeDefinition)
-CARBON_DIAGNOSTIC_KIND(ImplAsIncompleteFacetTypeRewrites)
 CARBON_DIAGNOSTIC_KIND(ImplAsNonFacetType)
 CARBON_DIAGNOSTIC_KIND(ImplAsOutsideClass)
 CARBON_DIAGNOSTIC_KIND(ImplAssociatedConstantNeedsValue)
@@ -364,6 +363,7 @@ CARBON_DIAGNOSTIC_KIND(ImplLookupInUnidentifiedFacetType)
 CARBON_DIAGNOSTIC_KIND(RequireImplsExtendWithExplicitSelf)
 CARBON_DIAGNOSTIC_KIND(RequireImplsMissingFacetType)
 CARBON_DIAGNOSTIC_KIND(RequireImplsMissingSelf)
+CARBON_DIAGNOSTIC_KIND(RequireImplsIncompleteFacetType)
 CARBON_DIAGNOSTIC_KIND(RequireImplsUnidentifiedFacetType)
 CARBON_DIAGNOSTIC_KIND(RequireInWrongScope)
 

+ 2 - 0
toolchain/sem_ir/require_impls.h

@@ -23,6 +23,8 @@ struct RequireImpls : Printable<RequireImpls> {
   // Evaluates to the `FacetType` that the self-type must implement.
   TypeInstId facet_type_inst_id;
   // The `FacetTypeInfo` derived from the `facet_type_inst_id` instruction.
+  // TODO: Remove this, we need to use the inst to get a constant value in the
+  // appropriate specific.
   FacetTypeId facet_type_id;
   // If the facet type extends `Self`. When true, the `self_id` will be `Self`.
   bool extend_self;

+ 4 - 0
toolchain/sem_ir/stringify.cpp

@@ -814,6 +814,10 @@ auto StringifySpecific(const File& sem_ir, SpecificId specific_id)
           sem_ir.interfaces().Get(interface_decl.interface_id), specific_id);
       break;
     }
+    case CARBON_KIND(RequireImplsDecl _): {
+      step_stack.Push("require");
+      break;
+    }
     default: {
       // TODO: Include the specific arguments here.
       step_stack.PushInstId(generic.decl_id);