mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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:
@@ -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,
|
||||||
|
|||||||
@@ -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,6 +142,10 @@ 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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 << constraint.value->getName().str() << " ";
|
||||||
|
if (!constraint.source->isDerivedRequirement())
|
||||||
Out << "*";
|
Out << "*";
|
||||||
Out << "[";
|
Out << "[";
|
||||||
ProtoAndSource.second->print(Out, SrcMgr);
|
constraint.source->print(Out, SrcMgr);
|
||||||
Out << "]";
|
Out << "]";
|
||||||
},
|
}
|
||||||
[&] { 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();
|
||||||
|
if (equivClass) {
|
||||||
|
for (const auto &conforms : equivClass->conformsTo) {
|
||||||
protocols.push_back(conforms.first);
|
protocols.push_back(conforms.first);
|
||||||
assert(protocolSources.count(conforms.first) == 0 &&
|
assert(protocolSources.count(conforms.first) == 0 &&
|
||||||
"redundant protocol requirement?");
|
"redundant protocol requirement?");
|
||||||
protocolSources.insert({conforms.first, conforms.second});
|
|
||||||
|
// 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.
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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}}
|
||||||
|
// 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:)'}}
|
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}}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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() { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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'}}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {}
|
||||||
|
|||||||
@@ -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}}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user