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