Merge pull request #11786 from slavapestov/fix-class-anyobject-4.0

Fix printing of class-constrained protocols [4.0]
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 3f00d4d..0d1ab3a 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -3489,9 +3489,6 @@
 class ProtocolDecl : public NominalTypeDecl {
   SourceLoc ProtocolLoc;
 
-  /// The location of the 'class' keyword for class-bound protocols.
-  SourceLoc ClassRequirementLoc;
-
   /// The syntactic representation of the where clause in a protocol like
   /// `protocol ... where ... { ... }`.
   TrailingWhereClause *TrailingWhere;
@@ -3571,17 +3568,6 @@
     ProtocolDeclBits.RequiresClass = requiresClass;
   }
 
-  /// Specify that this protocol is class-bounded, recording the location of
-  /// the 'class' keyword.
-  void setClassBounded(SourceLoc loc) {
-    ClassRequirementLoc = loc;
-    ProtocolDeclBits.RequiresClassValid = true;
-    ProtocolDeclBits.RequiresClass = true;
-  }
-
-  /// Retrieve the source location of the 'class' keyword.
-  SourceLoc getClassBoundedLoc() const { return ClassRequirementLoc; }
-
   /// Determine whether an existential conforming to this protocol can be
   /// matched with a generic type parameter constrained to this protocol.
   /// This is only permitted if there is nothing "non-trivial" that we
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index 1fc0fd1..d7fa4ce 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -763,7 +763,7 @@
   ParserResult<ImportDecl> parseDeclImport(ParseDeclOptions Flags,
                                            DeclAttributes &Attributes);
   ParserStatus parseInheritance(SmallVectorImpl<TypeLoc> &Inherited,
-                                SourceLoc *classRequirementLoc);
+                                bool allowClassRequirement);
   ParserStatus parseDeclItem(bool &PreviousHadSemi,
                              Parser::ParseDeclOptions Options,
                              llvm::function_ref<void(Decl*)> handler);
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index b9918cb..e1ea1f0 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -989,11 +989,9 @@
   void printInherited(const Decl *decl,
                       ArrayRef<TypeLoc> inherited,
                       ArrayRef<ProtocolDecl *> protos,
-                      Type superclass = {},
-                      bool explicitClass = false);
+                      Type superclass = {});
 
-  void printInherited(const NominalTypeDecl *decl,
-                      bool explicitClass = false);
+  void printInherited(const NominalTypeDecl *decl);
   void printInherited(const EnumDecl *D);
   void printInherited(const ExtensionDecl *decl);
   void printInherited(const GenericTypeParamDecl *D);
@@ -1312,8 +1310,12 @@
 
     // A requirement like Self : Protocol or Self.T : Class might be from an
     // inheritance, or might be a where clause.
-    if (req.getKind() != RequirementKind::Layout && result.second) {
-      auto inherited = req.getSecondType();
+    if (result.second) {
+      Type inherited;
+      if (req.getKind() == RequirementKind::Layout)
+        inherited = proto->getASTContext().getAnyObjectType();
+      else
+        inherited = req.getSecondType();
       inWhereClause =
           none_of(result.first->getInherited(), [&](const TypeLoc &loc) {
             return loc.getType()->isEqual(inherited);
@@ -2049,9 +2051,8 @@
 void PrintAST::printInherited(const Decl *decl,
                               ArrayRef<TypeLoc> inherited,
                               ArrayRef<ProtocolDecl *> protos,
-                              Type superclass,
-                              bool explicitClass) {
-  if (inherited.empty() && superclass.isNull() && !explicitClass) {
+                              Type superclass) {
+  if (inherited.empty() && superclass.isNull()) {
     if (protos.empty())
       return;
   }
@@ -2060,10 +2061,7 @@
     bool PrintedColon = false;
     bool PrintedInherited = false;
 
-    if (explicitClass) {
-      Printer << " : " << tok::kw_class;
-      PrintedInherited = true;
-    } else if (superclass) {
+    if (superclass) {
       bool ShouldPrintSuper = true;
       if (auto NTD = superclass->getAnyNominal()) {
         ShouldPrintSuper = shouldPrint(NTD);
@@ -2115,9 +2113,6 @@
 
     Printer << " : ";
 
-    if (explicitClass)
-      Printer << " " << tok::kw_class << ", ";
-
     interleave(TypesToPrint, [&](TypeLoc TL) {
       printTypeLoc(TL);
     }, [&]() {
@@ -2126,9 +2121,8 @@
   }
 }
 
-void PrintAST::printInherited(const NominalTypeDecl *decl,
-                              bool explicitClass) {
-  printInherited(decl, decl->getInherited(), { }, nullptr, explicitClass);
+void PrintAST::printInherited(const NominalTypeDecl *decl) {
+  printInherited(decl, decl->getInherited(), { }, nullptr);
 }
 
 void PrintAST::printInherited(const EnumDecl *decl) {
@@ -2539,23 +2533,7 @@
         Printer.printName(decl->getName());
       });
 
-    // Figure out whether we need an explicit 'class' in the inheritance.
-    bool explicitClass = false;
-    if (decl->requiresClass() && !decl->isObjC()) {
-      bool inheritsRequiresClass = false;
-      for (auto proto : decl->getLocalProtocols(
-                          ConformanceLookupKind::OnlyExplicit)) {
-        if (proto->requiresClass()) {
-          inheritsRequiresClass = true;
-          break;
-        }
-      }
-
-      if (!inheritsRequiresClass)
-        explicitClass = true;
-    }
-
-    printInherited(decl, explicitClass);
+    printInherited(decl);
 
     // The trailing where clause is a syntactic thing, which isn't serialized
     // (etc.) and thus isn't available for printing things out of
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 17bcc7e..fedd8ee 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2630,13 +2630,11 @@
 ///     type-identifier
 /// \endverbatim
 ParserStatus Parser::parseInheritance(SmallVectorImpl<TypeLoc> &Inherited,
-                                      SourceLoc *classRequirementLoc) {
+                                      bool allowClassRequirement) {
   Scope S(this, ScopeKind::InheritanceClause);
   consumeToken(tok::colon);
 
-  // Clear out the class requirement location.
-  if (classRequirementLoc)
-    *classRequirementLoc = SourceLoc();
+  SourceLoc classRequirementLoc;
 
   ParserStatus Status;
   SourceLoc prevComma;
@@ -2645,7 +2643,7 @@
     if (Tok.is(tok::kw_class)) {
       // If we aren't allowed to have a class requirement here, complain.
       auto classLoc = consumeToken();
-      if (!classRequirementLoc) {
+      if (!allowClassRequirement) {
         SourceLoc endLoc = Tok.is(tok::comma) ? Tok.getLoc() : classLoc;
         diagnose(classLoc, diag::invalid_class_requirement)
           .fixItRemove(SourceRange(classLoc, endLoc));
@@ -2653,9 +2651,9 @@
       }
 
       // If we already saw a class requirement, complain.
-      if (classRequirementLoc->isValid()) {
+      if (classRequirementLoc.isValid()) {
         diagnose(classLoc, diag::redundant_class_requirement)
-          .highlight(*classRequirementLoc)
+          .highlight(classRequirementLoc)
           .fixItRemove(SourceRange(prevComma, classLoc));
         continue;
       }
@@ -2669,7 +2667,12 @@
       }
 
       // Record the location of the 'class' keyword.
-      *classRequirementLoc = classLoc;
+      classRequirementLoc = classLoc;
+
+      // Add 'AnyObject' to the inherited list.
+      Inherited.push_back(
+        new (Context) SimpleIdentTypeRepr(classLoc,
+                                          Context.getIdentifier("AnyObject")));
       continue;
     }
 
@@ -2933,7 +2936,7 @@
   // Parse optional inheritance clause.
   SmallVector<TypeLoc, 2> Inherited;
   if (Tok.is(tok::colon))
-    status |= parseInheritance(Inherited, /*classRequirementLoc=*/nullptr);
+    status |= parseInheritance(Inherited, /*allowClassRequirement=*/false);
 
   // Parse the optional where-clause.
   TrailingWhereClause *trailingWhereClause = nullptr;
@@ -3270,7 +3273,7 @@
   // FIXME: Allow class requirements here.
   SmallVector<TypeLoc, 2> Inherited;
   if (Tok.is(tok::colon))
-    Status |= parseInheritance(Inherited, /*classRequirementLoc=*/nullptr);
+    Status |= parseInheritance(Inherited, /*allowClassRequirement=*/false);
   
   ParserResult<TypeRepr> UnderlyingTy;
   if (Tok.is(tok::equal)) {
@@ -5000,7 +5003,7 @@
   if (Tok.is(tok::colon)) {
     ContextChange CC(*this, ED);
     SmallVector<TypeLoc, 2> Inherited;
-    Status |= parseInheritance(Inherited, /*classRequirementLoc=*/nullptr);
+    Status |= parseInheritance(Inherited, /*allowClassRequirement=*/false);
     ED->setInherited(Context.AllocateCopy(Inherited));
   }
 
@@ -5263,7 +5266,7 @@
   if (Tok.is(tok::colon)) {
     ContextChange CC(*this, SD);
     SmallVector<TypeLoc, 2> Inherited;
-    Status |= parseInheritance(Inherited, /*classRequirementLoc=*/nullptr);
+    Status |= parseInheritance(Inherited, /*allowClassRequirement=*/false);
     SD->setInherited(Context.AllocateCopy(Inherited));
   }
 
@@ -5351,7 +5354,7 @@
   if (Tok.is(tok::colon)) {
     ContextChange CC(*this, CD);
     SmallVector<TypeLoc, 2> Inherited;
-    Status |= parseInheritance(Inherited, /*classRequirementLoc=*/nullptr);
+    Status |= parseInheritance(Inherited, /*allowClassRequirement=*/false);
     CD->setInherited(Context.AllocateCopy(Inherited));
   }
 
@@ -5439,11 +5442,11 @@
   
   // Parse optional inheritance clause.
   SmallVector<TypeLoc, 4> InheritedProtocols;
-  SourceLoc classRequirementLoc;
   SourceLoc colonLoc;
   if (Tok.is(tok::colon)) {
     colonLoc = Tok.getLoc();
-    Status |= parseInheritance(InheritedProtocols, &classRequirementLoc);
+    Status |= parseInheritance(InheritedProtocols,
+                               /*allowClassRequirement=*/true);
   }
 
   TrailingWhereClause *TrailingWhere = nullptr;
@@ -5460,10 +5463,6 @@
                    Context.AllocateCopy(InheritedProtocols), TrailingWhere);
   // No need to setLocalDiscriminator: protocols can't appear in local contexts.
 
-  // If there was a 'class' requirement, mark this as a class-bounded protocol.
-  if (classRequirementLoc.isValid())
-    Proto->setClassBounded(classRequirementLoc);
-
   Proto->getAttrs() = Attributes;
 
   ContextChange CC(*this, Proto);
diff --git a/test/IDE/print_ast_tc_decls.swift b/test/IDE/print_ast_tc_decls.swift
index 34d62ee..406d888 100644
--- a/test/IDE/print_ast_tc_decls.swift
+++ b/test/IDE/print_ast_tc_decls.swift
@@ -486,7 +486,7 @@
 }
 
 protocol d0150_TestClassProtocol : class {}
-// PASS_COMMON-LABEL: {{^}}protocol d0150_TestClassProtocol : class {{{$}}
+// PASS_COMMON-LABEL: {{^}}protocol d0150_TestClassProtocol : AnyObject {{{$}}
 
 @objc protocol d0151_TestClassProtocol {}
 // PASS_COMMON-LABEL: {{^}}@objc protocol d0151_TestClassProtocol {{{$}}
diff --git a/test/IRGen/existentials_objc.sil b/test/IRGen/existentials_objc.sil
index 3a64d16..d84dfb3 100644
--- a/test/IRGen/existentials_objc.sil
+++ b/test/IRGen/existentials_objc.sil
@@ -7,8 +7,11 @@
 
 sil_stage canonical
 
+import Builtin
 import gizmo
 
+typealias AnyObject = Builtin.AnyObject
+
 // rdar://16621578
 
 sil @init_opaque_existential : $@convention(thin) <T where T : Gizmo> (@owned T) -> @out Any {
diff --git a/test/IRGen/fixlifetime.sil b/test/IRGen/fixlifetime.sil
index c6d0d6a..5127d73 100644
--- a/test/IRGen/fixlifetime.sil
+++ b/test/IRGen/fixlifetime.sil
@@ -28,8 +28,12 @@
 // CHECK-native:  call void @__swift_fixLifetime(%swift.refcounted*
 // CHECK-native:  call void bitcast (void (%swift.refcounted*)* @__swift_fixLifetime to void (%T11fixlifetime1CC**)*)(%T11fixlifetime1CC**
 
+import Builtin
+
 sil_stage canonical
 
+typealias AnyObject = Builtin.AnyObject
+
 class C {}
 sil_vtable C {}
 protocol P : class {}
diff --git a/test/IRGen/unowned.sil b/test/IRGen/unowned.sil
index 65a21b5..4eb5253 100644
--- a/test/IRGen/unowned.sil
+++ b/test/IRGen/unowned.sil
@@ -7,8 +7,12 @@
 // CHECK: [[OPAQUE:%swift.opaque]] = type opaque
 // CHECK: [[A:%T7unowned1AV]] = type <{ %swift.unowned }>
 
+import Builtin
+
 class C {}
 sil_vtable C {}
+
+typealias AnyObject = Builtin.AnyObject
 protocol P : class {
   func explode()
 }
diff --git a/test/IRGen/unowned_objc.sil b/test/IRGen/unowned_objc.sil
index 2abf376..5231f96 100644
--- a/test/IRGen/unowned_objc.sil
+++ b/test/IRGen/unowned_objc.sil
@@ -3,6 +3,8 @@
 // REQUIRES: CPU=x86_64
 // XFAIL: linux
 
+import Builtin
+
 //   These types end up in a completely different order with interop disabled.
 // CHECK: [[TYPE:%swift.type]] = type
 // CHECK: [[OPAQUE:%swift.opaque]] = type opaque
@@ -12,6 +14,7 @@
 
 class C {}
 sil_vtable C {}
+typealias AnyObject = Builtin.AnyObject
 protocol P : class {
   func explode()
 }
diff --git a/test/SIL/clone_init_existential.sil b/test/SIL/clone_init_existential.sil
index 5233544..b718fa1 100644
--- a/test/SIL/clone_init_existential.sil
+++ b/test/SIL/clone_init_existential.sil
@@ -7,6 +7,8 @@
 
 import Builtin
 
+typealias AnyObject = Builtin.AnyObject
+
 protocol ClassProto1 : class {
 }
 
diff --git a/test/SIL/ownership-verifier/use_verifier.sil b/test/SIL/ownership-verifier/use_verifier.sil
index 782008b..247dad9 100644
--- a/test/SIL/ownership-verifier/use_verifier.sil
+++ b/test/SIL/ownership-verifier/use_verifier.sil
@@ -15,7 +15,7 @@
 
 sil @allocate_object : $@convention(thin) () -> @owned Builtin.NativeObject
 
-public protocol AnyObject : class {}
+typealias AnyObject = Builtin.AnyObject
 
 public protocol Error {}
 
diff --git a/test/SILGen/class_bound_protocols.swift b/test/SILGen/class_bound_protocols.swift
index d65989d..6b4f90f 100644
--- a/test/SILGen/class_bound_protocols.swift
+++ b/test/SILGen/class_bound_protocols.swift
@@ -7,6 +7,8 @@
 
 precedencegroup AssignmentPrecedence {}
 
+typealias AnyObject = Builtin.AnyObject
+
 // -- Class-bound archetypes and existentials are *not* address-only and can
 //    be manipulated using normal reference type value semantics.
 
diff --git a/test/SILGen/objc_imported_generic.swift b/test/SILGen/objc_imported_generic.swift
index b343828..b89c683 100644
--- a/test/SILGen/objc_imported_generic.swift
+++ b/test/SILGen/objc_imported_generic.swift
@@ -89,9 +89,9 @@
 }
 
 // CHECK-LABEL: sil @_T021objc_imported_generic0C13BlockBridging{{[_0-9a-zA-Z]*}}F
-// CHECK:         [[BLOCK_TO_FUNC:%.*]] = function_ref @_T0xxIyBya_xxIxxo_RlzC21objc_imported_generic7AnsibleRzlTR
+// CHECK:         [[BLOCK_TO_FUNC:%.*]] = function_ref @_T0xxIyBya_xxIxxo_21objc_imported_generic7AnsibleRzlTR
 // CHECK:         partial_apply [[BLOCK_TO_FUNC]]<T>
-// CHECK:         [[FUNC_TO_BLOCK:%.*]] = function_ref @_T0xxIxxo_xxIyBya_RlzC21objc_imported_generic7AnsibleRzlTR
+// CHECK:         [[FUNC_TO_BLOCK:%.*]] = function_ref @_T0xxIxxo_xxIyBya_21objc_imported_generic7AnsibleRzlTR
 // CHECK:         init_block_storage_header {{.*}} invoke [[FUNC_TO_BLOCK]]<T>
 
 // CHECK-LABEL: sil @_T021objc_imported_generic20arraysOfGenericParam{{[_0-9a-zA-Z]*}}F
diff --git a/test/SILOptimizer/address_projection.sil b/test/SILOptimizer/address_projection.sil
index 2c03a65..b4413f2 100644
--- a/test/SILOptimizer/address_projection.sil
+++ b/test/SILOptimizer/address_projection.sil
@@ -5,6 +5,7 @@
 sil_stage canonical
 // CHECK: sil_stage lowered
 
+typealias AnyObject = Builtin.AnyObject
 typealias Int = Builtin.Int64
 
 // CHECK-LABEL: sil hidden @f010_addrlower_identity : $@convention(thin) <T> (@in T) -> @out T {
diff --git a/test/SILOptimizer/rcidentity.sil b/test/SILOptimizer/rcidentity.sil
index ef73830..ebea583 100644
--- a/test/SILOptimizer/rcidentity.sil
+++ b/test/SILOptimizer/rcidentity.sil
@@ -6,6 +6,8 @@
 // NonTest Utilities //
 ///////////////////////
 
+typealias AnyObject = Builtin.AnyObject
+
 protocol FakeAnyObject : class {}
 
 class C : FakeAnyObject {
diff --git a/test/SourceKit/CursorInfo/cursor_info.swift b/test/SourceKit/CursorInfo/cursor_info.swift
index d207eb6..28ad7ac 100644
--- a/test/SourceKit/CursorInfo/cursor_info.swift
+++ b/test/SourceKit/CursorInfo/cursor_info.swift
@@ -600,7 +600,7 @@
 // FIXME: ref.class - rdar://problem/25014968
 
 // RUN: %sourcekitd-test -req=cursor -pos=150:10 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck %s -check-prefix=CHECK66
-// CHECK66: <decl.protocol><syntaxtype.keyword>protocol</syntaxtype.keyword> <decl.name>P2</decl.name> :  <syntaxtype.keyword>class</syntaxtype.keyword>, <ref.protocol usr="s:11cursor_info2P1P">P1</ref.protocol></decl.protocol>
+// CHECK66: <decl.protocol><syntaxtype.keyword>protocol</syntaxtype.keyword> <decl.name>P2</decl.name> : <ref.typealias usr="s:s9AnyObjecta">AnyObject</ref.typealias>, <ref.protocol usr="s:11cursor_info2P1P">P1</ref.protocol></decl.protocol>
 
 // RUN: %sourcekitd-test -req=cursor -pos=114:18 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck %s -check-prefix=CHECK67
 // CHECK67: source.lang.swift.decl.associatedtype (114:18-114:19)
diff --git a/test/decl/protocol/req/class.swift b/test/decl/protocol/req/class.swift
index 3767479..b7d1487 100644
--- a/test/decl/protocol/req/class.swift
+++ b/test/decl/protocol/req/class.swift
@@ -5,5 +5,7 @@
 protocol P2 : class, class { } // expected-error{{redundant 'class' requirement}}{{20-27=}}
 
 protocol P3 : P2, class { } // expected-error{{'class' must come first in the requirement list}}{{15-15=class, }}{{17-24=}}
+// expected-warning@-1 {{redundant layout constraint 'Self' : 'AnyObject'}}
+// expected-note@-2 {{layout constraint constraint 'Self' : 'AnyObject' implied here}}
 
 struct X : class { } // expected-error{{'class' requirement only applies to protocols}} {{12-18=}}