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

Explorer and toolchain changes to implement #2483 (#2707)

This PR is making two main changes to the Explorer and Toolchain:
- Replace the `is` keyword in `where SomeType is SomeInterface` with `impls`, so it is `where SomeType impls SomeInterface`
- Rewrite uses of the "impls" to something else to avoid, frequently "`impl` declarations" or "implementations", to avoid confusion with the `impls` keyword.

---------

Co-authored-by: Geoff Romer <gromer@google.com>
josh11b 3 лет назад
Родитель
Сommit
46503c0a9d
64 измененных файлов с 335 добавлено и 302 удалено
  1. 3 3
      common/fuzzing/carbon.proto
  2. 5 5
      common/fuzzing/proto_to_carbon.cpp
  3. 1 1
      explorer/ast/ast_rtti.txt
  4. 2 1
      explorer/ast/declaration.cpp
  5. 13 8
      explorer/ast/declaration.h
  6. 3 3
      explorer/ast/expression.cpp
  7. 15 11
      explorer/ast/expression.h
  8. 1 1
      explorer/ast/impl_binding.h
  9. 7 7
      explorer/ast/value.cpp
  10. 12 12
      explorer/ast/value.h
  11. 13 13
      explorer/data/prelude.carbon
  12. 8 8
      explorer/fuzzing/ast_to_proto.cpp
  13. 2 1
      explorer/fuzzing/fuzzer_corpus/26c2d5cf1d3f39a1f0fc16691f770713002312a0
  14. 2 2
      explorer/fuzzing/fuzzer_corpus/2d454cacd53c4ed55138382f919c3547d81059fd
  15. 2 1
      explorer/fuzzing/fuzzer_corpus/4e0c2238235281a56e0b58c3ec927a3466c8b1e4
  16. 2 1
      explorer/fuzzing/fuzzer_corpus/4ee954ee8c71e3023e3855608bd6c60185453505
  17. 2 1
      explorer/fuzzing/fuzzer_corpus/59f5bff3c89e6ae504001fd40e25570fa68f4816
  18. 2 1
      explorer/fuzzing/fuzzer_corpus/604e3189c3c6fdcd4ba5375a88614370264f92e1
  19. 2 1
      explorer/fuzzing/fuzzer_corpus/6d8efa516d912ed4fb3a51abe81181ac5a3ce7de
  20. 4 4
      explorer/fuzzing/fuzzer_corpus/8c82de66ed8c2c2e00ff9d0da8d299a7bc2e0a52
  21. 6 5
      explorer/fuzzing/fuzzer_corpus/91ac9c25f698c4efb6886c33ba330739e7087851
  22. 2 1
      explorer/fuzzing/fuzzer_corpus/abe990a35bad5c0ed6f66289dac8b310bccf732a
  23. 2 1
      explorer/fuzzing/fuzzer_corpus/b0104f7d6a22c98bb612f42cec045f64f0599507
  24. 2 1
      explorer/fuzzing/fuzzer_corpus/b6faa454160b04a71aebd4eefba1074e82f6b991
  25. 2 1
      explorer/fuzzing/fuzzer_corpus/c1dda40eae19225720932d324f3f0610f31ab471
  26. 2 1
      explorer/fuzzing/fuzzer_corpus/f69e3144cbc99fb1dc4d1c8f7a1547679ffeb93a
  27. 29 27
      explorer/interpreter/impl_scope.cpp
  28. 11 11
      explorer/interpreter/impl_scope.h
  29. 11 10
      explorer/interpreter/interpreter.cpp
  30. 1 1
      explorer/interpreter/matching_impl_set.cpp
  31. 2 2
      explorer/interpreter/matching_impl_set.h
  32. 1 1
      explorer/interpreter/resolve_control_flow.cpp
  33. 7 5
      explorer/interpreter/resolve_names.cpp
  34. 97 92
      explorer/interpreter/type_checker.cpp
  35. 16 16
      explorer/interpreter/type_checker.h
  36. 1 1
      explorer/interpreter/type_structure.cpp
  37. 2 2
      explorer/syntax/lexer.lpp
  38. 3 3
      explorer/syntax/parser.ypp
  39. 2 2
      explorer/testdata/assoc_const/impl_used_by_later_rewrite.carbon
  40. 5 5
      explorer/testdata/assoc_const/rewrite_interface_params.carbon
  41. 1 1
      explorer/testdata/constraint/dot_self_is_other.carbon
  42. 1 1
      explorer/testdata/constraint/fail_combine_equality.carbon
  43. 1 1
      explorer/testdata/constraint/fail_missing_member.carbon
  44. 2 2
      explorer/testdata/constraint/fail_where_impls_non_constraint.carbon
  45. 2 2
      explorer/testdata/constraint/fail_where_impls_non_type.carbon
  46. 2 2
      explorer/testdata/constraint/fail_where_non_type_impls.carbon
  47. 1 1
      explorer/testdata/constraint/nondependent_where.carbon
  48. 1 1
      explorer/testdata/constraint/qualified_lookup_in_where.carbon
  49. 1 1
      explorer/testdata/constraint/where_impls.carbon
  50. 1 1
      explorer/testdata/constraint/where_self.carbon
  51. 2 2
      explorer/testdata/impl/fail_unmet_impls_constraint.carbon
  52. 1 1
      explorer/testdata/impl/impls_constraint.carbon
  53. 1 1
      explorer/testdata/impl_match/fail_self_recurse.carbon
  54. 1 1
      explorer/testdata/impl_match/fail_self_recurse_without_match_first.carbon
  55. 1 1
      explorer/testdata/impl_match/fail_struct_recurse.carbon
  56. 3 3
      explorer/testdata/impl_match/fail_three_step_recurse.carbon
  57. 1 1
      explorer/testdata/impl_match/fail_tuple_recurse.carbon
  58. 1 1
      explorer/testdata/impl_match/self_recurse_with_match.carbon
  59. 1 1
      explorer/testdata/impl_match/self_recurse_with_match_first.carbon
  60. 1 1
      explorer/testdata/interface/fail_interface_missing_member.carbon
  61. 1 1
      explorer/testdata/name_lookup/class_fn_body_reorder.carbon
  62. 1 1
      explorer/testdata/name_lookup/fail_class_fn_use_before_declaration.carbon
  63. 1 1
      explorer/testdata/named_constraint/fail_impl_as_member_access.carbon
  64. 1 0
      toolchain/lexer/token_kind.def

+ 3 - 3
common/fuzzing/carbon.proto

@@ -134,7 +134,7 @@ message ArrayTypeLiteral {
   optional Expression size = 2;
 }
 
-message IsWhereClause {
+message ImplsWhereClause {
   optional Expression type = 1;
   optional Expression constraint = 2;
 }
@@ -151,7 +151,7 @@ message RewriteWhereClause {
 
 message WhereClause {
   oneof kind {
-    IsWhereClause is = 1;
+    ImplsWhereClause impls = 1;
     EqualsWhereClause equals = 2;
     RewriteWhereClause rewrite = 3;
   }
@@ -442,7 +442,7 @@ message ImplDeclaration {
 }
 
 message MatchFirstDeclaration {
-  repeated Declaration impls = 1;
+  repeated Declaration impl_declarations = 1;
 }
 
 message AliasDeclaration {

+ 5 - 5
common/fuzzing/proto_to_carbon.cpp

@@ -399,10 +399,10 @@ static auto ExpressionToCarbon(const Fuzzing::Expression& expression,
       for (const auto& clause : where.clauses()) {
         out << sep;
         switch (clause.kind_case()) {
-          case Fuzzing::WhereClause::kIs:
-            ExpressionToCarbon(clause.is().type(), out);
-            out << " is ";
-            ExpressionToCarbon(clause.is().constraint(), out);
+          case Fuzzing::WhereClause::kImpls:
+            ExpressionToCarbon(clause.impls().type(), out);
+            out << " impls ";
+            ExpressionToCarbon(clause.impls().constraint(), out);
             break;
           case Fuzzing::WhereClause::kEquals:
             ExpressionToCarbon(clause.equals().lhs(), out);
@@ -970,7 +970,7 @@ static auto DeclarationToCarbon(const Fuzzing::Declaration& declaration,
     case Fuzzing::Declaration::kMatchFirst: {
       const auto& match_first = declaration.match_first();
       out << "__match_first {\n";
-      for (const auto& impl : match_first.impls()) {
+      for (const auto& impl : match_first.impl_declarations()) {
         DeclarationToCarbon(impl, out);
         out << "\n";
       }

+ 1 - 1
explorer/ast/ast_rtti.txt

@@ -83,7 +83,7 @@ abstract class Expression : AstNode;
   class BuiltinConvertExpression : Expression;
   class UnimplementedExpression : Expression;
 abstract class WhereClause : AstNode;
-  class IsWhereClause : WhereClause;
+  class ImplsWhereClause : WhereClause;
   class EqualsWhereClause : WhereClause;
   class RewriteWhereClause : WhereClause;
 root class Element;

+ 2 - 1
explorer/ast/declaration.cpp

@@ -45,7 +45,8 @@ void Declaration::Print(llvm::raw_ostream& out) const {
       const auto& match_first_decl = cast<MatchFirstDeclaration>(*this);
       PrintID(out);
       out << " {\n";
-      for (Nonnull<const ImplDeclaration*> m : match_first_decl.impls()) {
+      for (Nonnull<const ImplDeclaration*> m :
+           match_first_decl.impl_declarations()) {
         out << *m;
       }
       out << "}\n";

+ 13 - 8
explorer/ast/declaration.h

@@ -943,26 +943,31 @@ class ImplDeclaration : public Declaration {
 
 class MatchFirstDeclaration : public Declaration {
  public:
-  MatchFirstDeclaration(SourceLocation source_loc,
-                        std::vector<Nonnull<ImplDeclaration*>> impls)
+  MatchFirstDeclaration(
+      SourceLocation source_loc,
+      std::vector<Nonnull<ImplDeclaration*>> impl_declarations)
       : Declaration(AstNodeKind::MatchFirstDeclaration, source_loc),
-        impls_(std::move(impls)) {}
+        impl_declarations_(std::move(impl_declarations)) {}
 
   explicit MatchFirstDeclaration(CloneContext& context,
                                  const MatchFirstDeclaration& other)
-      : Declaration(context, other), impls_(context.Clone(other.impls_)) {}
+      : Declaration(context, other),
+        impl_declarations_(context.Clone(other.impl_declarations_)) {}
 
   static auto classof(const AstNode* node) -> bool {
     return InheritsFromMatchFirstDeclaration(node->kind());
   }
 
-  auto impls() const -> llvm::ArrayRef<Nonnull<const ImplDeclaration*>> {
-    return impls_;
+  auto impl_declarations() const
+      -> llvm::ArrayRef<Nonnull<const ImplDeclaration*>> {
+    return impl_declarations_;
+  }
+  auto impl_declarations() -> llvm::ArrayRef<Nonnull<ImplDeclaration*>> {
+    return impl_declarations_;
   }
-  auto impls() -> llvm::ArrayRef<Nonnull<ImplDeclaration*>> { return impls_; }
 
  private:
-  std::vector<Nonnull<ImplDeclaration*>> impls_;
+  std::vector<Nonnull<ImplDeclaration*>> impl_declarations_;
 };
 
 class AliasDeclaration : public Declaration {

+ 3 - 3
explorer/ast/expression.cpp

@@ -398,9 +398,9 @@ WhereClause::~WhereClause() = default;
 
 void WhereClause::Print(llvm::raw_ostream& out) const {
   switch (kind()) {
-    case WhereClauseKind::IsWhereClause: {
-      const auto& clause = cast<IsWhereClause>(*this);
-      out << clause.type() << " is " << clause.constraint();
+    case WhereClauseKind::ImplsWhereClause: {
+      const auto& clause = cast<ImplsWhereClause>(*this);
+      out << clause.type() << " impls " << clause.constraint();
       break;
     }
     case WhereClauseKind::EqualsWhereClause: {

+ 15 - 11
explorer/ast/expression.h

@@ -224,8 +224,8 @@ class IdentifierExpression : public Expression {
 // `A`, but with type `type`.
 //
 // In a `where` binding, the type of `.Self` is the constraint preceding the
-// `where` keyword. For example, in `Foo where .Result is Bar(.Self)`, the type
-// of `.Self` is `Foo`.
+// `where` keyword. For example, in `Foo where .Result impls Bar(.Self)`, the
+// type of `.Self` is `Foo`.
 class DotSelfExpression : public Expression {
  public:
   explicit DotSelfExpression(SourceLocation source_loc)
@@ -747,7 +747,9 @@ class CallExpression : public Expression {
   // Maps each of `function`'s impl bindings to a witness.
   // Should not be called before typechecking, or if `function` is not
   // a generic function.
-  auto impls() const -> const ImplWitnessMap& { return bindings_.witnesses(); }
+  auto witnesses() const -> const ImplWitnessMap& {
+    return bindings_.witnesses();
+  }
 
   // Can only be called by type-checking, if a conversion was required.
   void set_argument(Nonnull<Expression*> argument) { argument_ = argument; }
@@ -982,25 +984,27 @@ class WhereClause : public AstNode {
       : AstNode(context, other) {}
 };
 
-// An `is` where clause.
+// An `impls` where clause.
 //
-// For example, `ConstraintA where .Type is ConstraintB` requires that the
+// For example, `ConstraintA where .Type impls ConstraintB` requires that the
 // associated type `.Type` implements the constraint `ConstraintB`.
-class IsWhereClause : public WhereClause {
+class ImplsWhereClause : public WhereClause {
  public:
-  explicit IsWhereClause(SourceLocation source_loc, Nonnull<Expression*> type,
-                         Nonnull<Expression*> constraint)
-      : WhereClause(WhereClauseKind::IsWhereClause, source_loc),
+  explicit ImplsWhereClause(SourceLocation source_loc,
+                            Nonnull<Expression*> type,
+                            Nonnull<Expression*> constraint)
+      : WhereClause(WhereClauseKind::ImplsWhereClause, source_loc),
         type_(type),
         constraint_(constraint) {}
 
-  explicit IsWhereClause(CloneContext& context, const IsWhereClause& other)
+  explicit ImplsWhereClause(CloneContext& context,
+                            const ImplsWhereClause& other)
       : WhereClause(context, other),
         type_(context.Clone(other.type_)),
         constraint_(context.Clone(other.constraint_)) {}
 
   static auto classof(const AstNode* node) {
-    return InheritsFromIsWhereClause(node->kind());
+    return InheritsFromImplsWhereClause(node->kind());
   }
 
   auto type() const -> const Expression& { return *type_; }

+ 1 - 1
explorer/ast/impl_binding.h

@@ -23,7 +23,7 @@ class GenericBinding;
 // (`BindingPattern`) there is no explicit syntax that corresponds to
 // an `ImplBinding`, so they are not created during parsing. Instances
 // of `ImplBinding` are created during type checking, when processing
-// a type parameter (a `GenericBinding`), or an `is` requirement in
+// a type parameter (a `GenericBinding`), or an `impls` requirement in
 // a `where` clause.
 class ImplBinding : public AstNode {
  public:

+ 7 - 7
explorer/ast/value.cpp

@@ -597,10 +597,10 @@ void Value::Print(llvm::raw_ostream& out) const {
         out << "." << *GetName(rewrite.constant->constant())
             << ") = " << *rewrite.unconverted_replacement;
       }
-      for (const ImplConstraint& impl : constraint.impl_constraints()) {
+      for (const ImplsConstraint& impl : constraint.impls_constraints()) {
         // TODO: Skip cases where `impl.type` is `.Self` and the interface is
         // in `lookup_contexts()`.
-        out << sep << *impl.type << " is " << *impl.interface;
+        out << sep << *impl.type << " impls " << *impl.interface;
       }
       for (const EqualityConstraint& equality :
            constraint.equality_constraints()) {
@@ -809,17 +809,17 @@ auto TypeEqual(Nonnull<const Value*> t1, Nonnull<const Value*> t2,
     case Value::Kind::ConstraintType: {
       const auto& constraint1 = cast<ConstraintType>(*t1);
       const auto& constraint2 = cast<ConstraintType>(*t2);
-      if (constraint1.impl_constraints().size() !=
-              constraint2.impl_constraints().size() ||
+      if (constraint1.impls_constraints().size() !=
+              constraint2.impls_constraints().size() ||
           constraint1.equality_constraints().size() !=
               constraint2.equality_constraints().size() ||
           constraint1.lookup_contexts().size() !=
               constraint2.lookup_contexts().size()) {
         return false;
       }
-      for (size_t i = 0; i < constraint1.impl_constraints().size(); ++i) {
-        const auto& impl1 = constraint1.impl_constraints()[i];
-        const auto& impl2 = constraint2.impl_constraints()[i];
+      for (size_t i = 0; i < constraint1.impls_constraints().size(); ++i) {
+        const auto& impl1 = constraint1.impls_constraints()[i];
+        const auto& impl2 = constraint2.impls_constraints()[i];
         if (!TypeEqual(impl1.type, impl2.type, equality_ctx) ||
             !TypeEqual(impl1.interface, impl2.interface, equality_ctx)) {
           return false;

+ 12 - 12
explorer/ast/value.h

@@ -663,7 +663,7 @@ class FunctionType : public Value {
       -> llvm::ArrayRef<Nonnull<const GenericBinding*>> {
     return deduced_bindings_;
   }
-  // The bindings for the witness tables (impls) required by the
+  // The bindings for the impl witness tables required by the
   // bounds on the type parameters of the generic function.
   auto impl_bindings() const -> llvm::ArrayRef<Nonnull<const ImplBinding*>> {
     return impl_bindings_;
@@ -927,7 +927,7 @@ class NamedConstraintType : public Value {
 };
 
 // A constraint that requires implementation of an interface.
-struct ImplConstraint {
+struct ImplsConstraint {
   template <typename F>
   auto Decompose(F f) const {
     return f(type, interface);
@@ -1037,14 +1037,14 @@ class ConstraintType : public Value {
  public:
   explicit ConstraintType(
       Nonnull<const GenericBinding*> self_binding,
-      std::vector<ImplConstraint> impl_constraints,
+      std::vector<ImplsConstraint> impls_constraints,
       std::vector<IntrinsicConstraint> intrinsic_constraints,
       std::vector<EqualityConstraint> equality_constraints,
       std::vector<RewriteConstraint> rewrite_constraints,
       std::vector<LookupContext> lookup_contexts)
       : Value(Kind::ConstraintType),
         self_binding_(self_binding),
-        impl_constraints_(std::move(impl_constraints)),
+        impls_constraints_(std::move(impls_constraints)),
         intrinsic_constraints_(std::move(intrinsic_constraints)),
         equality_constraints_(std::move(equality_constraints)),
         rewrite_constraints_(std::move(rewrite_constraints)),
@@ -1056,7 +1056,7 @@ class ConstraintType : public Value {
 
   template <typename F>
   auto Decompose(F f) const {
-    return f(self_binding_, impl_constraints_, intrinsic_constraints_,
+    return f(self_binding_, impls_constraints_, intrinsic_constraints_,
              equality_constraints_, rewrite_constraints_, lookup_contexts_);
   }
 
@@ -1064,8 +1064,8 @@ class ConstraintType : public Value {
     return self_binding_;
   }
 
-  auto impl_constraints() const -> llvm::ArrayRef<ImplConstraint> {
-    return impl_constraints_;
+  auto impls_constraints() const -> llvm::ArrayRef<ImplsConstraint> {
+    return impls_constraints_;
   }
 
   auto intrinsic_constraints() const -> llvm::ArrayRef<IntrinsicConstraint> {
@@ -1097,7 +1097,7 @@ class ConstraintType : public Value {
 
  private:
   Nonnull<const GenericBinding*> self_binding_;
-  std::vector<ImplConstraint> impl_constraints_;
+  std::vector<ImplsConstraint> impls_constraints_;
   std::vector<IntrinsicConstraint> intrinsic_constraints_;
   std::vector<EqualityConstraint> equality_constraints_;
   std::vector<RewriteConstraint> rewrite_constraints_;
@@ -1175,7 +1175,7 @@ class BindingWitness : public Witness {
 };
 
 // A witness for a constraint type, expressed as a tuple of witnesses for the
-// individual impl constraints in the constraint type.
+// individual impls constraints in the constraint type.
 class ConstraintWitness : public Witness {
  public:
   explicit ConstraintWitness(std::vector<Nonnull<const Witness*>> witnesses)
@@ -1198,11 +1198,11 @@ class ConstraintWitness : public Witness {
   std::vector<Nonnull<const Witness*>> witnesses_;
 };
 
-// A witness for an impl constraint in a constraint type, expressed in terms of
+// A witness for an impls constraint in a constraint type, expressed in terms of
 // a symbolic witness for the constraint type.
 class ConstraintImplWitness : public Witness {
  public:
-  // Make a witness for the given impl_constraint of the given `ConstraintType`
+  // Make a witness for the given impls_constraint of the given `ConstraintType`
   // witness. If we're indexing into a known tuple of witnesses, pull out the
   // element.
   static auto Make(Nonnull<Arena*> arena, Nonnull<const Witness*> witness,
@@ -1239,7 +1239,7 @@ class ConstraintImplWitness : public Witness {
     return constraint_witness_;
   }
 
-  // Get the index of the impl constraint within the constraint type.
+  // Get the index of the impls constraint within the constraint type.
   auto index() const -> int { return index_; }
 
  private:

+ 13 - 13
explorer/data/prelude.carbon

@@ -70,8 +70,8 @@ __match_first {
   }
 
   // A tuple explicitly converts to another tuple if all its elements do. Note
-  // that this fully overlaps with the previous set of impls for the case where
-  // an implicit conversion is possible.
+  // that this fully overlaps with the previous set of impl declarations for
+  // the case where an implicit conversion is possible.
   impl forall [U1:! type, T1:! As(U1)]
       (T1,) as As((U1,)) {
     fn Convert[self: Self]() -> (U1,) {
@@ -389,7 +389,7 @@ constraint Mod {
   extends ModWith(Self) where .Result = Self;
 }
 
-// Note, these impls use the builtin addition for i32.
+// Note, these impl declarations use the builtin addition for i32.
 external impl i32 as Negate where .Result = i32 {
   fn Op[self: i32]() -> i32 { return -self; }
 }
@@ -571,70 +571,70 @@ impl forall [T:! type, U:! ImplicitAs(T)]
 }
 
 // TODO: Should `AddWith(U) & AssignWith(.Self.(AddWith(U).Result))` work?
-impl forall [U:! type, T:! AddWith(U) where .Self is AssignWith(.Self.Result)]
+impl forall [U:! type, T:! AddWith(U) where .Self impls AssignWith(.Self.Result)]
      T as AddAssignWith(U) {
   fn Op[addr self: Self*](other: U) {
     *self = *self + other;
   }
 }
 
-impl forall [U:! type, T:! SubWith(U) where .Self is AssignWith(.Self.Result)]
+impl forall [U:! type, T:! SubWith(U) where .Self impls AssignWith(.Self.Result)]
      T as SubAssignWith(U) {
   fn Op[addr self: Self*](other: U) {
     *self = *self - other;
   }
 }
 
-impl forall [U:! type, T:! MulWith(U) where .Self is AssignWith(.Self.Result)]
+impl forall [U:! type, T:! MulWith(U) where .Self impls AssignWith(.Self.Result)]
      T as MulAssignWith(U) {
   fn Op[addr self: Self*](other: U) {
     *self = *self * other;
   }
 }
 
-impl forall [U:! type, T:! DivWith(U) where .Self is AssignWith(.Self.Result)]
+impl forall [U:! type, T:! DivWith(U) where .Self impls AssignWith(.Self.Result)]
      T as DivAssignWith(U) {
   fn Op[addr self: Self*](other: U) {
     *self = *self / other;
   }
 }
 
-impl forall [U:! type, T:! ModWith(U) where .Self is AssignWith(.Self.Result)]
+impl forall [U:! type, T:! ModWith(U) where .Self impls AssignWith(.Self.Result)]
      T as ModAssignWith(U) {
   fn Op[addr self: Self*](other: U) {
     *self = *self % other;
   }
 }
 
-impl forall [U:! type, T:! BitAndWith(U) where .Self is AssignWith(.Self.Result)]
+impl forall [U:! type, T:! BitAndWith(U) where .Self impls AssignWith(.Self.Result)]
      T as BitAndAssignWith(U) {
   fn Op[addr self: Self*](other: U) {
     *self = *self & other;
   }
 }
 
-impl forall [U:! type, T:! BitOrWith(U) where .Self is AssignWith(.Self.Result)]
+impl forall [U:! type, T:! BitOrWith(U) where .Self impls AssignWith(.Self.Result)]
      T as BitOrAssignWith(U) {
   fn Op[addr self: Self*](other: U) {
     *self = *self | other;
   }
 }
 
-impl forall [U:! type, T:! BitXorWith(U) where .Self is AssignWith(.Self.Result)]
+impl forall [U:! type, T:! BitXorWith(U) where .Self impls AssignWith(.Self.Result)]
      T as BitXorAssignWith(U) {
   fn Op[addr self: Self*](other: U) {
     *self = *self ^ other;
   }
 }
 
-impl forall [U:! type, T:! LeftShiftWith(U) where .Self is AssignWith(.Self.Result)]
+impl forall [U:! type, T:! LeftShiftWith(U) where .Self impls AssignWith(.Self.Result)]
      T as LeftShiftAssignWith(U) {
   fn Op[addr self: Self*](other: U) {
     *self = *self << other;
   }
 }
 
-impl forall [U:! type, T:! RightShiftWith(U) where .Self is AssignWith(.Self.Result)]
+impl forall [U:! type, T:! RightShiftWith(U) where .Self impls AssignWith(.Self.Result)]
      T as RightShiftAssignWith(U) {
   fn Op[addr self: Self*](other: U) {
     *self = *self >> other;

+ 8 - 8
explorer/fuzzing/ast_to_proto.cpp

@@ -256,12 +256,12 @@ static auto ExpressionToProto(const Expression& expression)
       for (const WhereClause* where : where.clauses()) {
         Fuzzing::WhereClause clause_proto;
         switch (where->kind()) {
-          case WhereClauseKind::IsWhereClause: {
-            auto* is_proto = clause_proto.mutable_is();
-            *is_proto->mutable_type() =
-                ExpressionToProto(cast<IsWhereClause>(where)->type());
-            *is_proto->mutable_constraint() =
-                ExpressionToProto(cast<IsWhereClause>(where)->constraint());
+          case WhereClauseKind::ImplsWhereClause: {
+            auto* impls_proto = clause_proto.mutable_impls();
+            *impls_proto->mutable_type() =
+                ExpressionToProto(cast<ImplsWhereClause>(where)->type());
+            *impls_proto->mutable_constraint() =
+                ExpressionToProto(cast<ImplsWhereClause>(where)->constraint());
             break;
           }
           case WhereClauseKind::EqualsWhereClause: {
@@ -845,8 +845,8 @@ static auto DeclarationToProto(const Declaration& declaration)
     case DeclarationKind::MatchFirstDeclaration: {
       const auto& match_first = cast<MatchFirstDeclaration>(declaration);
       auto* match_first_proto = declaration_proto.mutable_match_first();
-      for (const auto* impl : match_first.impls()) {
-        *match_first_proto->add_impls() = DeclarationToProto(*impl);
+      for (const auto* impl : match_first.impl_declarations()) {
+        *match_first_proto->add_impl_declarations() = DeclarationToProto(*impl);
       }
       break;
     }

+ 2 - 1
explorer/fuzzing/fuzzer_corpus/a39216150512f65b529af0981e77f61b3301ff22 → explorer/fuzzing/fuzzer_corpus/26c2d5cf1d3f39a1f0fc16691f770713002312a0

@@ -32,7 +32,7 @@ compilation_unit {
             }
           }
           clauses {
-            is {
+            impls {
               type {
                 int_type_literal {
                 }
@@ -76,3 +76,4 @@ compilation_unit {
     }
   }
 }
+

+ 2 - 2
explorer/fuzzing/fuzzer_corpus/1d5c57e26f96532fca3fab7cf9474049a8cd71b7 → explorer/fuzzing/fuzzer_corpus/2d454cacd53c4ed55138382f919c3547d81059fd

@@ -30,7 +30,7 @@ compilation_unit {
   }
   declarations {
     match_first {
-      impls {
+      impl_declarations {
         impl {
           kind: ExternalImpl
           impl_type {
@@ -69,7 +69,7 @@ compilation_unit {
           }
         }
       }
-      impls {
+      impl_declarations {
         impl {
           kind: ExternalImpl
           impl_type {

+ 2 - 1
explorer/fuzzing/fuzzer_corpus/e581bd5064e962288e5e78d9938def1e40feb12b → explorer/fuzzing/fuzzer_corpus/4e0c2238235281a56e0b58c3ec927a3466c8b1e4

@@ -82,7 +82,7 @@ compilation_unit {
             }
           }
           clauses {
-            is {
+            impls {
               type {
                 int_type_literal {
                 }
@@ -239,3 +239,4 @@ compilation_unit {
     }
   }
 }
+

+ 2 - 1
explorer/fuzzing/fuzzer_corpus/1cffd9bfbbba52a53c5f886563683d230d02ad80 → explorer/fuzzing/fuzzer_corpus/4ee954ee8c71e3023e3855608bd6c60185453505

@@ -66,7 +66,7 @@ compilation_unit {
             }
           }
           clauses {
-            is {
+            impls {
               type {
                 designator {
                   name: "Self"
@@ -393,3 +393,4 @@ compilation_unit {
     }
   }
 }
+

+ 2 - 1
explorer/fuzzing/fuzzer_corpus/03527ef9005c1d05b8bf667521a324a622e81ba9 → explorer/fuzzing/fuzzer_corpus/59f5bff3c89e6ae504001fd40e25570fa68f4816

@@ -148,7 +148,7 @@ compilation_unit {
                   }
                 }
                 clauses {
-                  is {
+                  impls {
                     type {
                       designator {
                         name: "Self"
@@ -323,3 +323,4 @@ compilation_unit {
     }
   }
 }
+

+ 2 - 1
explorer/fuzzing/fuzzer_corpus/2ded3a52f879950b9f7c70626708f433c4e1af2a → explorer/fuzzing/fuzzer_corpus/604e3189c3c6fdcd4ba5375a88614370264f92e1

@@ -23,7 +23,7 @@ compilation_unit {
             }
           }
           clauses {
-            is {
+            impls {
               type {
                 int_literal {
                   value: 4
@@ -68,3 +68,4 @@ compilation_unit {
     }
   }
 }
+

+ 2 - 1
explorer/fuzzing/fuzzer_corpus/990a34d604db8cb646b94ed74212a06796bf6639 → explorer/fuzzing/fuzzer_corpus/6d8efa516d912ed4fb3a51abe81181ac5a3ce7de

@@ -75,7 +75,7 @@ compilation_unit {
                     }
                   }
                   clauses {
-                    is {
+                    impls {
                       type {
                         int_type_literal {
                         }
@@ -300,3 +300,4 @@ compilation_unit {
     }
   }
 }
+

+ 4 - 4
explorer/fuzzing/fuzzer_corpus/db160c03d69c93b692d6f4e2ef1c15f0bcdb7f8f → explorer/fuzzing/fuzzer_corpus/8c82de66ed8c2c2e00ff9d0da8d299a7bc2e0a52

@@ -49,7 +49,7 @@ compilation_unit {
   }
   declarations {
     match_first {
-      impls {
+      impl_declarations {
         impl {
           kind: ExternalImpl
           impl_type {
@@ -91,7 +91,7 @@ compilation_unit {
           }
         }
       }
-      impls {
+      impl_declarations {
         impl {
           kind: ExternalImpl
           impl_type {
@@ -133,7 +133,7 @@ compilation_unit {
           }
         }
       }
-      impls {
+      impl_declarations {
         impl {
           kind: ExternalImpl
           impl_type {
@@ -175,7 +175,7 @@ compilation_unit {
           }
         }
       }
-      impls {
+      impl_declarations {
         impl {
           kind: ExternalImpl
           impl_type {

+ 6 - 5
explorer/fuzzing/fuzzer_corpus/31f34f507f6d8c70cc7934fc807d90e32031ecfb → explorer/fuzzing/fuzzer_corpus/91ac9c25f698c4efb6886c33ba330739e7087851

@@ -162,7 +162,7 @@ compilation_unit {
               }
             }
             clauses {
-              is {
+              impls {
                 type {
                   designator {
                     name: "Self"
@@ -204,7 +204,7 @@ compilation_unit {
               }
             }
             clauses {
-              is {
+              impls {
                 type {
                   designator {
                     name: "Self"
@@ -246,7 +246,7 @@ compilation_unit {
               }
             }
             clauses {
-              is {
+              impls {
                 type {
                   designator {
                     name: "Self"
@@ -288,7 +288,7 @@ compilation_unit {
               }
             }
             clauses {
-              is {
+              impls {
                 type {
                   designator {
                     name: "Self"
@@ -330,7 +330,7 @@ compilation_unit {
               }
             }
             clauses {
-              is {
+              impls {
                 type {
                   designator {
                     name: "Self"
@@ -890,3 +890,4 @@ compilation_unit {
     }
   }
 }
+

+ 2 - 1
explorer/fuzzing/fuzzer_corpus/84467b7cbaaa2931dc227bb0e46c3adac0ede663 → explorer/fuzzing/fuzzer_corpus/abe990a35bad5c0ed6f66289dac8b310bccf732a

@@ -23,7 +23,7 @@ compilation_unit {
             }
           }
           clauses {
-            is {
+            impls {
               type {
                 int_type_literal {
                 }
@@ -66,3 +66,4 @@ compilation_unit {
     }
   }
 }
+

+ 2 - 1
explorer/fuzzing/fuzzer_corpus/d47bc23011a4973b678586a56ebae479f4dd39ec → explorer/fuzzing/fuzzer_corpus/b0104f7d6a22c98bb612f42cec045f64f0599507

@@ -23,7 +23,7 @@ compilation_unit {
             }
           }
           clauses {
-            is {
+            impls {
               type {
                 int_type_literal {
                 }
@@ -67,3 +67,4 @@ compilation_unit {
     }
   }
 }
+

+ 2 - 1
explorer/fuzzing/fuzzer_corpus/169f839edd28aed284d4b38125e1833f73edac02 → explorer/fuzzing/fuzzer_corpus/b6faa454160b04a71aebd4eefba1074e82f6b991

@@ -208,7 +208,7 @@ compilation_unit {
               }
             }
             clauses {
-              is {
+              impls {
                 type {
                   designator {
                     name: "Self"
@@ -370,3 +370,4 @@ compilation_unit {
     }
   }
 }
+

+ 2 - 1
explorer/fuzzing/fuzzer_corpus/79f09fae3aeb20dfc1e988e2fcbd1bff13db295f → explorer/fuzzing/fuzzer_corpus/c1dda40eae19225720932d324f3f0610f31ab471

@@ -52,7 +52,7 @@ compilation_unit {
               }
             }
             clauses {
-              is {
+              impls {
                 type {
                   designator {
                     name: "Self"
@@ -245,3 +245,4 @@ compilation_unit {
     }
   }
 }
+

+ 2 - 1
explorer/fuzzing/fuzzer_corpus/9e19f13bb23a93ba4f740a11563c2246fee796be → explorer/fuzzing/fuzzer_corpus/f69e3144cbc99fb1dc4d1c8f7a1547679ffeb93a

@@ -167,7 +167,7 @@ compilation_unit {
             }
           }
           clauses {
-            is {
+            impls {
               type {
                 designator {
                   name: "Self"
@@ -476,3 +476,4 @@ compilation_unit {
     }
   }
 }
+

+ 29 - 27
explorer/interpreter/impl_scope.cpp

@@ -32,7 +32,7 @@ void ImplScope::Add(Nonnull<const Value*> iface,
     CARBON_CHECK(!sort_key)
         << "should only be given a sort key for an impl of an interface";
     // The caller should have substituted `.Self` for `type` already.
-    Add(constraint->impl_constraints(), deduced, impl_bindings, witness,
+    Add(constraint->impls_constraints(), deduced, impl_bindings, witness,
         type_checker);
     // A parameterized impl declaration doesn't contribute any equality
     // constraints to the scope. Instead, we'll resolve the equality
@@ -46,30 +46,32 @@ void ImplScope::Add(Nonnull<const Value*> iface,
     return;
   }
 
-  Impl new_impl = {.interface = cast<InterfaceType>(iface),
-                   .deduced = deduced,
-                   .type = type,
-                   .impl_bindings = impl_bindings,
-                   .witness = witness,
-                   .sort_key = std::move(sort_key)};
+  ImplFact new_impl = {.interface = cast<InterfaceType>(iface),
+                       .deduced = deduced,
+                       .type = type,
+                       .impl_bindings = impl_bindings,
+                       .witness = witness,
+                       .sort_key = std::move(sort_key)};
 
   // Find the first impl that's more specific than this one, and place this
   // impl right before it. This keeps the impls with the same type structure
   // sorted in lexical order, which is important for `match_first` semantics.
-  auto insert_pos = std::upper_bound(
-      impls_.begin(), impls_.end(), new_impl,
-      [](const Impl& a, const Impl& b) { return a.sort_key < b.sort_key; });
+  auto insert_pos =
+      std::upper_bound(impl_facts_.begin(), impl_facts_.end(), new_impl,
+                       [](const ImplFact& a, const ImplFact& b) {
+                         return a.sort_key < b.sort_key;
+                       });
 
-  impls_.insert(insert_pos, std::move(new_impl));
+  impl_facts_.insert(insert_pos, std::move(new_impl));
 }
 
-void ImplScope::Add(llvm::ArrayRef<ImplConstraint> impls,
+void ImplScope::Add(llvm::ArrayRef<ImplsConstraint> impls_constraints,
                     llvm::ArrayRef<Nonnull<const GenericBinding*>> deduced,
                     llvm::ArrayRef<Nonnull<const ImplBinding*>> impl_bindings,
                     Nonnull<const Witness*> witness,
                     const TypeChecker& type_checker) {
-  for (size_t i = 0; i != impls.size(); ++i) {
-    ImplConstraint impl = impls[i];
+  for (size_t i = 0; i != impls_constraints.size(); ++i) {
+    ImplsConstraint impl = impls_constraints[i];
     Add(impl.interface, deduced, impl.type, impl_bindings,
         type_checker.MakeConstraintWitnessAccess(witness, i), type_checker);
   }
@@ -129,18 +131,18 @@ auto ImplScope::TryResolve(Nonnull<const Value*> constraint_type,
   }
   if (const auto* constraint = dyn_cast<ConstraintType>(constraint_type)) {
     std::vector<Nonnull<const Witness*>> witnesses;
-    for (auto impl : constraint->impl_constraints()) {
-      // Note that later impl constraints can refer to earlier impl constraints
-      // via impl bindings. For example, in
-      //   `C where .Self.AssocType is D`,
-      // ... the `.Self.AssocType is D` constraint refers to the `.Self is C`
-      // constraint when naming `AssocType`. So incrementally build up a
-      // partial constraint witness as we go.
+    for (auto impl : constraint->impls_constraints()) {
+      // Note that later impls constraints can refer to earlier impls
+      // constraints via impl bindings. For example, in
+      //   `C where .Self.AssocType impls D`,
+      // ... the `.Self.AssocType impls D` constraint refers to the
+      // `.Self impls C` constraint when naming `AssocType`. So incrementally
+      // build up a partial constraint witness as we go.
       std::optional<Nonnull<const Witness*>> witness;
       if (constraint->self_binding()->impl_binding()) {
         // Note, this is a partial impl binding covering only the impl
-        // constraints that we've already seen. Earlier impl constraints should
-        // not be able to refer to impl bindings for later impl constraints.
+        // constraints that we've already seen. Earlier impls constraints should
+        // not be able to refer to impl bindings for later impls constraints.
         witness = type_checker.MakeConstraintWitness(witnesses);
       }
       Bindings local_bindings = bindings;
@@ -382,9 +384,9 @@ auto ImplScope::TryResolveInterfaceHere(
     const TypeChecker& type_checker) const
     -> ErrorOr<std::optional<ResolveResult>> {
   std::optional<ResolveResult> result = std::nullopt;
-  for (const Impl& impl : impls_) {
+  for (const ImplFact& impl : impl_facts_) {
     // If we've passed the final impl with a sort key matching our best impl,
-    // all further impls are worse and don't need to be checked.
+    // all further are worse and don't need to be checked.
     if (result && result->impl->sort_key < impl.sort_key) {
       break;
     }
@@ -417,9 +419,9 @@ auto ImplScope::TryResolveInterfaceHere(
 
 // TODO: Add indentation when printing the parents.
 void ImplScope::Print(llvm::raw_ostream& out) const {
-  out << "impls: ";
+  out << "impl declarations: ";
   llvm::ListSeparator sep;
-  for (const Impl& impl : impls_) {
+  for (const ImplFact& impl : impl_facts_) {
     out << sep << *(impl.type) << " as " << *(impl.interface);
     if (impl.sort_key) {
       out << " " << *impl.sort_key;

+ 11 - 11
explorer/interpreter/impl_scope.h

@@ -16,15 +16,15 @@ class TypeChecker;
 // The `ImplScope` class is responsible for mapping a type and
 // interface to the location of the witness table for the `impl` for
 // that type and interface.  A scope may have parent scopes, whose
-// impls will also be visible in the child scope.
+// implementations will also be visible in the child scope.
 //
 // There is typically one instance of `ImplScope` class per scope
-// because the impls that are visible for a given type and interface
-// can vary from scope to scope. For example, consider the `bar` and
-// `baz` methods in the following class C and nested class D.
+// because the implementationss that are visible for a given type and
+// interface can vary from scope to scope. For example, consider the
+// `bar` and `baz` methods in the following class C and nested class D.
 //
 //     class C(U:! type, T:! type)  {
-//       class D(V:! type where U is Fooable(T)) {
+//       class D(V:! type where U impls Fooable(T)) {
 //         fn bar[self: Self](x: U, y : T) -> T{
 //           return x.foo(y)
 //         }
@@ -43,7 +43,7 @@ class TypeChecker;
 // scope.
 class ImplScope {
  public:
-  // The `Impl` struct is a key-value pair where the key is the
+  // The `ImplFact` struct is a key-value pair where the key is the
   // combination of a type and an interface, e.g., `List` and `Container`,
   // and the value is the result of statically resolving to the `impl`
   // for `List` as `Container`, which is an `Expression` that produces
@@ -54,7 +54,7 @@ class ImplScope {
   // later are impl bindings, that is, parameters for witnesses. In this case,
   // `sort_key` indicates the order in which this impl should be considered
   // relative to other matching impls.
-  struct Impl {
+  struct ImplFact {
     Nonnull<const InterfaceType*> interface;
     std::vector<Nonnull<const GenericBinding*>> deduced;
     Nonnull<const Value*> type;
@@ -66,7 +66,7 @@ class ImplScope {
   // Internal type used to represent the result of resolving a lookup in a
   // particular impl scope.
   struct ResolveResult {
-    Nonnull<const Impl*> impl;
+    Nonnull<const ImplFact*> impl;
     Nonnull<const Witness*> witness;
   };
 
@@ -89,10 +89,10 @@ class ImplScope {
            llvm::ArrayRef<Nonnull<const ImplBinding*>> impl_bindings,
            Nonnull<const Witness*> witness, const TypeChecker& type_checker,
            std::optional<TypeStructureSortKey> sort_key = std::nullopt);
-  // Adds a list of impl constraints from a constraint type into scope. Any
+  // Adds a list of impls constraints from a constraint type into scope. Any
   // references to `.Self` are expected to have already been substituted for
   // the type implementing the constraint.
-  void Add(llvm::ArrayRef<ImplConstraint> impls,
+  void Add(llvm::ArrayRef<ImplsConstraint> impls_constraints,
            llvm::ArrayRef<Nonnull<const GenericBinding*>> deduced,
            llvm::ArrayRef<Nonnull<const ImplBinding*>> impl_bindings,
            Nonnull<const Witness*> witness, const TypeChecker& type_checker);
@@ -176,7 +176,7 @@ class ImplScope {
                                const TypeChecker& type_checker) const
       -> ErrorOr<std::optional<ResolveResult>>;
 
-  std::vector<Impl> impls_;
+  std::vector<ImplFact> impl_facts_;
   std::vector<Nonnull<const EqualityConstraint*>> equalities_;
   std::optional<Nonnull<const ImplScope*>> parent_scope_;
 };

+ 11 - 10
explorer/interpreter/interpreter.cpp

@@ -1355,7 +1355,7 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
     }
     case ExpressionKind::CallExpression: {
       const auto& call = cast<CallExpression>(exp);
-      unsigned int num_impls = call.impls().size();
+      unsigned int num_witnesses = call.witnesses().size();
       if (act.pos() == 0) {
         //    { {e1(e2) :: C, E, F} :: S, H}
         // -> { {e1 :: [](e2) :: C, E, F} :: S, H}
@@ -1366,31 +1366,32 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
         // -> { { e :: v([]) :: C, E, F} :: S, H}
         return todo_.Spawn(
             std::make_unique<ExpressionAction>(&call.argument()));
-      } else if (num_impls > 0 && act.pos() < 2 + static_cast<int>(num_impls)) {
-        auto iter = call.impls().begin();
+      } else if (num_witnesses > 0 &&
+                 act.pos() < 2 + static_cast<int>(num_witnesses)) {
+        auto iter = call.witnesses().begin();
         std::advance(iter, act.pos() - 2);
         return todo_.Spawn(
             std::make_unique<WitnessAction>(cast<Witness>(iter->second)));
-      } else if (act.pos() == 2 + static_cast<int>(num_impls)) {
+      } else if (act.pos() == 2 + static_cast<int>(num_witnesses)) {
         //    { { v2 :: v1([]) :: C, E, F} :: S, H}
         // -> { {C',E',F'} :: {C, E, F} :: S, H}
         ImplWitnessMap witnesses;
-        if (num_impls > 0) {
+        if (num_witnesses > 0) {
           int i = 2;
-          for (const auto& [impl_bind, impl_exp] : call.impls()) {
+          for (const auto& [impl_bind, impl_exp] : call.witnesses()) {
             witnesses[impl_bind] = act.results()[i];
             ++i;
           }
         }
         return CallFunction(call, act.results()[0], act.results()[1],
                             std::move(witnesses));
-      } else if (act.pos() == 3 + static_cast<int>(num_impls)) {
-        if (act.results().size() < 3 + num_impls) {
+      } else if (act.pos() == 3 + static_cast<int>(num_witnesses)) {
+        if (act.results().size() < 3 + num_witnesses) {
           // Control fell through without explicit return.
           return todo_.FinishAction(TupleValue::Empty());
         } else {
           return todo_.FinishAction(
-              act.results()[2 + static_cast<int>(num_impls)]);
+              act.results()[2 + static_cast<int>(num_witnesses)]);
         }
       } else {
         CARBON_FATAL() << "in StepExp with Call pos " << act.pos();
@@ -1521,7 +1522,7 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
               .kind = IntrinsicConstraint::ImplicitAs,
               .arguments = args};
           auto* result = arena_->New<ConstraintType>(
-              self_binding, std::vector<ImplConstraint>{},
+              self_binding, std::vector<ImplsConstraint>{},
               std::vector<IntrinsicConstraint>{std::move(constraint)},
               std::vector<EqualityConstraint>{},
               std::vector<RewriteConstraint>{}, std::vector<LookupContext>{});

+ 1 - 1
explorer/interpreter/matching_impl_set.cpp

@@ -105,7 +105,7 @@ auto MatchingImplSet::GetLabelForDeclaration(const Declaration& declaration)
 }
 
 MatchingImplSet::Match::Match(Nonnull<MatchingImplSet*> parent,
-                              Nonnull<const ImplScope::Impl*> impl,
+                              Nonnull<const ImplScope::ImplFact*> impl,
                               Nonnull<const Value*> type,
                               Nonnull<const Value*> interface)
     : parent_(parent), impl_(impl), type_(type), interface_(interface) {

+ 2 - 2
explorer/interpreter/matching_impl_set.h

@@ -44,7 +44,7 @@ class MatchingImplSet {
   class Match {
    public:
     explicit Match(Nonnull<MatchingImplSet*> parent,
-                   Nonnull<const ImplScope::Impl*> impl,
+                   Nonnull<const ImplScope::ImplFact*> impl,
                    Nonnull<const Value*> type, Nonnull<const Value*> interface);
     ~Match();
 
@@ -63,7 +63,7 @@ class MatchingImplSet {
     // The set that this match is part of.
     Nonnull<MatchingImplSet*> parent_;
     // The `impl` that is being matched against.
-    Nonnull<const ImplScope::Impl*> impl_;
+    Nonnull<const ImplScope::ImplFact*> impl_;
     // The type that is being matched against the impl.
     Nonnull<const Value*> type_;
     // The interface that is being matched against the impl.

+ 1 - 1
explorer/interpreter/resolve_control_flow.cpp

@@ -181,7 +181,7 @@ auto ResolveControlFlow(Nonnull<Declaration*> declaration) -> ErrorOr<Success> {
     }
     case DeclarationKind::MatchFirstDeclaration: {
       auto& match_first_decl = cast<MatchFirstDeclaration>(*declaration);
-      for (Nonnull<Declaration*> impl : match_first_decl.impls()) {
+      for (Nonnull<Declaration*> impl : match_first_decl.impl_declarations()) {
         CARBON_RETURN_IF_ERROR(ResolveControlFlow(impl));
       }
       break;

+ 7 - 5
explorer/interpreter/resolve_names.cpp

@@ -413,11 +413,12 @@ auto NameResolver::ResolveNames(WhereClause& clause,
                                 const StaticScope& enclosing_scope)
     -> ErrorOr<Success> {
   switch (clause.kind()) {
-    case WhereClauseKind::IsWhereClause: {
-      auto& is_clause = cast<IsWhereClause>(clause);
-      CARBON_RETURN_IF_ERROR(ResolveNames(is_clause.type(), enclosing_scope));
+    case WhereClauseKind::ImplsWhereClause: {
+      auto& impls_clause = cast<ImplsWhereClause>(clause);
       CARBON_RETURN_IF_ERROR(
-          ResolveNames(is_clause.constraint(), enclosing_scope));
+          ResolveNames(impls_clause.type(), enclosing_scope));
+      CARBON_RETURN_IF_ERROR(
+          ResolveNames(impls_clause.constraint(), enclosing_scope));
       break;
     }
     case WhereClauseKind::EqualsWhereClause: {
@@ -697,7 +698,8 @@ auto NameResolver::ResolveNames(Declaration& declaration,
     }
     case DeclarationKind::MatchFirstDeclaration: {
       // A `match_first` declaration does not introduce a scope.
-      for (auto* impl : cast<MatchFirstDeclaration>(declaration).impls()) {
+      for (auto* impl :
+           cast<MatchFirstDeclaration>(declaration).impl_declarations()) {
         CARBON_RETURN_IF_ERROR(ResolveNames(*impl, enclosing_scope, bodies));
       }
       break;

+ 97 - 92
explorer/interpreter/type_checker.cpp

@@ -526,7 +526,7 @@ auto TypeChecker::IsImplicitlyConvertible(
     const ImplScope& impl_scope, bool allow_user_defined_conversions) const
     -> ErrorOr<bool> {
   // Check for an exact match or for an implicit conversion.
-  // TODO: `impl`s of `ImplicitAs` should be provided to cover these
+  // TODO: `impl` definitions of `ImplicitAs` should be provided to cover these
   // conversions.
   CARBON_CHECK(IsConcreteType(source));
   CARBON_CHECK(IsConcreteType(destination));
@@ -1515,18 +1515,18 @@ class TypeChecker::ConstraintTypeBuilder {
     return cast<Witness>(*impl_binding_->symbolic_identity());
   }
 
-  // Adds an `impl` constraint -- `T is C` if not already present.
-  // Returns the index of the impl constraint within the self witness.
-  auto AddImplConstraint(ImplConstraint impl) -> int {
-    for (int i = 0; i != static_cast<int>(impl_constraints_.size()); ++i) {
-      ImplConstraint& existing = impl_constraints_[i];
-      if (TypeEqual(existing.type, impl.type, std::nullopt) &&
-          TypeEqual(existing.interface, impl.interface, std::nullopt)) {
+  // Adds an `impls` constraint -- `T impls C` if not already present.
+  // Returns the index of the impls constraint within the self witness.
+  auto AddImplsConstraint(ImplsConstraint impls) -> int {
+    for (int i = 0; i != static_cast<int>(impls_constraints_.size()); ++i) {
+      ImplsConstraint& existing = impls_constraints_[i];
+      if (TypeEqual(existing.type, impls.type, std::nullopt) &&
+          TypeEqual(existing.interface, impls.interface, std::nullopt)) {
         return i;
       }
     }
-    impl_constraints_.push_back(impl);
-    return impl_constraints_.size() - 1;
+    impls_constraints_.push_back(impls);
+    return impls_constraints_.size() - 1;
   }
 
   // Adds an intrinsic constraint, if not already present.
@@ -1585,17 +1585,17 @@ class TypeChecker::ConstraintTypeBuilder {
     // First substitute into the impl bindings to form the full witness for
     // the constraint type.
     std::vector<Nonnull<const Witness*>> witnesses;
-    for (const auto& impl_constraint : constraint->impl_constraints()) {
+    for (const auto& impls_constraint : constraint->impls_constraints()) {
       Bindings local_bindings = bindings;
       local_bindings.Add(constraint->self_binding(), self,
                          type_checker.MakeConstraintWitness(witnesses));
       CARBON_ASSIGN_OR_RETURN(
           Nonnull<const Value*> type,
-          type_checker.Substitute(local_bindings, impl_constraint.type));
+          type_checker.Substitute(local_bindings, impls_constraint.type));
       CARBON_ASSIGN_OR_RETURN(const auto* interface,
                               type_checker.SubstituteCast<InterfaceType>(
-                                  local_bindings, impl_constraint.interface));
-      int index = AddImplConstraint({.type = type, .interface = interface});
+                                  local_bindings, impls_constraint.interface));
+      int index = AddImplsConstraint({.type = type, .interface = interface});
       witnesses.push_back(
           type_checker.MakeConstraintWitnessAccess(self_witness, index));
     }
@@ -1622,8 +1622,8 @@ class TypeChecker::ConstraintTypeBuilder {
                                   rewrite_constraint.converted_replacement));
 
       // Form a symbolic value naming the non-rewritten associated constant.
-      // The impl constraint will always already exist.
-      int index = AddImplConstraint({.type = self, .interface = interface});
+      // The impls constraint will always already exist.
+      int index = AddImplsConstraint({.type = self, .interface = interface});
       const auto* witness =
           type_checker.MakeConstraintWitnessAccess(self_witness, index);
       const auto* constant_value = arena_->New<AssociatedConstant>(
@@ -1700,31 +1700,31 @@ class TypeChecker::ConstraintTypeBuilder {
     friend class ConstraintTypeBuilder;
 
    private:
-    int num_impls_added = 0;
-    int num_equals_added = 0;
+    int num_impls_constraints_added = 0;
+    int num_equality_constraints_added = 0;
   };
 
-  // Brings all the constraints accumulated so far into the given impl scope,
-  // as if we built the constraint type and then added it into the scope. If
-  // this will be called more than once, an ImplsInScopeTracker can be provided
-  // to avoid adding the same impls more than once.
+  // Brings all the constraints accumulated so far into the given impl scope, as
+  // if we built the constraint type and then added it into the scope. If this
+  // will be called more than once, an ConstraintssInScopeTracker can be
+  // provided to avoid adding the same implementations more than once.
   void BringConstraintsIntoScope(const TypeChecker& type_checker,
                                  Nonnull<ImplScope*> impl_scope,
                                  Nonnull<ConstraintsInScopeTracker*> tracker) {
     // Figure out which constraints we're going to add.
-    int first_impl_to_add =
-        std::exchange(tracker->num_impls_added, impl_constraints_.size());
-    int first_equal_to_add =
-        std::exchange(tracker->num_equals_added, equality_constraints_.size());
-    auto new_impl_constraints =
-        llvm::ArrayRef<ImplConstraint>(impl_constraints_)
-            .drop_front(first_impl_to_add);
+    int first_impls_constraint_to_add = std::exchange(
+        tracker->num_impls_constraints_added, impls_constraints_.size());
+    int first_equality_constraint_to_add = std::exchange(
+        tracker->num_equality_constraints_added, equality_constraints_.size());
+    auto new_impls_constraints =
+        llvm::ArrayRef<ImplsConstraint>(impls_constraints_)
+            .drop_front(first_impls_constraint_to_add);
     auto new_equality_constraints =
         llvm::ArrayRef<EqualityConstraint>(equality_constraints_)
-            .drop_front(first_equal_to_add);
+            .drop_front(first_equality_constraint_to_add);
 
     // Add all of the new constraints.
-    impl_scope->Add(new_impl_constraints, std::nullopt, std::nullopt,
+    impl_scope->Add(new_impls_constraints, std::nullopt, std::nullopt,
                     GetSelfWitness(), type_checker);
     for (const auto& equal : new_equality_constraints) {
       impl_scope->AddEqualityConstraint(arena_->New<EqualityConstraint>(equal));
@@ -1751,7 +1751,7 @@ class TypeChecker::ConstraintTypeBuilder {
   auto Build() && -> Nonnull<const ConstraintType*> {
     // Create the new type.
     auto* result = arena_->New<ConstraintType>(
-        self_binding_, std::move(impl_constraints_),
+        self_binding_, std::move(impls_constraints_),
         std::move(intrinsic_constraints_), std::move(equality_constraints_),
         std::move(rewrite_constraints_), std::move(lookup_contexts_));
     // Update the impl binding to denote the constraint type itself.
@@ -1912,14 +1912,14 @@ class TypeChecker::ConstraintTypeBuilder {
           type_checker.RebuildValue(rewrite.unconverted_replacement_type));
     }
 
-    // Apply rewrites throughout impl constraints.
-    for (auto& impl_constraint : impl_constraints_) {
-      CARBON_ASSIGN_OR_RETURN(impl_constraint.type,
-                              type_checker.RebuildValue(impl_constraint.type));
+    // Apply rewrites throughout impls constraints.
+    for (auto& impls_constraint : impls_constraints_) {
+      CARBON_ASSIGN_OR_RETURN(impls_constraint.type,
+                              type_checker.RebuildValue(impls_constraint.type));
       CARBON_ASSIGN_OR_RETURN(
           const auto* subst_interface,
-          type_checker.RebuildValue(impl_constraint.interface));
-      impl_constraint.interface = cast<InterfaceType>(subst_interface);
+          type_checker.RebuildValue(impls_constraint.interface));
+      impls_constraint.interface = cast<InterfaceType>(subst_interface);
     }
 
     // Apply rewrites throughout intrinsic constraints.
@@ -1952,7 +1952,7 @@ class TypeChecker::ConstraintTypeBuilder {
   Nonnull<Arena*> arena_;
   Nonnull<GenericBinding*> self_binding_;
   Nonnull<ImplBinding*> impl_binding_;
-  std::vector<ImplConstraint> impl_constraints_;
+  std::vector<ImplsConstraint> impls_constraints_;
   std::vector<IntrinsicConstraint> intrinsic_constraints_;
   std::vector<EqualityConstraint> equality_constraints_;
   std::vector<RewriteConstraint> rewrite_constraints_;
@@ -2274,7 +2274,7 @@ auto TypeChecker::RefineWitness(Nonnull<const Witness*> witness,
 
 auto TypeChecker::MatchImpl(const InterfaceType& iface,
                             Nonnull<const Value*> impl_type,
-                            const ImplScope::Impl& impl,
+                            const ImplScope::ImplFact& impl,
                             const ImplScope& impl_scope,
                             SourceLocation source_loc) const
     -> ErrorOr<std::optional<Nonnull<const Witness*>>> {
@@ -2343,9 +2343,9 @@ auto TypeChecker::MatchImpl(const InterfaceType& iface,
 }
 
 auto TypeChecker::MakeConstraintWitness(
-    std::vector<Nonnull<const Witness*>> impl_constraint_witnesses) const
+    std::vector<Nonnull<const Witness*>> impls_constraint_witnesses) const
     -> Nonnull<const Witness*> {
-  return arena_->New<ConstraintWitness>(std::move(impl_constraint_witnesses));
+  return arena_->New<ConstraintWitness>(std::move(impls_constraint_witnesses));
 }
 
 auto TypeChecker::MakeConstraintWitnessAccess(Nonnull<const Witness*> witness,
@@ -3866,20 +3866,22 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
         CARBON_RETURN_IF_ERROR(TypeCheckWhereClause(clause, inner_impl_scope));
 
         switch (clause->kind()) {
-          case WhereClauseKind::IsWhereClause: {
-            auto& is_clause = cast<IsWhereClause>(*clause);
+          case WhereClauseKind::ImplsWhereClause: {
+            auto& impls_clause = cast<ImplsWhereClause>(*clause);
             CARBON_ASSIGN_OR_RETURN(
                 Nonnull<const Value*> type,
-                TypeCheckTypeExp(&is_clause.type(), inner_impl_scope));
+                TypeCheckTypeExp(&impls_clause.type(), inner_impl_scope));
             CARBON_ASSIGN_OR_RETURN(
                 Nonnull<const Value*> constraint,
-                InterpExp(&is_clause.constraint(), arena_, trace_stream_));
+                InterpExp(&impls_clause.constraint(), arena_, trace_stream_));
             CARBON_ASSIGN_OR_RETURN(
                 Nonnull<const ConstraintType*> constraint_type,
-                ConvertToConstraintType(is_clause.source_loc(),
-                                        "expression after `is`", constraint));
-            // Transform `where .B is (C where .D is E)` into `where .B is C
-            // and .B.D is E` then add all the resulting constraints.
+                ConvertToConstraintType(impls_clause.source_loc(),
+                                        "expression after `impls`",
+                                        constraint));
+            // Transform `where .B impls (C where .D impls E)` into
+            // `where .B impls C and .B.D impls E` then add all the resulting
+            // constraints.
             CARBON_RETURN_IF_ERROR(
                 builder.AddAndSubstitute(*this, constraint_type, type,
                                          builder.GetSelfWitness(), Bindings(),
@@ -3915,10 +3917,10 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
                      << "` does not name an associated constant";
             }
 
-            // Find (or add) `.Self is I`, and form a symbolic value naming the
-            // associated constant.
-            // TODO: Reject if the impl constraint didn't already exist.
-            int index = builder.AddImplConstraint(
+            // Find (or add) `.Self impls I`, and form a symbolic value naming
+            // the associated constant.
+            // TODO: Reject if the impls constraint didn't already exist.
+            int index = builder.AddImplsConstraint(
                 {.type = builder.GetSelfType(), .interface = result.interface});
             const auto* witness =
                 MakeConstraintWitnessAccess(builder.GetSelfWitness(), index);
@@ -4023,23 +4025,23 @@ void TypeChecker::CollectImplBindingsInPattern(
   });
 }
 
-void TypeChecker::BringPatternImplsIntoScope(Nonnull<const Pattern*> p,
-                                             ImplScope& impl_scope) {
+void TypeChecker::BringPatternImplBindingsIntoScope(Nonnull<const Pattern*> p,
+                                                    ImplScope& impl_scope) {
   std::vector<Nonnull<const ImplBinding*>> impl_bindings;
   CollectImplBindingsInPattern(p, impl_bindings);
-  BringImplsIntoScope(impl_bindings, impl_scope);
+  BringImplBindingsIntoScope(impl_bindings, impl_scope);
 }
 
-void TypeChecker::BringImplsIntoScope(
+void TypeChecker::BringImplBindingsIntoScope(
     llvm::ArrayRef<Nonnull<const ImplBinding*>> impl_bindings,
     ImplScope& impl_scope) {
   for (Nonnull<const ImplBinding*> impl_binding : impl_bindings) {
-    BringImplIntoScope(impl_binding, impl_scope);
+    BringImplBindingIntoScope(impl_binding, impl_scope);
   }
 }
 
-void TypeChecker::BringImplIntoScope(Nonnull<const ImplBinding*> impl_binding,
-                                     ImplScope& impl_scope) {
+void TypeChecker::BringImplBindingIntoScope(
+    Nonnull<const ImplBinding*> impl_binding, ImplScope& impl_scope) {
   CARBON_CHECK(impl_binding->type_var()->symbolic_identity().has_value() &&
                impl_binding->symbolic_identity().has_value());
   impl_scope.Add(impl_binding->interface(),
@@ -4076,15 +4078,16 @@ auto TypeChecker::TypeCheckWhereClause(Nonnull<WhereClause*> clause,
                                        const ImplScope& impl_scope)
     -> ErrorOr<Success> {
   switch (clause->kind()) {
-    case WhereClauseKind::IsWhereClause: {
-      auto& is_clause = cast<IsWhereClause>(*clause);
+    case WhereClauseKind::ImplsWhereClause: {
+      auto& impls_clause = cast<ImplsWhereClause>(*clause);
       // TODO: `type` is checked in the caller, because its converted value is
       // needed. Find a way to move that checking back here.
-      CARBON_RETURN_IF_ERROR(TypeCheckExp(&is_clause.constraint(), impl_scope));
-      if (!isa<TypeType>(is_clause.constraint().static_type())) {
-        return ProgramError(is_clause.constraint().source_loc())
-               << "expression after `is` does not resolve to a constraint, "
-               << "found " << is_clause.constraint().static_type();
+      CARBON_RETURN_IF_ERROR(
+          TypeCheckExp(&impls_clause.constraint(), impl_scope));
+      if (!isa<TypeType>(impls_clause.constraint().static_type())) {
+        return ProgramError(impls_clause.constraint().source_loc())
+               << "expression after `impls` does not resolve to a constraint, "
+               << "found " << impls_clause.constraint().static_type();
       }
       return Success();
     }
@@ -4355,8 +4358,8 @@ auto TypeChecker::TypeCheckGenericBinding(GenericBinding& binding,
     binding.set_impl_binding(impl_binding);
 
     // Substitute the VariableType as `.Self` of the constraint to form the
-    // resolved type of the binding. Eg, `T:! X where .Self is Y` resolves
-    // to `T:! <constraint T is X and T is Y>`.
+    // resolved type of the binding. Eg, `T:! X where .Self impls Y` resolves
+    // to `T:! <constraint T impls X and T impls Y>`.
     ConstraintTypeBuilder builder(arena_, &binding, impl_binding);
     CARBON_RETURN_IF_ERROR(
         builder.AddAndSubstitute(*this, constraint, symbolic_value, witness,
@@ -4372,7 +4375,7 @@ auto TypeChecker::TypeCheckGenericBinding(GenericBinding& binding,
       *trace_stream_ << "resolved constraint type is " << *type << "\n";
     }
 
-    BringImplIntoScope(impl_binding, impl_scope);
+    BringImplBindingIntoScope(impl_binding, impl_scope);
   }
 
   binding.set_static_type(type);
@@ -4873,10 +4876,10 @@ auto TypeChecker::TypeCheckCallableDeclaration(Nonnull<CallableDeclaration*> f,
   // If f->return_term().is_auto(), the function body was already
   // type checked in DeclareFunctionDeclaration.
   if (f->body().has_value() && !f->return_term().is_auto()) {
-    // Bring the impls into scope.
+    // Bring the impl bindings into scope.
     ImplScope function_scope(&impl_scope);
-    BringImplsIntoScope(cast<FunctionType>(f->static_type()).impl_bindings(),
-                        function_scope);
+    BringImplBindingsIntoScope(
+        cast<FunctionType>(f->static_type()).impl_bindings(), function_scope);
     if (trace_stream_->is_enabled()) {
       *trace_stream_ << function_scope;
     }
@@ -5069,7 +5072,7 @@ auto TypeChecker::TypeCheckClassDeclaration(
   }
   ImplScope class_scope(&impl_scope);
   if (class_decl->type_params().has_value()) {
-    BringPatternImplsIntoScope(*class_decl->type_params(), class_scope);
+    BringPatternImplBindingsIntoScope(*class_decl->type_params(), class_scope);
   }
   if (trace_stream_->is_enabled()) {
     *trace_stream_ << class_scope;
@@ -5157,7 +5160,7 @@ auto TypeChecker::TypeCheckMixinDeclaration(
   }
   ImplScope mixin_scope(&impl_scope);
   if (mixin_decl->params().has_value()) {
-    BringPatternImplsIntoScope(*mixin_decl->params(), mixin_scope);
+    BringPatternImplBindingsIntoScope(*mixin_decl->params(), mixin_scope);
   }
   if (trace_stream_->is_enabled()) {
     *trace_stream_ << mixin_scope;
@@ -5282,12 +5285,12 @@ auto TypeChecker::DeclareConstraintTypeDeclaration(
   // this interface.
   std::optional<Nonnull<const Witness*>> iface_impl_witness;
   if (is_interface) {
-    // The impl constraint says only that the direct members of the interface
+    // The impls constraint says only that the direct members of the interface
     // are available. For any indirect constraints, we need to add separate
     // entries to the constraint type. This ensures that all indirect
     // constraints are lifted to the top level so they can be accessed directly
     // and resolved independently if necessary.
-    int index = builder.AddImplConstraint(
+    int index = builder.AddImplsConstraint(
         {.type = builder.GetSelfType(),
          .interface = cast<InterfaceType>(constraint_type)});
     iface_impl_witness =
@@ -5303,7 +5306,8 @@ auto TypeChecker::DeclareConstraintTypeDeclaration(
     // to update state that's not available from there.
     switch (m->kind()) {
       case DeclarationKind::InterfaceExtendsDeclaration: {
-        // For an `extends C;` declaration, add `Self is C` to our constraint.
+        // For an `extends C;` declaration, add `Self impls C` to our
+        // constraint.
         auto* extends = cast<InterfaceExtendsDeclaration>(m);
         CARBON_ASSIGN_OR_RETURN(
             Nonnull<const Value*> base,
@@ -5320,7 +5324,7 @@ auto TypeChecker::DeclareConstraintTypeDeclaration(
       }
 
       case DeclarationKind::InterfaceImplDeclaration: {
-        // For an `impl X as Y;` declaration, add `X is Y` to our constraint.
+        // For an `impl X as Y;` declaration, add `X impls Y` to our constraint.
         auto* impl = cast<InterfaceImplDeclaration>(m);
         CARBON_ASSIGN_OR_RETURN(
             Nonnull<const Value*> impl_type,
@@ -5364,8 +5368,8 @@ auto TypeChecker::DeclareConstraintTypeDeclaration(
 
         // The type specified for the associated constant becomes a
         // constraint for the constraint type: `let X:! Interface` adds a
-        // `Self.X is Interface` constraint that `impl`s must satisfy and users
-        // of the constraint type can rely on.
+        // `Self.X impls Interface` constraint that `impl` declarations must
+        // satisfy and users of the constraint type can rely on.
         if (const auto* constraint_type =
                 dyn_cast<ConstraintType>(constraint)) {
           CARBON_RETURN_IF_ERROR(
@@ -5393,7 +5397,7 @@ auto TypeChecker::DeclareConstraintTypeDeclaration(
       }
     }
 
-    // Add any new impl constraints to the scope.
+    // Add any new impls constraints to the scope.
     builder.BringConstraintsIntoScope(*this, &constraint_scope,
                                       &constraint_tracker);
   }
@@ -5418,7 +5422,8 @@ auto TypeChecker::TypeCheckConstraintTypeDeclaration(
   }
   ImplScope constraint_scope(&impl_scope);
   if (constraint_decl->params().has_value()) {
-    BringPatternImplsIntoScope(*constraint_decl->params(), constraint_scope);
+    BringPatternImplBindingsIntoScope(*constraint_decl->params(),
+                                      constraint_scope);
   }
   if (trace_stream_->is_enabled()) {
     *trace_stream_ << constraint_scope;
@@ -5506,7 +5511,7 @@ auto TypeChecker::CheckAndAddImplBindings(
     const ScopeInfo& scope_info) -> ErrorOr<Success> {
   // Each interface that is a lookup context is required to be implemented by
   // the impl members. Other constraints are required to be satisfied by
-  // either those impls or impls available elsewhere.
+  // either those implementations or implementations available elsewhere.
   Nonnull<const ConstraintType*> constraint = impl_decl->constraint_type();
   for (auto lookup : constraint->lookup_contexts()) {
     if (const auto* iface_type = dyn_cast<InterfaceType>(lookup.context)) {
@@ -5648,15 +5653,15 @@ auto TypeChecker::DeclareImplDeclaration(Nonnull<ImplDeclaration*> impl_decl,
                                  builder.GetSelfWitness(), Bindings(),
                                  /*add_lookup_contexts=*/true));
     if (trace_stream_->is_enabled()) {
-      *trace_stream_ << "resolving impl constraint type for " << *impl_decl
+      *trace_stream_ << "resolving impls constraint type for " << *impl_decl
                      << " from " << *implemented_constraint << "\n";
     }
     CARBON_RETURN_IF_ERROR(builder.Resolve(
         *this, impl_decl->interface().source_loc(), impl_scope));
     constraint_type = std::move(builder).Build();
     if (trace_stream_->is_enabled()) {
-      *trace_stream_ << "resolving impl constraint type as " << *constraint_type
-                     << "\n";
+      *trace_stream_ << "resolving impls constraint type as "
+                     << *constraint_type << "\n";
     }
     impl_decl->set_constraint_type(constraint_type);
   }
@@ -5764,9 +5769,9 @@ auto TypeChecker::TypeCheckImplDeclaration(Nonnull<ImplDeclaration*> impl_decl,
   Nonnull<const Value*> self = *impl_decl->self()->constant_value();
   Nonnull<const ConstraintType*> constraint = impl_decl->constraint_type();
 
-  // Bring the impls from the parameters into scope.
+  // Bring the impl bindings from the parameters into scope.
   ImplScope impl_scope(&enclosing_scope);
-  BringImplsIntoScope(impl_decl->impl_bindings(), impl_scope);
+  BringImplBindingsIntoScope(impl_decl->impl_bindings(), impl_scope);
   for (Nonnull<Declaration*> m : impl_decl->members()) {
     CARBON_ASSIGN_OR_RETURN(
         ConstraintLookupResult result,
@@ -5966,7 +5971,7 @@ auto TypeChecker::TypeCheckDeclaration(
     }
     case DeclarationKind::MatchFirstDeclaration: {
       auto* match_first = cast<MatchFirstDeclaration>(d);
-      for (auto* impl : match_first->impls()) {
+      for (auto* impl : match_first->impl_declarations()) {
         impl->set_match_first(match_first);
         CARBON_RETURN_IF_ERROR(TypeCheckImplDeclaration(impl, impl_scope));
       }
@@ -6057,7 +6062,7 @@ auto TypeChecker::DeclareDeclaration(Nonnull<Declaration*> d,
       break;
     }
     case DeclarationKind::MatchFirstDeclaration: {
-      for (auto* impl : cast<MatchFirstDeclaration>(d)->impls()) {
+      for (auto* impl : cast<MatchFirstDeclaration>(d)->impl_declarations()) {
         CARBON_RETURN_IF_ERROR(DeclareImplDeclaration(
             impl, scope_info, /*is_template_instantiation=*/false));
       }

+ 16 - 16
explorer/interpreter/type_checker.h

@@ -78,7 +78,7 @@ class TypeChecker {
   // `type`, then return the witness for this `impl`. Otherwise return
   // std::nullopt.
   auto MatchImpl(const InterfaceType& iface, Nonnull<const Value*> type,
-                 const ImplScope::Impl& impl, const ImplScope& impl_scope,
+                 const ImplScope::ImplFact& impl, const ImplScope& impl_scope,
                  SourceLocation source_loc) const
       -> ErrorOr<std::optional<Nonnull<const Witness*>>>;
 
@@ -105,7 +105,7 @@ class TypeChecker {
   // Given the witnesses for the components of a constraint, form a witness for
   // the constraint.
   auto MakeConstraintWitness(
-      std::vector<Nonnull<const Witness*>> impl_constraint_witnesses) const
+      std::vector<Nonnull<const Witness*>> impls_constraint_witnesses) const
       -> Nonnull<const Witness*>;
 
   // Given the witnesses for the components of a constraint, form a witness for
@@ -143,11 +143,11 @@ class TypeChecker {
               .bindings = std::move(class_bindings)};
     }
 
-    // The innermost enclosing impl scope, within which impls should be looked
-    // up.
+    // The innermost enclosing impl scope, within which impl declarations should
+    // be looked up.
     Nonnull<ImplScope*> innermost_scope;
     // The innermost enclosing non-class impl scope, where impl declarations
-    // should introduce new impls.
+    // should introduce new implementations.
     Nonnull<ImplScope*> innermost_non_class_scope;
     // The enclosing generic bindings, if any.
     std::vector<Nonnull<const GenericBinding*>> bindings;
@@ -192,7 +192,7 @@ class TypeChecker {
   // surrounding context gives us that information. Otherwise, it is nullopt.
   // Implicit conversions from `expected` to the pattern's type are permitted.
   //
-  // `impl_scope` is extended with all impls implied by the pattern.
+  // `impl_scope` is extended with all implementations implied by the pattern.
   auto TypeCheckPattern(Nonnull<Pattern*> p,
                         std::optional<Nonnull<const Value*>> expected,
                         ImplScope& impl_scope,
@@ -214,7 +214,7 @@ class TypeChecker {
       -> ErrorOr<Success>;
 
   // Perform deduction for the deduced bindings in a function call, and set its
-  // lists of generic bindings and impls.
+  // lists of generic bindings and implementations.
   //
   // -   `params` is the list of parameters.
   // -   `generic_params` indicates which parameters are generic parameters,
@@ -302,20 +302,20 @@ class TypeChecker {
       Nonnull<const Pattern*> p,
       std::vector<Nonnull<const ImplBinding*>>& impl_bindings);
 
-  // Add the impls from the pattern into the given `impl_scope`.
-  void BringPatternImplsIntoScope(Nonnull<const Pattern*> p,
-                                  ImplScope& impl_scope);
+  // Add the impl bindings from the pattern into the given `impl_scope`.
+  void BringPatternImplBindingsIntoScope(Nonnull<const Pattern*> p,
+                                         ImplScope& impl_scope);
 
   // Create a witness for the given `impl` binding.
   auto CreateImplBindingWitness(Nonnull<const ImplBinding*> impl_binding)
       -> Nonnull<const Witness*>;
 
   // Add the given ImplBinding to the given `impl_scope`.
-  void BringImplIntoScope(Nonnull<const ImplBinding*> impl_binding,
-                          ImplScope& impl_scope);
+  void BringImplBindingIntoScope(Nonnull<const ImplBinding*> impl_binding,
+                                 ImplScope& impl_scope);
 
   // Add all of the `impl_bindings` into the `scope`.
-  void BringImplsIntoScope(
+  void BringImplBindingsIntoScope(
       llvm::ArrayRef<Nonnull<const ImplBinding*>> impl_bindings,
       ImplScope& scope);
 
@@ -436,8 +436,8 @@ class TypeChecker {
                        const ImplScope& impl_scope) const -> ErrorOr<Success>;
 
   // Rebuild a value in the current type-checking context. Applies any rewrites
-  // that are in scope and attempts to resolve associated constants using impls
-  // that have been declared since the value was formed.
+  // that are in scope and attempts to resolve associated constants using
+  // implementations that have been declared since the value was formed.
   auto RebuildValue(Nonnull<const Value*> value) const
       -> ErrorOr<Nonnull<const Value*>>;
 
@@ -544,7 +544,7 @@ class TypeChecker {
   // rewrites that are not yet visible in any type.
   std::vector<ConstraintTypeBuilder*> partial_constraint_types_;
 
-  // A set of impls we're currently matching.
+  // A set of implementations we're currently matching.
   // TODO: This is `mutable` because `MatchImpl` is `const`. We need to remove
   // the `const`s from everywhere that transitively does `impl` matching to get
   // rid of this `mutable`.

+ 1 - 1
explorer/interpreter/type_structure.cpp

@@ -86,7 +86,7 @@ struct TypeStructureBuilder {
 
   // Constraint types can contain mentions of VariableTypes, but they aren't
   // deducible so it's not important to look for them.
-  void Visit(const ImplConstraint&) {}
+  void Visit(const ImplsConstraint&) {}
   void Visit(const IntrinsicConstraint&) {}
   void Visit(const EqualityConstraint&) {}
   void Visit(const RewriteConstraint&) {}

+ 2 - 2
explorer/syntax/lexer.lpp

@@ -76,10 +76,10 @@ GREATER_GREATER       ">>"
 GREATER_GREATER_EQUAL ">>="
 IF                    "if"
 IMPL                  "impl"
+IMPLS                 "impls"
 IMPORT                "import"
 IN                    "in"
 INTERFACE             "interface"
-IS                    "is"
 LEFT_CURLY_BRACE      "{"
 LEFT_PARENTHESIS      "("
 LEFT_SQUARE_BRACKET   "["
@@ -198,11 +198,11 @@ operand_start         [(A-Za-z0-9_\"]
 {GREATER_GREATER}       { return CARBON_SIMPLE_TOKEN(GREATER_GREATER);       }
 {GREATER}               { return CARBON_SIMPLE_TOKEN(GREATER);               }
 {IF}                    { return CARBON_SIMPLE_TOKEN(IF);                    }
+{IMPLS}                 { return CARBON_SIMPLE_TOKEN(IMPLS);                 }
 {IMPL}                  { return CARBON_SIMPLE_TOKEN(IMPL);                  }
 {IMPORT}                { return CARBON_SIMPLE_TOKEN(IMPORT);                }
 {INTERFACE}             { return CARBON_SIMPLE_TOKEN(INTERFACE);             }
 {IN}                    { return CARBON_SIMPLE_TOKEN(IN);                    }
-{IS}                    { return CARBON_SIMPLE_TOKEN(IS);                    }
 {LEFT_CURLY_BRACE}      { return CARBON_SIMPLE_TOKEN(LEFT_CURLY_BRACE);      }
 {LEFT_PARENTHESIS}      { return CARBON_SIMPLE_TOKEN(LEFT_PARENTHESIS);      }
 {LEFT_SQUARE_BRACKET}   { return CARBON_SIMPLE_TOKEN(LEFT_SQUARE_BRACKET);   }

+ 3 - 3
explorer/syntax/parser.ypp

@@ -252,10 +252,10 @@
   GREATER_GREATER_EQUAL
   IF
   IMPL
+  IMPLS
   IMPORT
   IN
   INTERFACE
-  IS
   LEFT_CURLY_BRACE
   LEFT_PARENTHESIS
   LEFT_SQUARE_BRACKET
@@ -721,8 +721,8 @@ or_expression:
     }
 ;
 where_clause:
-  comparison_operand IS comparison_operand
-    { $$ = arena->New<IsWhereClause>(context.source_loc(), $1, $3); }
+  comparison_operand IMPLS comparison_operand
+    { $$ = arena->New<ImplsWhereClause>(context.source_loc(), $1, $3); }
 | comparison_operand EQUAL_EQUAL comparison_operand
     { $$ = arena->New<EqualsWhereClause>(context.source_loc(), $1, $3); }
 // TODO: .(expression) = expression

+ 2 - 2
explorer/testdata/assoc_const/impl_used_by_later_rewrite.carbon

@@ -16,9 +16,9 @@ interface Y(T:! type) {
 }
 
 interface Z {
-  // The `i32 is X(.Self)` constraint is indirectly required by
+  // The `i32 impls X(.Self)` constraint is indirectly required by
   // specifying that `.M = i32`.
-  let N:! Y(.Self) where i32 is X(.Self) and .M = i32;
+  let N:! Y(.Self) where i32 impls X(.Self) and .M = i32;
 }
 
 impl i32 as X(i32) {}

+ 5 - 5
explorer/testdata/assoc_const/rewrite_interface_params.carbon

@@ -25,11 +25,11 @@ interface HasParams(A:! type, B:! type, C:! type, D:! type) {
 // Here we discover that there is a rewrite for `HasParams(...).V` only after
 // substitution converts each one to `HasParam(X, X, X, X).V`.
 fn F[X:! (HasTypes & HasParams(.Self, .Self, .Self, .Self)) where
-       .Self is HasParams(.A, .A, .A, .A) and
-       .Self is HasParams(.B, .B, .B, .B) and
-       .Self is HasParams(.C, .C, .C, .C) and
-       .Self is HasParams(.D, .D, .D, .D) and
-       .Self is HasParams(.E, .E, .E, .E) and
+       .Self impls HasParams(.A, .A, .A, .A) and
+       .Self impls HasParams(.B, .B, .B, .B) and
+       .Self impls HasParams(.C, .C, .C, .C) and
+       .Self impls HasParams(.D, .D, .D, .D) and
+       .Self impls HasParams(.E, .E, .E, .E) and
        .F = .Self.(HasParams(.E, .E, .E, .E).V).A and
        .E = .Self.(HasParams(.D, .D, .D, .D).V).A and
        .D = .Self.(HasParams(.C, .C, .C, .C).V).A and

+ 1 - 1
explorer/testdata/constraint/dot_self_is_other.carbon

@@ -16,7 +16,7 @@ impl i32 as A { fn F() -> i32 { return 1; } }
 impl i32 as B { fn F() -> i32 { return 2; } }
 
 fn GetA[T:! A](x: T) -> i32 { return x.F(); }
-fn GetAB[T:! B where .Self is A](x: T) -> i32 {
+fn GetAB[T:! B where .Self impls A](x: T) -> i32 {
   // Note that there's no ambiguity in the use of the name F here.
   // `x.F` is `x.(B.F)` because the constraint only treats `B`, not
   // `A`, as a lookup context.

+ 1 - 1
explorer/testdata/constraint/fail_combine_equality.carbon

@@ -13,7 +13,7 @@ impl i32 as I {}
 
 fn F(A:! i32, B:! i32, C:! i32, D:! i32, E:! i32,
      T:! I where A == B and C == D and C == E and B == D) {
-  // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/constraint/fail_combine_equality.carbon:[[@LINE+1]]: member access, F not in interface I where T is interface I and A == B and C == D and C == E and B == D
+  // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/constraint/fail_combine_equality.carbon:[[@LINE+1]]: member access, F not in interface I where T impls interface I and A == B and C == D and C == E and B == D
   T.F();
 }
 

+ 1 - 1
explorer/testdata/constraint/fail_missing_member.carbon

@@ -11,7 +11,7 @@ package ExplorerTest api;
 interface A { fn F() -> i32; }
 interface B { fn G() -> i32; }
 
-// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/constraint/fail_missing_member.carbon:[[@LINE+1]]: member access, H not in interface A & interface B where T is interface A and T is interface B
+// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/constraint/fail_missing_member.carbon:[[@LINE+1]]: member access, H not in interface A & interface B where T impls interface A and T impls interface B
 fn Get[T:! A & B](n: T) -> i32 { return n.H(); }
 
 impl i32 as A {

+ 2 - 2
explorer/testdata/constraint/fail_where_is_non_constraint.carbon → explorer/testdata/constraint/fail_where_impls_non_constraint.carbon

@@ -10,7 +10,7 @@ package ExplorerTest api;
 
 interface A {}
 
-// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/constraint/fail_where_is_non_constraint.carbon:[[@LINE+1]]: expected a constraint in expression after `is`, found i32
-alias B = A where i32 is i32;
+// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/constraint/fail_where_impls_non_constraint.carbon:[[@LINE+1]]: expected a constraint in expression after `impls`, found i32
+alias B = A where i32 impls i32;
 
 fn Main() -> i32 { return 0; }

+ 2 - 2
explorer/testdata/constraint/fail_where_is_non_type.carbon → explorer/testdata/constraint/fail_where_impls_non_type.carbon

@@ -10,7 +10,7 @@ package ExplorerTest api;
 
 interface A {}
 
-// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/constraint/fail_where_is_non_type.carbon:[[@LINE+1]]: expression after `is` does not resolve to a constraint, found i32
-alias B = A where i32 is 5;
+// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/constraint/fail_where_impls_non_type.carbon:[[@LINE+1]]: expression after `impls` does not resolve to a constraint, found i32
+alias B = A where i32 impls 5;
 
 fn Main() -> i32 { return 0; }

+ 2 - 2
explorer/testdata/constraint/fail_where_non_type_is.carbon → explorer/testdata/constraint/fail_where_non_type_impls.carbon

@@ -10,7 +10,7 @@ package ExplorerTest api;
 
 interface A {}
 
-// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/constraint/fail_where_non_type_is.carbon:[[@LINE+1]]: type error in type expression: 'i32' is not implicitly convertible to 'type'
-alias B = A where 4 is A;
+// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/constraint/fail_where_non_type_impls.carbon:[[@LINE+1]]: type error in type expression: 'i32' is not implicitly convertible to 'type'
+alias B = A where 4 impls A;
 
 fn Main() -> i32 { return 0; }

+ 1 - 1
explorer/testdata/constraint/nondependent_where.carbon

@@ -12,7 +12,7 @@ package ExplorerTest api;
 interface A { fn Get() -> Self; }
 impl i32 as A { fn Get() -> Self { return 1; } }
 
-alias AlsoA = A where i32 is A and 4 == 4;
+alias AlsoA = A where i32 impls A and 4 == 4;
 
 fn F[T:! AlsoA](x: T) -> T { return T.Get(); }
 

+ 1 - 1
explorer/testdata/constraint/qualified_lookup_in_where.carbon

@@ -15,7 +15,7 @@ interface B { fn F() -> i32; }
 impl i32 as A { fn F() -> i32 { return 1; } }
 impl i32 as B { fn F() -> i32 { return 2; } }
 
-fn GetAB(T:! B where .Self is A) -> i32 {
+fn GetAB(T:! B where .Self impls A) -> i32 {
   return 100 * T.(A.F)() + 10 * T.(B.F)() + T.F();
 }
 

+ 1 - 1
explorer/testdata/constraint/where_is.carbon → explorer/testdata/constraint/where_impls.carbon

@@ -18,7 +18,7 @@ interface Extension {
   extends Base;
 }
 
-fn F[T:! type where .Self is Extension](x: T) {
+fn F[T:! type where .Self impls Extension](x: T) {
   x.(Extension.F)();
 }
 

+ 1 - 1
explorer/testdata/constraint/where_self.carbon

@@ -15,7 +15,7 @@ interface SwizzleWith(T:! type) {
 
 // TODO: There should be some way to write this that includes
 // `SwizzleWith(.Self)` in the list of lookup contexts.
-alias Swizzle = type where .Self is SwizzleWith(.Self);
+alias Swizzle = type where .Self impls SwizzleWith(.Self);
 
 impl i32 as SwizzleWith(i32) {
   fn Op[self: Self](x: Self) -> Self { return self * 10 + x; }

+ 2 - 2
explorer/testdata/impl/fail_unmet_impl_constraint.carbon → explorer/testdata/impl/fail_unmet_impls_constraint.carbon

@@ -11,8 +11,8 @@ package ExplorerTest api;
 interface A {}
 interface B {}
 
-// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/impl/fail_unmet_impl_constraint.carbon:[[@LINE+1]]: could not find implementation of interface B for i32
-external impl i32 as A where i32 is B {}
+// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/impl/fail_unmet_impls_constraint.carbon:[[@LINE+1]]: could not find implementation of interface B for i32
+external impl i32 as A where i32 impls B {}
 
 fn Main() -> i32 {
   return 0;

+ 1 - 1
explorer/testdata/impl/impl_constraint.carbon → explorer/testdata/impl/impls_constraint.carbon

@@ -24,7 +24,7 @@ external impl i32 as A {
   fn F() -> i32 { return 1; }
 }
 
-external impl i32 as B & C(i32) where .Self is A {
+external impl i32 as B & C(i32) where .Self impls A {
   fn F() -> i32 { return 2; }
   fn G() -> i32 { return 3; }
   fn H() -> i32 { return 4; }

+ 1 - 1
explorer/testdata/impl_match/fail_self_recurse.carbon

@@ -10,7 +10,7 @@ package ExplorerTest api;
 
 interface Foo {}
 
-impl forall [T:! type where .Self* is Foo] T as Foo {}
+impl forall [T:! type where .Self* impls Foo] T as Foo {}
 
 fn F[T:! Foo](x: T) {}
 

+ 1 - 1
explorer/testdata/impl_match/fail_self_recurse_without_match_first.carbon

@@ -11,7 +11,7 @@ package ExplorerTest api;
 interface Foo {}
 
 impl forall [T:! type where .Self == i32*] T as Foo {}
-impl forall [T:! type where .Self* is Foo] T as Foo {}
+impl forall [T:! type where .Self* impls Foo] T as Foo {}
 
 fn F[T:! Foo](x: T) {}
 

+ 1 - 1
explorer/testdata/impl_match/fail_struct_recurse.carbon

@@ -10,7 +10,7 @@ package ExplorerTest api;
 
 interface Foo {}
 
-impl forall [T:! type where {.a: .Self} is Foo] T as Foo {}
+impl forall [T:! type where {.a: .Self} impls Foo] T as Foo {}
 
 fn F[T:! Foo](x: T) {}
 

+ 3 - 3
explorer/testdata/impl_match/fail_three_step_recurse.carbon

@@ -12,9 +12,9 @@ interface A {}
 interface B {}
 interface C {}
 
-impl forall [T:! type where .Self* is A] T as B {}
-impl forall [T:! type where .Self* is B] T as C {}
-impl forall [T:! type where .Self* is C] T as A {}
+impl forall [T:! type where .Self* impls A] T as B {}
+impl forall [T:! type where .Self* impls B] T as C {}
+impl forall [T:! type where .Self* impls C] T as A {}
 
 fn F[T:! A](x: T) {}
 

+ 1 - 1
explorer/testdata/impl_match/fail_tuple_recurse.carbon

@@ -10,7 +10,7 @@ package ExplorerTest api;
 
 interface Foo {}
 
-impl forall [T:! type where (.Self,) is Foo] T as Foo {}
+impl forall [T:! type where (.Self,) impls Foo] T as Foo {}
 
 fn F[T:! Foo](x: T) {}
 

+ 1 - 1
explorer/testdata/impl_match/self_recurse_with_match.carbon

@@ -12,7 +12,7 @@ package ExplorerTest api;
 interface Foo {}
 
 impl i32* as Foo {}
-impl forall [T:! type where .Self* is Foo] T as Foo {}
+impl forall [T:! type where .Self* impls Foo] T as Foo {}
 
 fn F[T:! Foo](x: T) {}
 

+ 1 - 1
explorer/testdata/impl_match/self_recurse_with_match_first.carbon

@@ -13,7 +13,7 @@ interface Foo {}
 
 __match_first {
   impl forall [T:! type where .Self == i32*] T as Foo {}
-  impl forall [T:! type where .Self* is Foo] T as Foo {}
+  impl forall [T:! type where .Self* impls Foo] T as Foo {}
 }
 
 fn F[T:! Foo](x: T) {}

+ 1 - 1
explorer/testdata/interface/fail_interface_missing_member.carbon

@@ -13,7 +13,7 @@ interface Vector {
 }
 
 fn ScaleGeneric[T:! Vector](a: T, s: i32) -> T {
-  // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/interface/fail_interface_missing_member.carbon:[[@LINE+1]]: member access, Scale not in interface Vector where T is interface Vector
+  // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/interface/fail_interface_missing_member.carbon:[[@LINE+1]]: member access, Scale not in interface Vector where T impls interface Vector
   return a.Scale(s);
 }
 

+ 1 - 1
explorer/testdata/name_lookup/class_fn_body_reorder.carbon

@@ -10,7 +10,7 @@
 package ExplorerTest api;
 
 // The bodies of member functions are processed after all immediately enclosing
-// classes, impls, and interfaces.
+// classes, impl declarations, and interfaces.
 class A {
   fn F[self: Self]() -> i32 {
     return G() + self.H();

+ 1 - 1
explorer/testdata/name_lookup/fail_class_fn_use_before_declaration.carbon

@@ -9,7 +9,7 @@
 package ExplorerTest api;
 
 // The bodies of member functions are processed after all immediately enclosing
-// classes, impls, and interfaces.
+// classes, impl declarations, and interfaces.
 class A {
   fn F() -> type {
     return i32;

+ 1 - 1
explorer/testdata/named_constraint/fail_impl_as_member_access.carbon

@@ -19,7 +19,7 @@ constraint ImplAsHasFoo {
 fn CallFoo[T:! ImplAsHasFoo](x: T) {
   // OK, T is HasFoo.
   x.(HasFoo.Foo)();
-  // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/named_constraint/fail_impl_as_member_access.carbon:[[@LINE+1]]: member access, Foo not in constraint ImplAsHasFoo where T is interface HasFoo
+  // CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/testdata/named_constraint/fail_impl_as_member_access.carbon:[[@LINE+1]]: member access, Foo not in constraint ImplAsHasFoo where T impls interface HasFoo
   x.Foo();
 }
 

+ 1 - 0
toolchain/lexer/token_kind.def

@@ -136,6 +136,7 @@ CARBON_KEYWORD_TOKEN(For,                 "for")
 CARBON_KEYWORD_TOKEN(Friend,              "friend")
 CARBON_KEYWORD_TOKEN(If,                  "if")
 CARBON_KEYWORD_TOKEN(Impl,                "impl")
+CARBON_KEYWORD_TOKEN(Impls,               "impls")
 CARBON_KEYWORD_TOKEN(Import,              "import")
 CARBON_KEYWORD_TOKEN(In,                  "in")
 CARBON_KEYWORD_TOKEN(Interface,           "interface")