[GSB] Track all conformance constraint sources.

Move the storage for the protocols to which a particular potential
archetype conforms into EquivalenceClass, so that it is more easily
shared. More importantly, keep track of *all* of the constraint
sources that produced a particular conformance requirement, so we can
revisit them later, which provides a number of improvements:

* We can drop self-derived requirements at the end, once we've
  established all of the equivalence classes
* We diagnose redundant conformance requirements, e.g., "T: Sequence"
  is redundant if "T: Collection" is already specified.
* We can choose the best path when forming the conformance access
  path.
This commit is contained in:
Doug Gregor
2017-03-06 16:36:16 -08:00
parent c443739d68
commit eaee4add8a
13 changed files with 254 additions and 155 deletions

View File

@@ -1571,6 +1571,12 @@ ERROR(requires_same_concrete_type,none,
ERROR(protocol_typealias_conflict, none, ERROR(protocol_typealias_conflict, none,
"typealias %0 requires types %1 and %2 to be the same", "typealias %0 requires types %1 and %2 to be the same",
(Identifier, Type, Type)) (Identifier, Type, Type))
WARNING(redundant_conformance_constraint,none,
"redundant conformance constraint %0: %1", (Type, ProtocolDecl *))
NOTE(redundant_conformance_here,none,
"conformance constraint %1: %2 %select{written here|implied here}0",
(bool, Type, ProtocolDecl *))
WARNING(redundant_same_type_to_concrete,none, WARNING(redundant_same_type_to_concrete,none,
"redundant same-type constraint %0 == %1", (Type, Type)) "redundant same-type constraint %0 == %1", (Type, Type))
NOTE(same_type_redundancy_here,none, NOTE(same_type_redundancy_here,none,

View File

@@ -96,6 +96,14 @@ public:
/// Describes an equivalence class of potential archetypes. /// Describes an equivalence class of potential archetypes.
struct EquivalenceClass { struct EquivalenceClass {
/// The list of protocols to which this equivalence class conforms.
///
/// The keys form the (semantic) list of protocols to which this type
/// conforms. The values are the conformance constraints as written on
/// this equivalence class.
llvm::MapVector<ProtocolDecl *, std::vector<Constraint<ProtocolDecl *>>>
conformsTo;
/// Concrete type to which this equivalence class is equal. /// Concrete type to which this equivalence class is equal.
/// ///
/// This is the semantic concrete type; the constraints as written /// This is the semantic concrete type; the constraints as written
@@ -134,7 +142,11 @@ public:
Optional<ConcreteConstraint> Optional<ConcreteConstraint>
findAnySuperclassConstraintAsWritten( findAnySuperclassConstraintAsWritten(
PotentialArchetype *preferredPA = nullptr) const; PotentialArchetype *preferredPA = nullptr) const;
};
/// Determine whether conformance to the given protocol is satisfied by
/// a superclass requirement.
bool isConformanceSatisfiedBySuperclass(ProtocolDecl *proto) const;
};
friend class RequirementSource; friend class RequirementSource;
@@ -166,13 +178,9 @@ private:
/// queried. /// queried.
/// ///
/// \param proto The protocol to which we are establishing conformance. /// \param proto The protocol to which we are establishing conformance.
///
/// \param protoSource The requirement source for the conformance to the
/// given protocol.
const RequirementSource *resolveSuperConformance( const RequirementSource *resolveSuperConformance(
GenericSignatureBuilder::PotentialArchetype *pa, GenericSignatureBuilder::PotentialArchetype *pa,
ProtocolDecl *proto, ProtocolDecl *proto);
const RequirementSource *&protoSource);
/// \brief Add a new conformance requirement specifying that the given /// \brief Add a new conformance requirement specifying that the given
/// potential archetype conforms to the given protocol. /// potential archetype conforms to the given protocol.
@@ -462,6 +470,12 @@ private:
ArrayRef<GenericTypeParamType *> genericParams, ArrayRef<GenericTypeParamType *> genericParams,
PotentialArchetype *pa); PotentialArchetype *pa);
/// Check conformance constraints within the equivalence class of the
/// given potential archetype.
void checkConformanceConstraints(
ArrayRef<GenericTypeParamType *> genericParams,
PotentialArchetype *pa);
public: public:
/// \brief Resolve the given type to the potential archetype it names. /// \brief Resolve the given type to the potential archetype it names.
/// ///
@@ -1016,9 +1030,6 @@ class GenericSignatureBuilder::PotentialArchetype {
llvm::MapVector<PotentialArchetype *, const RequirementSource *> llvm::MapVector<PotentialArchetype *, const RequirementSource *>
SameTypeConstraints; SameTypeConstraints;
/// \brief The list of protocols to which this archetype will conform.
llvm::MapVector<ProtocolDecl *, const RequirementSource *> ConformsTo;
/// \brief The layout constraint of this archetype, if specified. /// \brief The layout constraint of this archetype, if specified.
LayoutConstraint Layout; LayoutConstraint Layout;
@@ -1215,16 +1226,23 @@ public:
return dyn_cast<TypeAliasDecl>(identifier.assocTypeOrAlias); return dyn_cast<TypeAliasDecl>(identifier.assocTypeOrAlias);
} }
/// Retrieve the set of protocols to which this type conforms. /// Retrieve the set of protocols to which this potential archetype
llvm::MapVector<ProtocolDecl *, const RequirementSource *> & /// conforms.
getConformsTo() { SmallVector<ProtocolDecl *, 4> getConformsTo() const {
return ConformsTo; SmallVector<ProtocolDecl *, 4> result;
if (auto equiv = getEquivalenceClassIfPresent()) {
for (const auto &entry : equiv->conformsTo)
result.push_back(entry.first);
}
return result;
} }
/// Add a conformance to this potential archetype. /// Add a conformance to this potential archetype.
/// ///
/// \returns true if the conformance was new, false if it already existed. /// \returns true if the conformance was new, false if it already existed.
bool addConformance(ProtocolDecl *proto, bool updateExistingSource, bool addConformance(ProtocolDecl *proto,
const RequirementSource *source, const RequirementSource *source,
GenericSignatureBuilder &builder); GenericSignatureBuilder &builder);

View File

@@ -528,7 +528,7 @@ bool GenericSignature::requiresClass(Type type, ModuleDecl &mod) {
// If any of the protocols are class-bound, then it must be a class. // If any of the protocols are class-bound, then it must be a class.
for (auto proto : pa->getConformsTo()) { for (auto proto : pa->getConformsTo()) {
if (proto.first->requiresClass()) return true; if (proto->requiresClass()) return true;
} }
return false; return false;
@@ -571,7 +571,7 @@ SmallVector<ProtocolDecl *, 2> GenericSignature::getConformsTo(Type type,
// Retrieve the protocols to which this type conforms. // Retrieve the protocols to which this type conforms.
SmallVector<ProtocolDecl *, 2> result; SmallVector<ProtocolDecl *, 2> result;
for (auto proto : pa->getConformsTo()) for (auto proto : pa->getConformsTo())
result.push_back(proto.first); result.push_back(proto);
// Canonicalize the resulting set of protocols. // Canonicalize the resulting set of protocols.
ProtocolType::canonicalizeProtocols(result); ProtocolType::canonicalizeProtocols(result);
@@ -738,6 +738,26 @@ static Type eraseAssociatedTypes(Type type) {
return type; return type;
} }
namespace {
typedef GenericSignatureBuilder::RequirementSource RequirementSource;
template<typename T>
using GSBConstraint = GenericSignatureBuilder::Constraint<T>;
}
/// Retrieve the best requirement source from the list
static const RequirementSource *
getBestRequirementSource(ArrayRef<GSBConstraint<ProtocolDecl *>> constraints) {
const RequirementSource *bestSource = nullptr;
for (const auto &constraint : constraints) {
auto source = constraint.source;
if (!bestSource || source->compare(bestSource) < 0)
bestSource = source;
}
return bestSource;
}
ConformanceAccessPath GenericSignature::getConformanceAccessPath( ConformanceAccessPath GenericSignature::getConformanceAccessPath(
Type type, Type type,
ProtocolDecl *protocol, ProtocolDecl *protocol,
@@ -747,12 +767,12 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
// Resolve this type to a potential archetype. // Resolve this type to a potential archetype.
auto &builder = *getGenericSignatureBuilder(mod); auto &builder = *getGenericSignatureBuilder(mod);
auto pa = builder.resolveArchetype(type); auto pa = builder.resolveArchetype(type);
auto rep = pa->getRepresentative(); auto equivClass = pa->getOrCreateEquivalenceClass();
// Dig out the conformance of this type to the given protocol, because we // Dig out the conformance of this type to the given protocol, because we
// want its requirement source. // want its requirement source.
auto conforms = rep->getConformsTo().find(protocol); auto conforms = equivClass->conformsTo.find(protocol);
assert(conforms != rep->getConformsTo().end()); assert(conforms != equivClass->conformsTo.end());
// Follow the requirement source to form the conformance access path. // Follow the requirement source to form the conformance access path.
typedef GenericSignatureBuilder::RequirementSource RequirementSource; typedef GenericSignatureBuilder::RequirementSource RequirementSource;
@@ -837,16 +857,17 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
// Dig out the potential archetype for this stored type. // Dig out the potential archetype for this stored type.
auto pa = reqSigBuilder.resolveArchetype(storedType); auto pa = reqSigBuilder.resolveArchetype(storedType);
auto rep = pa->getRepresentative(); auto equivClass = pa->getOrCreateEquivalenceClass();
// Find the conformance of this potential archetype to the protocol in // Find the conformance of this potential archetype to the protocol in
// question. // question.
auto knownConforms = rep->getConformsTo().find(conformingProto); auto conforms = equivClass->conformsTo.find(conformingProto);
assert(knownConforms != rep->getConformsTo().end()); assert(conforms != equivClass->conformsTo.end());
// Compute the root type, canonicalizing it w.r.t. the protocol context. // Compute the root type, canonicalizing it w.r.t. the protocol context.
auto inProtoSig = inProtocol->getGenericSignature(); auto inProtoSig = inProtocol->getGenericSignature();
Type localRootType = knownConforms->second->getRootPotentialArchetype() auto conformsSource = getBestRequirementSource(conforms->second);
Type localRootType = conformsSource->getRootPotentialArchetype()
->getDependentType(inProtoSig->getGenericParams(), ->getDependentType(inProtoSig->getGenericParams(),
/*allowUnresolved*/true); /*allowUnresolved*/true);
localRootType = inProtoSig->getCanonicalTypeInContext( localRootType = inProtoSig->getCanonicalTypeInContext(
@@ -854,7 +875,7 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
*inProtocol->getModuleContext()); *inProtocol->getModuleContext());
// Build the path according to the requirement signature. // Build the path according to the requirement signature.
buildPath(reqSig, knownConforms->second, conformingProto, localRootType); buildPath(reqSig, conformsSource, conformingProto, localRootType);
// We're done. // We're done.
return; return;
@@ -884,14 +905,14 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
}; };
// Canonicalize the root type. // Canonicalize the root type.
auto source = conforms->second; auto source = getBestRequirementSource(conforms->second);
auto subjectPA = source->getRootPotentialArchetype(); auto subjectPA = source->getRootPotentialArchetype();
subjectPA = subjectPA->getArchetypeAnchor(*subjectPA->getBuilder()); subjectPA = subjectPA->getArchetypeAnchor(*subjectPA->getBuilder());
Type rootType = subjectPA->getDependentType(getGenericParams(), Type rootType = subjectPA->getDependentType(getGenericParams(),
/*allowUnresolved=*/false); /*allowUnresolved=*/false);
// Build the path. // Build the path.
buildPath(this, conforms->second, protocol, rootType); buildPath(this, source, protocol, rootType);
// Return the path; we're done! // Return the path; we're done!
return path; return path;

View File

@@ -237,6 +237,11 @@ bool RequirementSource::isSelfDerivedSource(PotentialArchetype *pa) const {
case RequirementSource::Inferred: case RequirementSource::Inferred:
case RequirementSource::RequirementSignatureSelf: case RequirementSource::RequirementSignatureSelf:
currentPA = source->getRootPotentialArchetype(); currentPA = source->getRootPotentialArchetype();
while (auto parent = currentPA->getParent()) {
if (auto assocType = currentPA->getResolvedAssociatedType())
assocTypes.push_back(assocType);
currentPA = parent;
}
break; break;
case RequirementSource::Concrete: case RequirementSource::Concrete:
@@ -262,7 +267,6 @@ bool RequirementSource::isSelfDerivedSource(PotentialArchetype *pa) const {
currentPA = knownNested->second.front(); currentPA = knownNested->second.front();
} }
// FIXME: currentPA == pa?
return false; return false;
} }
@@ -798,6 +802,18 @@ EquivalenceClass::findAnySuperclassConstraintAsWritten(
return result; return result;
} }
bool EquivalenceClass::isConformanceSatisfiedBySuperclass(
ProtocolDecl *proto) const {
auto known = conformsTo.find(proto);
assert(known != conformsTo.end() && "doesn't conform to this protocol");
for (const auto &constraint: known->second) {
if (constraint.source->kind == RequirementSource::Superclass)
return true;
}
return false;
}
bool GenericSignatureBuilder::updateRequirementSource( bool GenericSignatureBuilder::updateRequirementSource(
const RequirementSource *&existingSource, const RequirementSource *&existingSource,
const RequirementSource *newSource) { const RequirementSource *newSource) {
@@ -816,8 +832,7 @@ bool GenericSignatureBuilder::updateRequirementSource(
const RequirementSource *GenericSignatureBuilder::resolveSuperConformance( const RequirementSource *GenericSignatureBuilder::resolveSuperConformance(
GenericSignatureBuilder::PotentialArchetype *pa, GenericSignatureBuilder::PotentialArchetype *pa,
ProtocolDecl *proto, ProtocolDecl *proto) {
const RequirementSource *&protoSource) {
// Get the superclass constraint. // Get the superclass constraint.
Type superclass = pa->getSuperclass(); Type superclass = pa->getSuperclass();
if (!superclass) return nullptr; if (!superclass) return nullptr;
@@ -843,8 +858,7 @@ const RequirementSource *GenericSignatureBuilder::resolveSuperConformance(
superclassSource = superclassSource =
superclassSource->viaSuperclass(*this, conformance->getConcrete()); superclassSource->viaSuperclass(*this, conformance->getConcrete());
if (protoSource) paEquivClass->conformsTo[proto].push_back({pa, proto, superclassSource});
updateRequirementSource(protoSource, superclassSource);
return superclassSource; return superclassSource;
} }
@@ -926,29 +940,23 @@ static DeclRange getProtocolMembers(ProtocolDecl *proto) {
} }
bool PotentialArchetype::addConformance(ProtocolDecl *proto, bool PotentialArchetype::addConformance(ProtocolDecl *proto,
bool updateExistingSource,
const RequirementSource *source, const RequirementSource *source,
GenericSignatureBuilder &builder) { GenericSignatureBuilder &builder) {
auto rep = getRepresentative(); // Check whether we already knew about this conformance.
if (rep != this) auto equivClass = getOrCreateEquivalenceClass();
return rep->addConformance(proto, updateExistingSource, source, builder); auto known = equivClass->conformsTo.find(proto);
if (known != equivClass->conformsTo.end()) {
// Check whether we already know about this conformance. // We already knew about this conformance; record this specific constraint.
auto known = ConformsTo.find(proto); known->second.push_back({this, proto, source});
if (known != ConformsTo.end()) {
// We already have this requirement. Update the requirement source
// appropriately.
if (updateExistingSource)
builder.updateRequirementSource(known->second, source);
return false; return false;
} }
// Add this conformance. // Add the conformance along with this constraint.
auto inserted = ConformsTo.insert(std::make_pair(proto, source)).first; equivClass->conformsTo[proto].push_back({this, proto, source});
// If there is a superclass, try to resolve the conformance immediately via // Determine whether there is a superclass constraint where the
// the superclass. // superclass conforms to this protocol.
getBuilder()->resolveSuperConformance(this, proto, inserted->second); (void)getBuilder()->resolveSuperConformance(this, proto);
// Resolve any existing nested types that need it. // Resolve any existing nested types that need it.
for (auto &nested : NestedTypes) { for (auto &nested : NestedTypes) {
@@ -1261,9 +1269,8 @@ PotentialArchetype *PotentialArchetype::getNestedArchetypeAnchor(
TypeAliasDecl *bestTypeAlias = nullptr; TypeAliasDecl *bestTypeAlias = nullptr;
SmallVector<TypeAliasDecl *, 4> typealiases; SmallVector<TypeAliasDecl *, 4> typealiases;
auto rep = getRepresentative(); auto rep = getRepresentative();
for (const auto &conforms : rep->getConformsTo()) { for (auto proto : rep->getConformsTo()) {
// Look for an associated type and/or typealias with this name. // Look for an associated type and/or typealias with this name.
auto proto = conforms.first;
AssociatedTypeDecl *assocType = nullptr; AssociatedTypeDecl *assocType = nullptr;
TypeAliasDecl *typealias = nullptr; TypeAliasDecl *typealias = nullptr;
for (auto member : proto->lookupDirect(name, for (auto member : proto->lookupDirect(name,
@@ -1494,21 +1501,8 @@ PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
// If there's a superclass constraint that conforms to the protocol, // If there's a superclass constraint that conforms to the protocol,
// add the appropriate same-type relationship. // add the appropriate same-type relationship.
auto rep = getRepresentative(); if (auto superSource = builder.resolveSuperConformance(this, proto))
auto knownConformance = rep->getConformsTo().find(proto);
if (knownConformance != rep->getConformsTo().end()) {
auto superSource =
builder.resolveSuperConformance(this, proto, knownConformance->second);
maybeAddSameTypeRequirementForNestedType(resultPA, superSource, builder); maybeAddSameTypeRequirementForNestedType(resultPA, superSource, builder);
} else {
// FIXME: Dropping unknown conformance source on the floor.
const RequirementSource *nullSource = nullptr;
auto superSource = builder.resolveSuperConformance(this, proto,
nullSource);
maybeAddSameTypeRequirementForNestedType(resultPA, superSource, builder);
}
// We know something concrete about the parent PA, so we need to propagate // We know something concrete about the parent PA, so we need to propagate
// that information to this new archetype. // that information to this new archetype.
@@ -1551,6 +1545,7 @@ Type GenericSignatureBuilder::PotentialArchetype::getTypeInContext(
return archetypeAnchor->getTypeInContext(builder, genericEnv); return archetypeAnchor->getTypeInContext(builder, genericEnv);
auto representative = getRepresentative(); auto representative = getRepresentative();
auto equivClass = representative->getOrCreateEquivalenceClass();
ASTContext &ctx = genericEnv->getGenericSignature()->getASTContext(); ASTContext &ctx = genericEnv->getGenericSignature()->getASTContext();
// Return a concrete type or archetype we've already resolved. // Return a concrete type or archetype we've already resolved.
@@ -1655,9 +1650,9 @@ Type GenericSignatureBuilder::PotentialArchetype::getTypeInContext(
// Collect the protocol conformances for the archetype. // Collect the protocol conformances for the archetype.
SmallVector<ProtocolDecl *, 4> Protos; SmallVector<ProtocolDecl *, 4> Protos;
for (const auto &conforms : representative->getConformsTo()) { for (auto proto : representative->getConformsTo()) {
if (conforms.second->kind != RequirementSource::Superclass) if (!equivClass || !equivClass->isConformanceSatisfiedBySuperclass(proto))
Protos.push_back(conforms.first); Protos.push_back(proto);
} }
// Create the archetype. // Create the archetype.
@@ -1791,20 +1786,27 @@ void GenericSignatureBuilder::PotentialArchetype::dump(llvm::raw_ostream &Out,
} }
// Print requirements. // Print requirements.
if (!ConformsTo.empty()) { if (equivClass) {
Out << " : "; bool First = true;
for (const auto &entry : equivClass->conformsTo) {
for (const auto &constraint : entry.second) {
if (constraint.archetype != this) continue;
interleave(ConformsTo, if (First) {
[&](std::pair<ProtocolDecl *, const RequirementSource *> First = false;
ProtoAndSource) { Out << ": ";
Out << ProtoAndSource.first->getName().str() << " "; } else {
if (!ProtoAndSource.second->isDerivedRequirement()) Out << " & ";
Out << "*"; }
Out << "[";
ProtoAndSource.second->print(Out, SrcMgr); Out << constraint.value->getName().str() << " ";
Out << "]"; if (!constraint.source->isDerivedRequirement())
}, Out << "*";
[&] { Out << " & "; }); Out << "[";
constraint.source->print(Out, SrcMgr);
Out << "]";
}
}
} }
if (getRepresentative() != this) { if (getRepresentative() != this) {
@@ -1998,13 +2000,13 @@ bool GenericSignatureBuilder::addConformanceRequirement(PotentialArchetype *PAT,
ProtocolDecl *Proto, ProtocolDecl *Proto,
const RequirementSource *Source, const RequirementSource *Source,
llvm::SmallPtrSetImpl<ProtocolDecl *> &Visited) { llvm::SmallPtrSetImpl<ProtocolDecl *> &Visited) {
// Add the requirement, if we haven't done so already.
if (!PAT->addConformance(Proto, Source, *this))
return false;
// Add the requirement to the representative. // Add the requirement to the representative.
auto T = PAT->getRepresentative(); auto T = PAT->getRepresentative();
// Add the requirement, if we haven't done so already.
if (!T->addConformance(Proto, /*updateExistingSource=*/true, Source, *this))
return false;
bool inserted = Visited.insert(Proto).second; bool inserted = Visited.insert(Proto).second;
assert(inserted); assert(inserted);
(void) inserted; (void) inserted;
@@ -2120,10 +2122,9 @@ bool GenericSignatureBuilder::updateSuperclass(
// Local function to handle the update of superclass conformances // Local function to handle the update of superclass conformances
// when the superclass constraint changes. // when the superclass constraint changes.
auto updateSuperclassConformances = [&] { auto updateSuperclassConformances = [&] {
for (auto &conforms : T->ConformsTo) { for (auto proto : T->getConformsTo()) {
if (auto superSource = resolveSuperConformance(T, conforms.first, if (auto superSource = resolveSuperConformance(T, proto)) {
conforms.second)) { for (auto req : getProtocolMembers(proto)) {
for (auto req : getProtocolMembers(conforms.first)) {
auto assocType = dyn_cast<AssociatedTypeDecl>(req); auto assocType = dyn_cast<AssociatedTypeDecl>(req);
if (!assocType) continue; if (!assocType) continue;
@@ -2242,24 +2243,6 @@ bool GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
if (mismatch) return true; if (mismatch) return true;
} }
// Don't mark requirements as redundant if they come from one of our
// child archetypes. This is a targeted fix -- more general cases
// continue to break. In general, we need to detect cycles in the
// archetype graph and not propagate requirement source information
// along back edges.
bool updateExistingSource = true;
auto T2Parent = T2;
while (T2Parent != nullptr) {
if (T2Parent->getRepresentative() == T1)
updateExistingSource = false;
T2Parent = T2Parent->getParent();
}
// Another targeted fix -- don't drop conformances from generic
// parameters.
if (T1->getParent() == nullptr)
updateExistingSource = false;
// Merge the equivalence classes. // Merge the equivalence classes.
auto equivClass = T1->getOrCreateEquivalenceClass(); auto equivClass = T1->getOrCreateEquivalenceClass();
auto equivClass2Members = T2->getEquivalenceClassMembers(); auto equivClass2Members = T2->getEquivalenceClassMembers();
@@ -2304,9 +2287,15 @@ bool GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
} }
// Add all of the protocol conformance requirements of T2 to T1. // Add all of the protocol conformance requirements of T2 to T1.
for (auto conforms : T2->ConformsTo) { if (equivClass2) {
T1->addConformance(conforms.first, updateExistingSource, for (const auto &entry : equivClass2->conformsTo) {
conforms.second, *this); T1->addConformance(entry.first, entry.second.front().source, *this);
auto &constraints1 = equivClass->conformsTo[entry.first];
constraints1.insert(constraints1.end(),
entry.second.begin() + 1,
entry.second.end());
}
} }
// Recursively merge the associated types of T2 into T1. // Recursively merge the associated types of T2 into T1.
@@ -2356,8 +2345,7 @@ bool GenericSignatureBuilder::addSameTypeRequirementToConcrete(
DenseMap<ProtocolDecl *, ProtocolConformanceRef> conformances; DenseMap<ProtocolDecl *, ProtocolConformanceRef> conformances;
CanType depTy = rep->getDependentType({ }, /*allowUnresolved=*/true) CanType depTy = rep->getDependentType({ }, /*allowUnresolved=*/true)
->getCanonicalType(); ->getCanonicalType();
for (auto &conforms : rep->getConformsTo()) { for (auto protocol : rep->getConformsTo()) {
auto protocol = conforms.first;
auto conformance = auto conformance =
getLookupConformanceFn()(depTy, Concrete, getLookupConformanceFn()(depTy, Concrete,
protocol->getDeclaredInterfaceType() protocol->getDeclaredInterfaceType()
@@ -2380,7 +2368,7 @@ bool GenericSignatureBuilder::addSameTypeRequirementToConcrete(
conformance->isConcrete() conformance->isConcrete()
? conformance->getConcrete() ? conformance->getConcrete()
: nullptr); : nullptr);
updateRequirementSource(conforms.second, concreteSource); equivClass->conformsTo[protocol].push_back({T, protocol, concreteSource});
} }
// Eagerly resolve any existing nested types to their concrete forms (others // Eagerly resolve any existing nested types to their concrete forms (others
@@ -2493,8 +2481,7 @@ void GenericSignatureBuilder::markPotentialArchetypeRecursive(
return; return;
pa->setIsRecursive(); pa->setIsRecursive();
// FIXME: Drop this protocol. pa->addConformance(proto, source, *this);
pa->addConformance(proto, /*updateExistingSource=*/true, source, *this);
if (!pa->getParent()) if (!pa->getParent())
return; return;
@@ -2809,8 +2796,7 @@ static Identifier typoCorrectNestedType(
llvm::SmallVector<Identifier, 2> bestMatches; llvm::SmallVector<Identifier, 2> bestMatches;
unsigned bestEditDistance = 0; unsigned bestEditDistance = 0;
unsigned maxScore = (name.size() + 1) / 3; unsigned maxScore = (name.size() + 1) / 3;
for (const auto &conforms : pa->getParent()->getConformsTo()) { for (auto proto : pa->getParent()->getConformsTo()) {
auto proto = conforms.first;
for (auto member : getProtocolMembers(proto)) { for (auto member : getProtocolMembers(proto)) {
auto assocType = dyn_cast<AssociatedTypeDecl>(member); auto assocType = dyn_cast<AssociatedTypeDecl>(member);
if (!assocType) if (!assocType)
@@ -2984,6 +2970,8 @@ GenericSignatureBuilder::finalize(SourceLoc loc,
checkRedundantSuperclassConstraints(genericParams, archetype); checkRedundantSuperclassConstraints(genericParams, archetype);
} }
} }
checkConformanceConstraints(genericParams, archetype);
}); });
// Check for generic parameters which have been made concrete or equated // Check for generic parameters which have been made concrete or equated
@@ -3139,6 +3127,7 @@ Constraint<T> GenericSignatureBuilder::checkConstraintList(
Diag<Type, T> redundancyDiag, Diag<Type, T> redundancyDiag,
Diag<bool, Type, T> otherNoteDiag) { Diag<bool, Type, T> otherNoteDiag) {
// Remove self-derived constraints. // Remove self-derived constraints.
assert(!constraints.empty() && "No constraints?");
constraints.erase( constraints.erase(
std::remove_if(constraints.begin(), constraints.end(), std::remove_if(constraints.begin(), constraints.end(),
[&](const Constraint<T> &constraint) { [&](const Constraint<T> &constraint) {
@@ -3146,6 +3135,7 @@ Constraint<T> GenericSignatureBuilder::checkConstraintList(
constraint.archetype); constraint.archetype);
}), }),
constraints.end()); constraints.end());
assert(!constraints.empty() && "All constraints were self-derived!");
// Sort the constraints, so we get a deterministic ordering of diagnostics. // Sort the constraints, so we get a deterministic ordering of diagnostics.
llvm::array_pod_sort(constraints.begin(), constraints.end()); llvm::array_pod_sort(constraints.begin(), constraints.end());
@@ -3300,6 +3290,29 @@ Constraint<T> GenericSignatureBuilder::checkConstraintList(
return *representativeConstraint; return *representativeConstraint;
} }
void GenericSignatureBuilder::checkConformanceConstraints(
ArrayRef<GenericTypeParamType *> genericParams,
PotentialArchetype *pa) {
auto equivClass = pa->getEquivalenceClassIfPresent();
if (!equivClass || equivClass->conformsTo.empty())
return;
for (auto &entry : equivClass->conformsTo) {
checkConstraintList<ProtocolDecl *>(
genericParams, entry.second,
[](const Constraint<ProtocolDecl *> &constraint) {
return true;
},
[&](ProtocolDecl *proto) {
assert(proto == entry.first && "Mixed up protocol constraints");
return ConstraintRelation::Redundant;
},
None,
diag::redundant_conformance_constraint,
diag::redundant_conformance_here);
}
}
void GenericSignatureBuilder::checkRedundantConcreteTypeConstraints( void GenericSignatureBuilder::checkRedundantConcreteTypeConstraints(
ArrayRef<GenericTypeParamType *> genericParams, ArrayRef<GenericTypeParamType *> genericParams,
PotentialArchetype *representative) { PotentialArchetype *representative) {
@@ -3720,11 +3733,23 @@ void GenericSignatureBuilder::enumerateRequirements(llvm::function_ref<
// Enumerate conformance requirements. // Enumerate conformance requirements.
SmallVector<ProtocolDecl *, 4> protocols; SmallVector<ProtocolDecl *, 4> protocols;
DenseMap<ProtocolDecl *, const RequirementSource *> protocolSources; DenseMap<ProtocolDecl *, const RequirementSource *> protocolSources;
for (const auto &conforms : rep->getConformsTo()) { auto equivClass = rep->getEquivalenceClassIfPresent();
protocols.push_back(conforms.first); if (equivClass) {
assert(protocolSources.count(conforms.first) == 0 && for (const auto &conforms : equivClass->conformsTo) {
"redundant protocol requirement?"); protocols.push_back(conforms.first);
protocolSources.insert({conforms.first, conforms.second}); assert(protocolSources.count(conforms.first) == 0 &&
"redundant protocol requirement?");
// Find the best source among the constraints that describe conformance
// to this protocol.
auto bestSource = conforms.second.front().source;
for (const auto &constraint : conforms.second) {
if (constraint.source->compare(bestSource) < 0)
bestSource = constraint.source;
}
protocolSources.insert({conforms.first, bestSource});
}
} }
// Sort the protocols in canonical order. // Sort the protocols in canonical order.

View File

@@ -30,8 +30,9 @@ func typoAssoc3<T : P2, U : P2>()
where U.AssocP2.assoc : P3, T.AssocP2.assoc : P4, where U.AssocP2.assoc : P3, T.AssocP2.assoc : P4,
T.AssocP2 == U.AssocP2 {} T.AssocP2 == U.AssocP2 {}
// expected-error@+3{{'T.AssocP2' does not have a member type named 'assoc'; did you mean 'Assoc'?}}{{47-52=Assoc}}
// expected-error@+2{{'T' does not have a member type named 'Assocp2'; did you mean 'AssocP2'?}}{{39-46=AssocP2}} // expected-error@+2{{'T' does not have a member type named 'Assocp2'; did you mean 'AssocP2'?}}{{39-46=AssocP2}}
// expected-error@+1{{'T.AssocP2' does not have a member type named 'assoc'; did you mean 'Assoc'?}}{{47-52=Assoc}} // expected-error@+1{{'T.AssocP2' does not have a member type named 'assoc'; did you mean 'Assoc'?}}
func typoAssoc4<T : P2>(_: T) where T.Assocp2.assoc : P3 {} func typoAssoc4<T : P2>(_: T) where T.Assocp2.assoc : P3 {}
@@ -39,7 +40,7 @@ func typoAssoc4<T : P2>(_: T) where T.Assocp2.assoc : P3 {}
// CHECK-GENERIC-NEXT: Requirements: // CHECK-GENERIC-NEXT: Requirements:
// CHECK-GENERIC-NEXT: τ_0_0 : P2 [τ_0_0: Explicit @ {{.*}}:21] // CHECK-GENERIC-NEXT: τ_0_0 : P2 [τ_0_0: Explicit @ {{.*}}:21]
// CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2 : P1 [τ_0_0: Explicit @ {{.*}}:21 -> Protocol requirement (via Self.AssocP2 in P2)] // CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2 : P1 [τ_0_0: Explicit @ {{.*}}:21 -> Protocol requirement (via Self.AssocP2 in P2)]
// CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2[.P1].Assoc : P3 [τ_0_0[.P2].AssocP2.assoc: Explicit @ {{.*}}:53] // CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2[.P1].Assoc : P3 [τ_0_0[.P2].AssocP2[.P1].Assoc: Explicit @ {{.*}}:53]
// CHECK-GENERIC-NEXT: Potential archetypes // CHECK-GENERIC-NEXT: Potential archetypes
// <rdar://problem/19620340> // <rdar://problem/19620340>

View File

@@ -12,4 +12,9 @@ protocol Q : P {
} }
func f<T>(t: T) where T : P, T : Q, T.A : P0 { } // expected-note{{'f(t:)' previously declared here}} func f<T>(t: T) where T : P, T : Q, T.A : P0 { } // expected-note{{'f(t:)' previously declared here}}
func f<T>(t: T) where T : Q, T : P, T.A : P0 { } // expected-error{{invalid redeclaration of 'f(t:)'}} // expected-warning@-1{{redundant conformance constraint 'T': 'P'}}
// expected-note@-2{{conformance constraint 'T': 'P' implied here}}
func f<T>(t: T) where T : Q, T : P, T.A : P0 { } // expected-error{{invalid redeclaration of 'f(t:)'}}
// expected-warning@-1{{redundant conformance constraint 'T': 'P'}}
// expected-note@-2{{conformance constraint 'T': 'P' implied here}}

View File

@@ -56,8 +56,8 @@ func testPaths3<V: P5>(_ v: V) {
acceptQ0(v.getAssocP3()) acceptQ0(v.getAssocP3())
} }
protocol P6Unordered: P5Unordered { protocol P6Unordered: P5Unordered { // expected-note{{conformance constraint 'Self.A': 'P0' implied here}}
associatedtype A: P0 associatedtype A: P0 // expected-warning{{redundant conformance constraint 'Self.A': 'P0'}}
} }
protocol P5Unordered { protocol P5Unordered {

View File

@@ -57,8 +57,9 @@ protocol Q5: Q2, Q3, Q4 {}
// CHECK-LABEL: .Q6@ // CHECK-LABEL: .Q6@
// CHECK-NEXT: Requirement signature: <Self where Self : Q2, Self : Q3, Self : Q4> // CHECK-NEXT: Requirement signature: <Self where Self : Q2, Self : Q3, Self : Q4>
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0 : Q3, τ_0_0 : Q4> // CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0 : Q3, τ_0_0 : Q4>
protocol Q6: Q2, Q3, Q4 { protocol Q6: Q2, // expected-note{{conformance constraint 'Self.X': 'P1' implied here}}
associatedtype X: P1 Q3, Q4 {
associatedtype X: P1 // expected-warning{{redundant conformance constraint 'Self.X': 'P1'}}
} }
// multiple inheritance with a new conformance // multiple inheritance with a new conformance

View File

@@ -126,6 +126,8 @@ func inferSameType1<T, U>(_ x: Model_P3_P4_Eq<T, U>) { }
// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Explicit @ {{.*}}:25 -> Protocol requirement (via Self.P3Assoc in P3)] // CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Explicit @ {{.*}}:25 -> Protocol requirement (via Self.P3Assoc in P3)]
// CHECK-NEXT: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [τ_0_0[.P3].P3Assoc: Explicit] // CHECK-NEXT: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [τ_0_0[.P3].P3Assoc: Explicit]
func inferSameType2<T : P3, U : P4>(_: T, _: U) where U.P4Assoc : P2, T.P3Assoc == U.P4Assoc {} func inferSameType2<T : P3, U : P4>(_: T, _: U) where U.P4Assoc : P2, T.P3Assoc == U.P4Assoc {}
// expected-warning@-1{{redundant conformance constraint 'T.P3Assoc': 'P2'}}
// expected-note@-2{{conformance constraint 'T.P3Assoc': 'P2' implied here}}
// CHECK-LABEL: .inferSameType3@ // CHECK-LABEL: .inferSameType3@
// CHECK-NEXT: Requirements: // CHECK-NEXT: Requirements:
@@ -149,8 +151,8 @@ protocol P7 : P6 {
// CHECK-LABEL: P7.nestedSameType1()@ // CHECK-LABEL: P7.nestedSameType1()@
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P7, τ_0_0.AssocP6.Element : P6, τ_0_0.AssocP6.Element == τ_0_0.AssocP7.AssocP6.Element> // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P7, τ_0_0.AssocP6.Element : P6, τ_0_0.AssocP6.Element == τ_0_0.AssocP7.AssocP6.Element>
extension P7 where AssocP6.Element : P6, extension P7 where AssocP6.Element : P6, // expected-note{{conformance constraint 'Self.AssocP6.Element': 'P6' written here}}
AssocP7.AssocP6.Element : P6, AssocP7.AssocP6.Element : P6, // expected-warning{{redundant conformance constraint 'Self.AssocP6.Element': 'P6'}}
AssocP6.Element == AssocP7.AssocP6.Element { AssocP6.Element == AssocP7.AssocP6.Element {
func nestedSameType1() { } func nestedSameType1() { }
} }

View File

@@ -75,17 +75,23 @@ extension P2 where Self.T : C {
// CHECK: superclassConformance1 // CHECK: superclassConformance1
// CHECK: Requirements: // CHECK: Requirements:
// CHECK-NEXT: τ_0_0 : C [τ_0_0: Explicit @ {{.*}}:46] // CHECK-NEXT: τ_0_0 : C [τ_0_0: Explicit @ {{.*}}:11]
// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:46 -> Superclass (C: P3)] // CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:11 -> Superclass (C: P3)]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C> // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C>
func superclassConformance1<T>(t: T) where T : C, T : P3 {} func superclassConformance1<T>(t: T)
where T : C, // expected-note{{conformance constraint 'T': 'P3' implied here}}
T : P3 {} // expected-warning{{redundant conformance constraint 'T': 'P3'}}
// CHECK: superclassConformance2 // CHECK: superclassConformance2
// CHECK: Requirements: // CHECK: Requirements:
// CHECK-NEXT: τ_0_0 : C [τ_0_0: Explicit @ {{.*}}:46] // CHECK-NEXT: τ_0_0 : C [τ_0_0: Explicit @ {{.*}}:11]
// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:46 -> Superclass (C: P3)] // CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:11 -> Superclass (C: P3)]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C> // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C>
func superclassConformance2<T>(t: T) where T : C, T : P3 {} func superclassConformance2<T>(t: T)
where T : C, // expected-note{{conformance constraint 'T': 'P3' implied here}}
T : P3 {} // expected-warning{{redundant conformance constraint 'T': 'P3'}}
protocol P4 { } protocol P4 { }
@@ -99,6 +105,8 @@ class C2 : C, P4 { }
func superclassConformance3<T>(t: T) where T : C, T : P4, T : C2 {} func superclassConformance3<T>(t: T) where T : C, T : P4, T : C2 {}
// expected-warning@-1{{redundant superclass constraint 'T' : 'C'}} // expected-warning@-1{{redundant superclass constraint 'T' : 'C'}}
// expected-note@-2{{superclass constraint 'T' : 'C2' written here}} // expected-note@-2{{superclass constraint 'T' : 'C2' written here}}
// expected-warning@-3{{redundant conformance constraint 'T': 'P4'}}
// expected-note@-4{{conformance constraint 'T': 'P4' implied here}}
protocol P5: A { } // expected-error{{non-class type 'P5' cannot inherit from class 'A'}} protocol P5: A { } // expected-error{{non-class type 'P5' cannot inherit from class 'A'}}

View File

@@ -1,13 +1,16 @@
// RUN: %target-swift-frontend -typecheck -verify %s // RUN: %target-swift-frontend -typecheck -verify %s
protocol Mashable { }
protocol Womparable { }
// FuncDecl: Choose 0 // FuncDecl: Choose 0
func f1<T>(x: T) {} func f1<T>(x: T) {}
// FuncDecl: Choose 1 // FuncDecl: Choose 1
// 1: Inherited constraint // 1: Inherited constraint
func f2<T: Hashable>(x: T) {} // no-warning func f2<T: Mashable>(x: T) {} // no-warning
// 2: Non-trailing where // 2: Non-trailing where
func f3<T where T: Comparable>(x: T) {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{10-30=}} {{37-37= where T: Comparable}} func f3<T where T: Womparable>(x: T) {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{10-30=}} {{37-37= where T: Womparable}}
// 3: Has return type // 3: Has return type
func f4<T>(x: T) -> Int { return 2 } // no-warning func f4<T>(x: T) -> Int { return 2 } // no-warning
// 4: Trailing where // 4: Trailing where
@@ -15,29 +18,29 @@ func f5<T>(x: T) where T : Equatable {} // no-warning
// FuncDecl: Choose 2 // FuncDecl: Choose 2
// 1,2 // 1,2
func f12<T: Hashable where T: Comparable>(x: T) {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{21-41=}} {{48-48= where T: Comparable}} func f12<T: Mashable where T: Womparable>(x: T) {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{21-41=}} {{48-48= where T: Womparable}}
// 1,3 // 1,3
func f13<T: Hashable>(x: T) -> Int { return 2 } // no-warning func f13<T: Mashable>(x: T) -> Int { return 2 } // no-warning
// 1,4 // 1,4
func f14<T: Hashable>(x: T) where T: Equatable {} // no-warning func f14<T: Mashable>(x: T) where T: Equatable {} // no-warning
// 2,3 // 2,3
func f23<T where T: Comparable>(x: T) -> Int { return 2 } // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{11-31=}} {{45-45= where T: Comparable}} func f23<T where T: Womparable>(x: T) -> Int { return 2 } // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{11-31=}} {{45-45= where T: Womparable}}
// 2,4 // 2,4
func f24<T where T: Comparable>(x: T) where T: Equatable {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{11-31=}} {{39-44=where T: Comparable,}} func f24<T where T: Womparable>(x: T) where T: Equatable {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{11-31=}} {{39-44=where T: Womparable,}}
// 3,4 // 3,4
func f34<T>(x: T) -> Int where T: Equatable { return 2 } // no-warning func f34<T>(x: T) -> Int where T: Equatable { return 2 } // no-warning
// FuncDecl: Choose 3 // FuncDecl: Choose 3
// 1,2,3 // 1,2,3
func f123<T: Hashable where T: Comparable>(x: T) -> Int { return 2 } // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{22-42=}} {{56-56= where T: Comparable}} func f123<T: Mashable where T: Womparable>(x: T) -> Int { return 2 } // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{22-42=}} {{56-56= where T: Womparable}}
// 1,2,4 // 1,2,4
func f124<T: Hashable where T: Comparable>(x: T) where T: Equatable {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{22-42=}} {{50-55=where T: Comparable,}} func f124<T: Mashable where T: Womparable>(x: T) where T: Equatable {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{22-42=}} {{50-55=where T: Womparable,}}
// 2,3,4 // 2,3,4
func f234<T where T: Comparable>(x: T) -> Int where T: Equatable { return 2 } // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{12-32=}} {{47-52=where T: Comparable,}} func f234<T where T: Womparable>(x: T) -> Int where T: Equatable { return 2 } // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{12-32=}} {{47-52=where T: Womparable,}}
// FuncDecl: Choose 4 // FuncDecl: Choose 4
// 1,2,3,4 // 1,2,3,4
func f1234<T: Hashable where T: Comparable>(x: T) -> Int where T: Equatable { return 2 } // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{23-43=}} {{58-63=where T: Comparable,}} func f1234<T: Mashable where T: Womparable>(x: T) -> Int where T: Equatable { return 2 } // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{23-43=}} {{58-63=where T: Womparable,}}
@@ -46,23 +49,23 @@ struct S0<T> {}
// NominalTypeDecl: Choose 1 // NominalTypeDecl: Choose 1
// 1: Inherited constraint // 1: Inherited constraint
struct S1<T: Hashable> {} // no-warning struct S1<T: Mashable> {} // no-warning
// 2: Non-trailing where // 2: Non-trailing where
struct S2<T where T: Comparable> {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{12-32=}} {{33-33= where T: Comparable}} struct S2<T where T: Womparable> {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{12-32=}} {{33-33= where T: Womparable}}
// 3: Trailing where // 3: Trailing where
struct S3<T> where T : Equatable {} // no-warning struct S3<T> where T : Equatable {} // no-warning
// NominalTypeDecl: Choose 2 // NominalTypeDecl: Choose 2
// 1,2 // 1,2
struct S12<T: Hashable where T: Comparable> {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{23-43=}} {{44-44= where T: Comparable}} struct S12<T: Mashable where T: Womparable> {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{23-43=}} {{44-44= where T: Womparable}}
// 1,3 // 1,3
struct S13<T: Hashable> where T: Equatable {} // no-warning struct S13<T: Mashable> where T: Equatable {} // no-warning
// 2,3 // 2,3
struct S23<T where T: Comparable> where T: Equatable {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{13-33=}} {{35-40=where T: Comparable,}} struct S23<T where T: Womparable> where T: Equatable {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{13-33=}} {{35-40=where T: Womparable,}}
// NominalTypeDecl: Choose 3 // NominalTypeDecl: Choose 3
// 1,2,3 // 1,2,3
struct S123<T: Hashable where T: Comparable> where T: Equatable {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{24-44=}} {{46-51=where T: Comparable,}} struct S123<T: Mashable where T: Womparable> where T: Equatable {} // expected-warning {{'where' clause next to generic parameters is deprecated and will be removed in the future version of Swift}} {{24-44=}} {{46-51=where T: Womparable,}}
protocol ProtoA {} protocol ProtoA {}

View File

@@ -82,6 +82,8 @@ protocol CircleStart : CircleEnd { func circle_start() } // expected-error 2{{ci
// expected-note@-1{{protocol 'CircleStart' declared here}} // expected-note@-1{{protocol 'CircleStart' declared here}}
protocol CircleEnd : CircleMiddle { func circle_end()} // expected-note{{protocol 'CircleEnd' declared here}} protocol CircleEnd : CircleMiddle { func circle_end()} // expected-note{{protocol 'CircleEnd' declared here}}
// expected-warning@+2{{redundant conformance constraint 'Self': 'CircleTrivial'}}
// expected-note@+1{{conformance constraint 'Self': 'CircleTrivial' implied here}}
protocol CircleEntry : CircleTrivial { } protocol CircleEntry : CircleTrivial { }
protocol CircleTrivial : CircleTrivial { } // expected-error 3{{circular protocol inheritance CircleTrivial}} protocol CircleTrivial : CircleTrivial { } // expected-error 3{{circular protocol inheritance CircleTrivial}}

View File

@@ -52,7 +52,8 @@ protocol P3 {
protocol P4 : P3 {} protocol P4 : P3 {}
protocol DeclaredP : P3, P4 {} protocol DeclaredP : P3, // expected-warning{{redundant conformance constraint 'Self': 'P3'}}
P4 {} // expected-note{{conformance constraint 'Self': 'P3' implied here}}
struct Y3 : DeclaredP { struct Y3 : DeclaredP {
} }
@@ -75,7 +76,13 @@ protocol Gamma {
associatedtype Delta: Alpha // expected-error{{type may not reference itself as a requirement}} associatedtype Delta: Alpha // expected-error{{type may not reference itself as a requirement}}
} }
struct Epsilon<T: Alpha, U: Gamma> where T.Beta == U, U.Delta == T {} // FIXME: Redundancy diagnostics are odd here.
struct Epsilon<T: Alpha, // expected-note{{conformance constraint 'U': 'Gamma' implied here}}
// expected-warning@-1{{redundant conformance constraint 'T': 'Alpha'}}
U: Gamma> // expected-warning{{redundant conformance constraint 'U': 'Gamma'}}
// expected-note@-1{{conformance constraint 'T': 'Alpha' implied here}}
where T.Beta == U,
U.Delta == T {}
// ----- // -----