Merge pull request #18893 from slavapestov/resilient-class-pattern

Use a true-const pattern to initialize non-generic resilient class metadata
diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h
index 402dd12..41d28fa 100644
--- a/include/swift/AST/TypeCheckRequests.h
+++ b/include/swift/AST/TypeCheckRequests.h
@@ -29,6 +29,7 @@
 
 class GenericParamList;
 class RequirementRepr;
+class SpecializeAttr;
 struct TypeLoc;
 
 /// Display a nominal type or extension thereof.
@@ -220,22 +221,27 @@
 
   /// The source of the where clause, which can be a generic parameter list
   /// or a declaration that can have a where clause.
-  llvm::PointerUnion<GenericParamList *, Decl *> source;
+  llvm::PointerUnion3<GenericParamList *, Decl *, SpecializeAttr *> source;
 
   WhereClauseOwner(Decl *decl);
 
   WhereClauseOwner(DeclContext *dc, GenericParamList *genericParams)
     : dc(dc), source(genericParams) { }
 
+  WhereClauseOwner(DeclContext *dc, SpecializeAttr *attr)
+    : dc(dc), source(attr) { }
+
   SourceLoc getLoc() const;
 
   friend hash_code hash_value(const WhereClauseOwner &owner) {
-    return hash_combine(hash_value(owner.dc), hash_value(owner.source));
+    return hash_combine(hash_value(owner.dc),
+                        hash_value(owner.source.getOpaqueValue()));
   }
 
   friend bool operator==(const WhereClauseOwner &lhs,
                          const WhereClauseOwner &rhs) {
-    return lhs.dc == rhs.dc && lhs.source == rhs.source;
+    return lhs.dc == rhs.dc &&
+           lhs.source.getOpaqueValue() == rhs.source.getOpaqueValue();
   }
 
   friend bool operator!=(const WhereClauseOwner &lhs,
diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp
index fe58b22..c4ae808 100644
--- a/lib/AST/TypeCheckRequests.cpp
+++ b/lib/AST/TypeCheckRequests.cpp
@@ -259,6 +259,9 @@
   if (auto decl = source.dyn_cast<Decl *>())
     return decl->getLoc();
 
+  if (auto attr = source.dyn_cast<SpecializeAttr *>())
+    return attr->getLocation();
+
   return source.get<GenericParamList *>()->getWhereLoc();
 }
 
@@ -266,6 +269,8 @@
                            const WhereClauseOwner &owner) {
   if (auto decl = owner.source.dyn_cast<Decl *>()) {
     simple_display(out, decl);
+  } else if (owner.source.is<SpecializeAttr *>()) {
+    out << "@_specialize";
   } else {
     out << "(SIL generic parameter list)";
   }
@@ -289,6 +294,13 @@
     return genericParams->getRequirements();
   }
 
+  if (auto attr = owner.source.dyn_cast<SpecializeAttr *>()) {
+    if (auto whereClause = attr->getTrailingWhereClause())
+      return whereClause->getRequirements();
+    
+    return { };
+  }
+
   auto decl = owner.source.dyn_cast<Decl *>();
   if (!decl)
     return { };
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index 3cde833..3eb1b4a 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -1243,8 +1243,12 @@
   // Apply sanitizer attributes to the function.
   // TODO: Check if the function is supposed to be excluded from ASan either by
   // being in the external file or via annotations.
-  if (IGM.IRGen.Opts.Sanitizers & SanitizerKind::Address)
-    CurFn->addFnAttr(llvm::Attribute::SanitizeAddress);
+  if (IGM.IRGen.Opts.Sanitizers & SanitizerKind::Address) {
+    // Disable ASan in coroutines; stack poisoning is not going to do
+    // reasonable things to the structural invariants.
+    if (!f->getLoweredFunctionType()->isCoroutine())
+      CurFn->addFnAttr(llvm::Attribute::SanitizeAddress);
+  }
   if (IGM.IRGen.Opts.Sanitizers & SanitizerKind::Thread) {
     auto declContext = f->getDeclContext();
     if (declContext && isa<DestructorDecl>(declContext))
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index 84e3f2d..fc07197 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -23,6 +23,7 @@
 #include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/NameLookup.h"
 #include "swift/AST/ParameterList.h"
+#include "swift/AST/TypeCheckRequests.h"
 #include "swift/AST/Types.h"
 #include "swift/Parse/Lexer.h"
 #include "llvm/Support/Debug.h"
@@ -1581,131 +1582,9 @@
 static void checkSpecializeAttrRequirements(
     SpecializeAttr *attr,
     AbstractFunctionDecl *FD,
-    ArrayRef<RequirementRepr> requirements,
-    SmallPtrSet<TypeBase *, 4> constrainedGenericParams,
+    const SmallPtrSet<TypeBase *, 4> &constrainedGenericParams,
     TypeChecker &TC) {
   auto genericSig = FD->getGenericSignature();
-  bool isInvalidAttr = false;
-
-  // Check that requirements are defined only on
-  // generic parameter types and not on their associated or dependent types or
-  // other generic types using these parameters.
-  for (auto &req : requirements) {
-    if (req.getKind() == RequirementReprKind::SameType) {
-      auto firstType = req.getFirstType();
-      auto secondType = req.getSecondType();
-
-      if (!firstType || firstType->is<ErrorType>() ||
-          firstType->hasArchetype()) {
-        isInvalidAttr = true;
-        continue;
-      }
-
-      if (!secondType || secondType->is<ErrorType>() ||
-          secondType->hasArchetype()) {
-        isInvalidAttr = true;
-        continue;
-      }
-
-      collectUsedGenericParameters(firstType, constrainedGenericParams);
-      collectUsedGenericParameters(secondType, constrainedGenericParams);
-
-      // One of the types should be concrete and the other one should not.
-      bool isFirstTypeNonConcrete = firstType->hasTypeParameter();
-      bool isSecondTypeNonConcrete = secondType->hasTypeParameter();
-
-      if (isFirstTypeNonConcrete && isSecondTypeNonConcrete) {
-        TC.diagnose(attr->getLocation(),
-                    diag::specialize_attr_non_concrete_same_type_req)
-            .highlight(req.getSourceRange());
-        continue;
-      }
-      if (!(isFirstTypeNonConcrete ^ isSecondTypeNonConcrete)) {
-        TC.diagnose(attr->getLocation(),
-                    diag::specialize_attr_only_one_concrete_same_type_req)
-            .highlight(req.getSourceRange());
-        continue;
-      }
-      if (isFirstTypeNonConcrete) {
-        if (!isa<GenericTypeParamType>(firstType->getCanonicalType())) {
-          TC.diagnose(attr->getLocation(),
-                      diag::specialize_attr_only_generic_param_req)
-              .highlight(req.getFirstTypeRepr()->getSourceRange());
-        }
-      }
-      if (isSecondTypeNonConcrete) {
-        if (!isa<GenericTypeParamType>(secondType->getCanonicalType())) {
-          TC.diagnose(attr->getLocation(),
-                      diag::specialize_attr_only_generic_param_req)
-              .highlight(req.getSecondTypeRepr()->getSourceRange());
-        }
-      }
-      continue;
-    }
-
-    if (req.getKind() == RequirementReprKind::LayoutConstraint ||
-        req.getKind() == RequirementReprKind::TypeConstraint) {
-      auto subjectType = req.getSubject();
-
-      // Skip any unknown or error types.
-      if (!subjectType || subjectType->is<ErrorType>() ||
-          subjectType->hasArchetype()) {
-        isInvalidAttr = true;
-        continue;
-      }
-
-      if (req.getKind() == RequirementReprKind::TypeConstraint) {
-        auto constraint = req.getConstraint();
-
-        if (!constraint || constraint->hasError() ||
-            constraint->hasArchetype()) {
-          isInvalidAttr = true;
-          continue;
-        }
-
-        auto nominalTy = constraint->getNominalOrBoundGenericNominal();
-        if (!nominalTy) {
-          TC.diagnose(attr->getLocation(),
-                      diag::specialize_attr_non_nominal_type_constraint_req)
-              .highlight(req.getSourceRange());
-          continue;
-        }
-
-        auto proto = dyn_cast<ProtocolDecl>(nominalTy);
-        if (!proto) {
-          TC.diagnose(attr->getLocation(),
-                      diag::specialize_attr_non_protocol_type_constraint_req)
-              .highlight(req.getSourceRange());
-        }
-      }
-
-      bool isSubjectNonConcrete = subjectType->hasTypeParameter();
-
-      if (isSubjectNonConcrete) {
-        collectUsedGenericParameters(subjectType, constrainedGenericParams);
-        if (!isa<GenericTypeParamType>(subjectType->getCanonicalType())) {
-          TC.diagnose(attr->getLocation(),
-                      diag::specialize_attr_only_generic_param_req)
-              .highlight(req.getSubjectRepr()->getSourceRange());
-        }
-      }
-
-      if (req.getKind() == RequirementReprKind::TypeConstraint) {
-        TC.diagnose(attr->getLocation(),
-                    diag::specialize_attr_unsupported_kind_of_req)
-            .highlight(req.getSourceRange());
-      }
-      continue;
-    }
-
-    TC.diagnose(attr->getLocation(),
-                diag::specialize_attr_unsupported_kind_of_req)
-        .highlight(req.getSourceRange());
-  }
-
-  if (isInvalidAttr) {
-    attr->setInvalid();
-  }
 
   if (!attr->isFullSpecialization())
     return;
@@ -1748,6 +1627,21 @@
   }
 }
 
+/// Require that the given type either not involve type parameters or be
+/// a type parameter.
+static bool diagnoseIndirectGenericTypeParam(SourceLoc loc, Type type,
+                                             TypeRepr *typeRepr) {
+  if (type->hasTypeParameter() && !type->is<GenericTypeParamType>()) {
+    type->getASTContext().Diags.diagnose(
+        loc,
+        diag::specialize_attr_only_generic_param_req)
+      .highlight(typeRepr->getSourceRange());
+    return true;
+  }
+
+  return false;
+}
+
 /// Type check that a set of requirements provided by @_specialize.
 /// Store the set of requirements in the attribute.
 void AttributeChecker::visitSpecializeAttr(SpecializeAttr *attr) {
@@ -1783,163 +1677,111 @@
   // First, add the old generic signature.
   Builder.addGenericSignature(genericSig);
 
-  SmallVector<Requirement, 4> convertedRequirements;
-  SmallVector<RequirementRepr, 4> resolvedRequirements;
-
   // Set of generic parameters being constrained. It is used to
   // determine if a full specialization misses requirements for
   // some of the generic parameters.
   SmallPtrSet<TypeBase *, 4> constrainedGenericParams;
 
-  // Go over the set of requirements and resolve their types.
-  auto resolution = TypeResolution::forContextual(FD);
-  for (auto &req : trailingWhereClause->getRequirements()) {
-    if (req.getKind() == RequirementReprKind::SameType) {
-      auto firstType = resolution.resolveType(req.getFirstTypeRepr(),
-                                              None);
-      auto secondType = resolution.resolveType(req.getSecondTypeRepr(),
-                                               None);
-      Type interfaceFirstType;
-      Type interfaceSecondType;
+  // Go over the set of requirements, adding them to the builder.
+  SmallVector<Requirement, 4> convertedRequirements;
+  RequirementRequest::visitRequirements(
+      WhereClauseOwner(FD, attr), TypeResolutionStage::Interface,
+      [&](const Requirement &req, RequirementRepr *reqRepr) {
+        // Collect all of the generic parameters used by these types.
+        switch (req.getKind()) {
+        case RequirementKind::Conformance:
+        case RequirementKind::SameType:
+        case RequirementKind::Superclass:
+          collectUsedGenericParameters(req.getSecondType(),
+                                       constrainedGenericParams);
+          LLVM_FALLTHROUGH;
 
-      // Map types to their interface types.
-      if (firstType)
-        interfaceFirstType = firstType->mapTypeOutOfContext();
-      if (secondType)
-        interfaceSecondType = secondType->mapTypeOutOfContext();
+        case RequirementKind::Layout:
+          collectUsedGenericParameters(req.getFirstType(),
+                                       constrainedGenericParams);
+          break;
+        }
 
-      collectUsedGenericParameters(interfaceFirstType,
-                                   constrainedGenericParams);
-      collectUsedGenericParameters(interfaceSecondType,
-                                   constrainedGenericParams);
+        // Check additional constraints.
+        // FIXME: These likely aren't fundamental limitations.
+        switch (req.getKind()) {
+        case RequirementKind::SameType: {
+          bool firstHasTypeParameter = req.getFirstType()->hasTypeParameter();
+          bool secondHasTypeParameter = req.getSecondType()->hasTypeParameter();
 
-      // Skip any unknown or error types.
-      if (!firstType || firstType->is<ErrorType>() || !secondType ||
-          secondType->is<ErrorType>())
-        continue;
+          // Exactly one type can have a type parameter.
+          if (firstHasTypeParameter == secondHasTypeParameter) {
+            TC.diagnose(
+                attr->getLocation(),
+                firstHasTypeParameter
+                  ? diag::specialize_attr_non_concrete_same_type_req
+                  : diag::specialize_attr_only_one_concrete_same_type_req)
+              .highlight(reqRepr->getSourceRange());
+            return false;
+          }
 
-      Type genericType;
-      Type concreteType;
-      if (interfaceFirstType->hasTypeParameter()) {
-        genericType = interfaceFirstType;
-        concreteType = interfaceSecondType;
-      } else {
-        genericType = interfaceSecondType;
-        concreteType = interfaceFirstType;
-      }
-      // Add a resolved requirement.
-      if (interfaceFirstType->hasTypeParameter()) {
-        resolvedRequirements.push_back(RequirementRepr::getSameType(
-            TypeLoc(req.getFirstTypeRepr(), genericType), req.getEqualLoc(),
-            TypeLoc(req.getSecondTypeRepr(), concreteType)));
-      } else {
-        resolvedRequirements.push_back(RequirementRepr::getSameType(
-            TypeLoc(req.getFirstTypeRepr(), concreteType), req.getEqualLoc(),
-            TypeLoc(req.getSecondTypeRepr(), genericType)));
-      }
+          // We either need a fully-concrete type or a generic type parameter.
+          if (diagnoseIndirectGenericTypeParam(attr->getLocation(),
+                                               req.getFirstType(),
+                                               reqRepr->getFirstTypeRepr()) ||
+              diagnoseIndirectGenericTypeParam(attr->getLocation(),
+                                               req.getSecondType(),
+                                               reqRepr->getSecondTypeRepr())) {
+            return false;
+          }
+          break;
+        }
 
-      // Convert the requirement into a semantic form.
-      Requirement convertedRequirement(RequirementKind::SameType,
-                                       genericType, concreteType);
-      convertedRequirements.push_back(convertedRequirement);
-      continue;
-    }
+        case RequirementKind::Superclass:
+          TC.diagnose(attr->getLocation(),
+                      diag::specialize_attr_non_protocol_type_constraint_req)
+            .highlight(reqRepr->getSourceRange());
+          return false;
 
-    if (req.getKind() == RequirementReprKind::LayoutConstraint) {
-      auto subjectType = resolution.resolveType(req.getSubjectRepr(),
-                                                None);
-      Type interfaceSubjectType;
+        case RequirementKind::Conformance:
+          if (diagnoseIndirectGenericTypeParam(attr->getLocation(),
+                                               req.getFirstType(),
+                                               reqRepr->getSubjectRepr())) {
+            return false;
+          }
 
-      // Map types to their interface types.
-      if (subjectType)
-        interfaceSubjectType = subjectType->mapTypeOutOfContext();
+          if (!req.getSecondType()->is<ProtocolType>()) {
+            TC.diagnose(attr->getLocation(),
+                        diag::specialize_attr_non_protocol_type_constraint_req)
+              .highlight(reqRepr->getSourceRange());
+            return false;
+          }
 
-      collectUsedGenericParameters(interfaceSubjectType,
-                                   constrainedGenericParams);
+          TC.diagnose(attr->getLocation(),
+                      diag::specialize_attr_unsupported_kind_of_req)
+            .highlight(reqRepr->getSourceRange());
 
-      // Skip any unknown or error types.
-      if (!subjectType || subjectType->is<ErrorType>() ||
-          !req.getLayoutConstraint() ||
-          !req.getLayoutConstraint()->isKnownLayout())
-        continue;
+          return false;
 
-      // Re-create a requirement using the resolved interface types.
-      auto resolvedReq = RequirementRepr::getLayoutConstraint(
-          TypeLoc(req.getSubjectRepr(), interfaceSubjectType),
-          req.getColonLoc(),
-          req.getLayoutConstraintLoc());
+        case RequirementKind::Layout:
+          if (diagnoseIndirectGenericTypeParam(attr->getLocation(),
+                                               req.getFirstType(),
+                                               reqRepr->getSubjectRepr())) {
+            return false;
+          }
+          break;
+        }
 
-      // Add a resolved requirement.
-      resolvedRequirements.push_back(resolvedReq);
-
-      // Convert the requirement into a semantic form.
-      Requirement convertedRequirement(RequirementKind::Layout,
-                                       interfaceSubjectType,
-                                       req.getLayoutConstraint());
-      convertedRequirements.push_back(convertedRequirement);
-      continue;
-    }
-
-    if (req.getKind() == RequirementReprKind::TypeConstraint) {
-      auto subjectType = resolution.resolveType(req.getSubjectRepr(), None);
-      auto constraint = resolution.resolveType(req.getConstraintLoc().getTypeRepr(), None);
-
-      Type interfaceSubjectType;
-
-      // Map types to their interface types.
-      if (subjectType)
-        interfaceSubjectType = subjectType->mapTypeOutOfContext();
-
-      collectUsedGenericParameters(interfaceSubjectType,
-                                   constrainedGenericParams);
-
-      // Skip any unknown or error types.
-      if (!subjectType || subjectType->hasError() ||
-          !constraint || constraint->hasError())
-        continue;
-
-      auto interfaceLayoutConstraint = constraint->mapTypeOutOfContext();
-
-      // Re-create a requirement using the resolved interface types.
-      auto resolvedReq = RequirementRepr::getTypeConstraint(
-          TypeLoc(req.getSubjectRepr(), interfaceSubjectType),
-          req.getColonLoc(),
-          TypeLoc(req.getConstraintRepr(), interfaceLayoutConstraint));
-
-      // Add a resolved requirement.
-      resolvedRequirements.push_back(resolvedReq);
-
-      // Convert the requirement into a semantic form.
-      Requirement convertedRequirement(
-          RequirementKind::Conformance,
-          interfaceSubjectType,
-          interfaceLayoutConstraint);
-      convertedRequirements.push_back(convertedRequirement);
-      continue;
-    }
-  }
+        // Add the requirement to the generic signature builder.
+        using FloatingRequirementSource =
+          GenericSignatureBuilder::FloatingRequirementSource;
+        Builder.addRequirement(req, reqRepr,
+                               FloatingRequirementSource::forExplicit(reqRepr),
+                               nullptr, DC->getParentModule());
+        convertedRequirements.push_back(getCanonicalRequirement(req));
+        return false;
+      });
 
   // Check the validity of provided requirements.
-  checkSpecializeAttrRequirements(attr, FD, resolvedRequirements,
-                                  constrainedGenericParams, TC);
+  checkSpecializeAttrRequirements(attr, FD, constrainedGenericParams, TC);
 
-  // Add the requirements to the builder.
-  assert(resolvedRequirements.size() == convertedRequirements.size());
-  using FloatingRequirementSource =
-    GenericSignatureBuilder::FloatingRequirementSource;
-  for (unsigned index : indices(convertedRequirements)) {
-    Builder.addRequirement(convertedRequirements[index],
-                           &resolvedRequirements[index],
-                           FloatingRequirementSource::forExplicit(
-                                                  &resolvedRequirements[index]),
-                           nullptr, DC->getParentModule());
-  }
-
-  // Canonicalize and store converted requirements in the attribute so that
+  // Store the converted requirements in the attribute so that
   // they are serialized later.
-  for (auto &req : convertedRequirements) {
-    req = getCanonicalRequirement(req);
-  }
   attr->setRequirements(DC->getASTContext(), convertedRequirements);
 
   // Check the result.
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 89d88a0..b2c8711 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -2518,7 +2518,7 @@
 }
 
 /// Determine the given witness has a same-type constraint constraining the
-/// given 'Self' type, and return the
+/// given 'Self' type, and return the requirement that does.
 ///
 /// \returns None if there is no such constraint; a non-empty optional that
 /// may have the \c RequirementRepr for the actual constraint.
diff --git a/test/IRGen/asan-attributes.swift b/test/IRGen/asan-attributes.swift
index dc0c680..f39c21e 100644
--- a/test/IRGen/asan-attributes.swift
+++ b/test/IRGen/asan-attributes.swift
@@ -1,8 +1,22 @@
 // This test verifies that we add the function attributes used by ASan.
 
-// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir -sanitize=address %s | %FileCheck %s -check-prefix=ASAN
+// RUN: %target-swift-frontend -emit-ir -disable-llvm-optzns -sanitize=address %s | %FileCheck %s -check-prefix=ASAN
 
-func test() {
+// ASAN: define {{.*}} @"$S4main4testyyF"() [[DEFAULT_ATTRS:#[0-9]+]]
+public func test() {
 }
 
-// ASAN: Function Attrs: sanitize_address
+// ASAN: define {{.*}} @"$S4main1xSivr"({{.*}}) [[COROUTINE_ATTRS:#[0-9]+]]
+public var x: Int {
+  _read {
+    yield 0
+  }
+}
+
+// ASAN: attributes [[DEFAULT_ATTRS]] =
+// ASAN-SAME: sanitize_address
+// ASAN-SAME: }
+
+// ASAN: attributes [[COROUTINE_ATTRS]] =
+// ASAN-NOT: sanitize_address
+// ASAN-SAME: }
diff --git a/test/attr/attr_specialize.swift b/test/attr/attr_specialize.swift
index abcd9f9..2546964 100644
--- a/test/attr/attr_specialize.swift
+++ b/test/attr/attr_specialize.swift
@@ -27,6 +27,7 @@
 // CHECK: @_specialize(exported: false, kind: full, where T == S<Int>)
 @_specialize(where T == S<Int>)
 @_specialize(where T == Int, U == Int) // expected-error{{use of undeclared type 'U'}},
+// expected-error@-1{{Only one concrete type should be used in the same-type requirement in '_specialize' attribute}}
 @_specialize(where T == T1) // expected-error{{use of undeclared type 'T1'}}
 public func oneGenericParam<T>(_ t: T) -> T {
   return t
@@ -49,10 +50,9 @@
   // CHECK: @_specialize(exported: false, kind: full, where T == Int)
   @_specialize(where T == Int)
   @_specialize(where T == T) // expected-error{{Only concrete type same-type requirements are supported by '_specialize' attribute}}
-	// expected-warning@-1{{redundant same-type constraint 'T' == 'T'}}
   @_specialize(where T == S<T>) // expected-error{{Only concrete type same-type requirements are supported by '_specialize' attribute}}
-	// expected-error@-1{{same-type constraint 'T' == 'S<T>' is recursive}}
   @_specialize(where T == Int, U == Int) // expected-error{{use of undeclared type 'U'}}
+  // expected-error@-1{{Only one concrete type should be used in the same-type requirement in '_specialize' attribute}}
   func noGenericParams() {}
 
   // CHECK: @_specialize(exported: false, kind: full, where T == Int, U == Float)
@@ -109,11 +109,13 @@
 
 
 @_specialize(where X:_Trivial(8), Y:_Trivial(32), Z == Int) // expected-error{{use of undeclared type 'Z'}}
+// expected-error@-1{{Only one concrete type should be used in the same-type requirement in '_specialize' attribute}}
 @_specialize(where X:_Trivial(8), Y:_Trivial(32, 4))
 @_specialize(where X == Int) // expected-error{{too few type parameters are specified in '_specialize' attribute (got 1, but expected 2)}} expected-error{{Missing constraint for 'Y' in '_specialize' attribute}}
 @_specialize(where Y:_Trivial(32)) // expected-error {{too few type parameters are specified in '_specialize' attribute (got 1, but expected 2)}} expected-error{{Missing constraint for 'X' in '_specialize' attribute}}
 @_specialize(where Y: P) // expected-error{{Only same-type and layout requirements are supported by '_specialize' attribute}} expected-error{{too few type parameters are specified in '_specialize' attribute (got 1, but expected 2)}} expected-error{{Missing constraint for 'X' in '_specialize' attribute}}
 @_specialize(where Y: MyClass) // expected-error{{use of undeclared type 'MyClass'}} expected-error{{too few type parameters are specified in '_specialize' attribute (got 1, but expected 2)}} expected-error{{Missing constraint for 'X' in '_specialize' attribute}}
+// expected-error@-1{{Only conformances to protocol types are supported by '_specialize' attribute}}
 @_specialize(where X:_Trivial(8), Y == Int)
 @_specialize(where X == Int, Y == Int)
 @_specialize(where X == Int, X == Int) // expected-error{{too few type parameters are specified in '_specialize' attribute (got 1, but expected 2)}} expected-error{{Missing constraint for 'Y' in '_specialize' attribute}}
@@ -121,6 +123,7 @@
 // expected-note@-2{{same-type constraint 'X' == 'Int' written here}}
 @_specialize(where Y:_Trivial(32), X == Float)
 @_specialize(where X1 == Int, Y1 == Int) // expected-error{{use of undeclared type 'X1'}} expected-error{{use of undeclared type 'Y1'}} expected-error{{too few type parameters are specified in '_specialize' attribute (got 0, but expected 2)}} expected-error{{Missing constraint for 'X' in '_specialize' attribute}} expected-error{{Missing constraint for 'Y' in '_specialize' attribute}}
+// expected-error@-1 2{{Only one concrete type should be used in the same-type requirement in '_specialize' attribute}}
 public func funcWithTwoGenericParameters<X, Y>(x: X, y: Y) {
 }
 
@@ -146,17 +149,16 @@
 @_specialize(kind: partial, kind: partial, where X == Int, Y == Int) // expected-error{{parameter 'kind' was already defined in '_specialize' attribute}}
 
 @_specialize(where X == Int, Y == Int, exported: true, kind: partial) // expected-error{{use of undeclared type 'exported'}} expected-error{{use of undeclared type 'kind'}} expected-error{{use of undeclared type 'partial'}} expected-error{{expected type}}
+// expected-error@-1 2{{Only conformances to protocol types are supported by '_specialize' attribute}}
 public func anotherFuncWithTwoGenericParameters<X: P, Y>(x: X, y: Y) {
 }
 
 @_specialize(where T: P) // expected-error{{Only same-type and layout requirements are supported by '_specialize' attribute}}
-@_specialize(where T: Int) // expected-error{{Only conformances to protocol types are supported by '_specialize' attribute}} expected-error{{Only same-type and layout requirements are supported by '_specialize' attribute}}
-// expected-error@-1{{type 'T' constrained to non-protocol, non-class type 'Int'}}
+@_specialize(where T: Int) // expected-error{{Only conformances to protocol types are supported by '_specialize' attribute}}
 
-@_specialize(where T: S1) // expected-error{{Only conformances to protocol types are supported by '_specialize' attribute}} expected-error{{Only same-type and layout requirements are supported by '_specialize' attribute}}
-// expected-error@-1{{type 'T' constrained to non-protocol, non-class type 'S1'}}
-@_specialize(where T: C1) // expected-error{{Only conformances to protocol types are supported by '_specialize' attribute}} expected-error{{Only same-type and layout requirements are supported by '_specialize' attribute}}
-@_specialize(where Int: P) // expected-error{{type 'Int' in conformance requirement does not refer to a generic parameter or associated type}} expected-error{{Only same-type and layout requirements are supported by '_specialize' attribute}} expected-error{{too few type parameters are specified in '_specialize' attribute (got 0, but expected 1)}} expected-error{{Missing constraint for 'T' in '_specialize' attribute}}
+@_specialize(where T: S1) // expected-error{{Only conformances to protocol types are supported by '_specialize' attribute}}
+@_specialize(where T: C1) // expected-error{{Only conformances to protocol types are supported by '_specialize' attribute}}
+@_specialize(where Int: P) // expected-error{{Only same-type and layout requirements are supported by '_specialize' attribute}} expected-error{{too few type parameters are specified in '_specialize' attribute (got 0, but expected 1)}} expected-error{{Missing constraint for 'T' in '_specialize' attribute}}
 func funcWithForbiddenSpecializeRequirement<T>(_ t: T) {
 }
 
@@ -172,7 +174,6 @@
 // expected-warning@-1{{redundant constraint 'T' : '_RefCountedObject'}}
 // expected-note@-2 1{{constraint 'T' : '_NativeRefCountedObject' written here}}
 @_specialize(where Array<T> == Int) // expected-error{{Only requirements on generic parameters are supported by '_specialize' attribute}}
-// expected-error@-1{{generic signature requires types 'Array<T>' and 'Int' to be the same}}
 @_specialize(where T.Element == Int) // expected-error{{Only requirements on generic parameters are supported by '_specialize' attribute}}
 public func funcWithComplexSpecializeRequirements<T: ProtocolWithDep>(t: T) -> Int {
   return 55555