Merge pull request #12346 from adrian-prantl/18296829
Revert
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 7f17f1f..3b9024e 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -562,8 +562,10 @@
class AssociatedTypeDeclBitfields {
friend class AssociatedTypeDecl;
unsigned : NumTypeDeclBits;
+ unsigned ComputedOverridden : 1;
+ unsigned HasOverridden : 1;
};
- enum { NumAssociatedTypeDeclBits = NumTypeDeclBits };
+ enum { NumAssociatedTypeDeclBits = NumTypeDeclBits + 2 };
static_assert(NumAssociatedTypeDeclBits <= 32, "fits in an unsigned");
class ImportDeclBitfields {
@@ -2662,6 +2664,33 @@
/// type; can only be called after the alias type has been resolved.
void computeType();
+ /// Retrieve the associated type "anchor", which is the associated type
+ /// declaration that will be used to describe this associated type in the
+ /// ABI.
+ ///
+ /// The associated type "anchor" is an associated type that does not
+ /// override any other associated type. There may be several such associated
+ /// types; select one deterministically.
+ AssociatedTypeDecl *getAssociatedTypeAnchor() const;
+
+ /// Retrieve the (first) overridden associated type declaration, if any.
+ AssociatedTypeDecl *getOverriddenDecl() const;
+
+ /// Retrieve the set of associated types overridden by this associated
+ /// type.
+ ArrayRef<AssociatedTypeDecl *> getOverriddenDecls() const;
+
+ /// Whether the overridden declarations have already been computed.
+ bool overriddenDeclsComputed() const {
+ return AssociatedTypeDeclBits.ComputedOverridden;
+ }
+
+ /// Record the set of overridden declarations.
+ ///
+ /// \returns the array recorded in the AST.
+ ArrayRef<AssociatedTypeDecl *> setOverriddenDecls(
+ ArrayRef<AssociatedTypeDecl *> overridden);
+
SourceLoc getStartLoc() const { return KeywordLoc; }
SourceRange getSourceRange() const;
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index e55ee0b..5aa9dc6 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -1452,18 +1452,13 @@
/// associated type.
PotentialArchetype(PotentialArchetype *parent, Identifier name);
- /// \brief Construct a new potential archetype for an associated type.
- PotentialArchetype(PotentialArchetype *parent, AssociatedTypeDecl *assocType)
- : parentOrBuilder(parent), identifier(assocType)
- {
- assert(parent != nullptr && "Not an associated type?");
- }
-
/// \brief Construct a new potential archetype for a concrete declaration.
PotentialArchetype(PotentialArchetype *parent, TypeDecl *concreteDecl)
: parentOrBuilder(parent), identifier(concreteDecl)
{
- assert(parent != nullptr && "Not an associated type?");
+ assert(parent != nullptr && "Not a nested type?");
+ assert(!isa<AssociatedTypeDecl>(concreteDecl) ||
+ cast<AssociatedTypeDecl>(concreteDecl)->getOverriddenDecls().empty());
}
/// \brief Construct a new potential archetype for a generic parameter.
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index cf4e11e..4101be6 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -54,7 +54,7 @@
/// in source control, you should also update the comment to briefly
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
-const uint16_t VERSION_MINOR = 368; // Last change: objc_method, objc_super_method
+const uint16_t VERSION_MINOR = 369; // Last change: associated type overrides
using DeclID = PointerEmbeddedInt<unsigned, 31>;
using DeclIDField = BCFixed<31>;
@@ -815,10 +815,11 @@
using AssociatedTypeDeclLayout = BCRecordLayout<
ASSOCIATED_TYPE_DECL,
- IdentifierIDField, // name
- DeclContextIDField,// context decl
- TypeIDField, // default definition
- BCFixed<1> // implicit flag
+ IdentifierIDField, // name
+ DeclContextIDField, // context decl
+ TypeIDField, // default definition
+ BCFixed<1>, // implicit flag
+ BCArray<DeclIDField> // overridden associated types
>;
using StructLayout = BCRecordLayout<
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 01e1798..c794667 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -278,6 +278,10 @@
/// The existential signature <T : P> for each P.
llvm::DenseMap<CanType, CanGenericSignature> ExistentialSignatures;
+ /// Overridden associated type declarations.
+ llvm::DenseMap<const AssociatedTypeDecl *, ArrayRef<AssociatedTypeDecl *>>
+ AssociatedTypeOverrides;
+
/// \brief Structure that captures data that is segregated into different
/// arenas.
struct Arena {
@@ -1541,6 +1545,125 @@
return env;
}
+/// Minimize the set of overridden associated types, eliminating any
+/// associated types that are overridden by other associated types.
+static void minimizeOverriddenAssociatedTypes(
+ SmallVectorImpl<AssociatedTypeDecl *> &assocTypes) {
+ // Mark associated types that are "worse" than some other associated type,
+ // because they come from an inherited protocol.
+ bool anyWorse = false;
+ std::vector<bool> worseThanAny(assocTypes.size(), false);
+ for (unsigned i : indices(assocTypes)) {
+ auto proto1 = assocTypes[i]->getProtocol();
+ for (unsigned j : range(i + 1, assocTypes.size())) {
+ auto proto2 = assocTypes[j]->getProtocol();
+ if (proto1->inheritsFrom(proto2)) {
+ anyWorse = true;
+ worseThanAny[j] = true;
+ } else if (proto2->inheritsFrom(proto1)) {
+ anyWorse = true;
+ worseThanAny[i] = true;
+ break;
+ }
+ }
+ }
+
+ // If we didn't find any associated types that were "worse", we're done.
+ if (!anyWorse) return;
+
+ // Copy in the associated types that aren't worse than any other associated
+ // type.
+ unsigned nextIndex = 0;
+ for (unsigned i : indices(assocTypes)) {
+ if (worseThanAny[i]) continue;
+ assocTypes[nextIndex++] = assocTypes[i];
+ }
+
+ assocTypes.erase(assocTypes.begin() + nextIndex, assocTypes.end());
+}
+
+/// Sort associated types just based on the protocol.
+static int compareSimilarAssociatedTypes(AssociatedTypeDecl *const *lhs,
+ AssociatedTypeDecl *const *rhs) {
+ auto lhsProto = (*lhs)->getProtocol();
+ auto rhsProto = (*rhs)->getProtocol();
+ return ProtocolType::compareProtocols(&lhsProto, &rhsProto);
+}
+
+ArrayRef<AssociatedTypeDecl *> AssociatedTypeDecl::getOverriddenDecls() const {
+ // If we already computed the set of overridden associated types, return it.
+ if (AssociatedTypeDeclBits.ComputedOverridden) {
+ // We didn't override any associated types, so return the empty set.
+ if (!AssociatedTypeDeclBits.HasOverridden)
+ return { };
+
+ // Look up the overrides.
+ auto known = getASTContext().Impl.AssociatedTypeOverrides.find(this);
+ assert(known != getASTContext().Impl.AssociatedTypeOverrides.end());
+ return known->second;
+ }
+
+ // Find associated types with the given name in all of the inherited
+ // protocols.
+ SmallVector<AssociatedTypeDecl *, 4> inheritedAssociatedTypes;
+ auto proto = getProtocol();
+ proto->walkInheritedProtocols([&](ProtocolDecl *inheritedProto) {
+ if (proto == inheritedProto) return TypeWalker::Action::Continue;
+
+ // Objective-C protocols
+ if (inheritedProto->isObjC()) return TypeWalker::Action::Continue;
+
+ // Look for associated types with the same name.
+ bool foundAny = false;
+ for (auto member : inheritedProto->lookupDirect(
+ getFullName(),
+ /*ignoreNewExtensions=*/true)) {
+ if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
+ inheritedAssociatedTypes.push_back(assocType);
+ foundAny = true;
+ }
+ }
+
+ return foundAny ? TypeWalker::Action::SkipChildren
+ : TypeWalker::Action::Continue;
+ });
+
+ // Minimize the set of inherited associated types, eliminating any that
+ // themselves are overridden.
+ minimizeOverriddenAssociatedTypes(inheritedAssociatedTypes);
+
+ // Sort the set of inherited associated types.
+ llvm::array_pod_sort(inheritedAssociatedTypes.begin(),
+ inheritedAssociatedTypes.end(),
+ compareSimilarAssociatedTypes);
+
+ return const_cast<AssociatedTypeDecl *>(this)
+ ->setOverriddenDecls(inheritedAssociatedTypes);
+}
+
+ArrayRef<AssociatedTypeDecl *> AssociatedTypeDecl::setOverriddenDecls(
+ ArrayRef<AssociatedTypeDecl *> overridden) {
+ assert(!AssociatedTypeDeclBits.ComputedOverridden &&
+ "Overridden decls already computed");
+ AssociatedTypeDeclBits.ComputedOverridden = true;
+
+ // If the set of overridden declarations is empty, note that.
+ if (overridden.empty()) {
+ AssociatedTypeDeclBits.HasOverridden = false;
+ return { };
+ }
+
+ // Record the overrides in the context.
+ auto &ctx = getASTContext();
+ AssociatedTypeDeclBits.HasOverridden = true;
+ auto overriddenCopy = ctx.AllocateCopy(overridden);
+ auto inserted =
+ ctx.Impl.AssociatedTypeOverrides.insert({this, overriddenCopy}).second;
+ (void)inserted;
+ assert(inserted && "Already recorded associated type overrides");
+ return overriddenCopy;
+}
+
bool ASTContext::canImportModule(std::pair<Identifier, SourceLoc> ModulePath) {
// If this module has already been successfully imported, it is importable.
if (getLoadedModule(ModulePath) != nullptr)
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 295c39d..e0987bd 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -667,6 +667,15 @@
[&](const RequirementRepr &req) { req.print(OS); },
[&] { OS << ", "; });
}
+ if (decl->overriddenDeclsComputed()) {
+ OS << " overridden=";
+ interleave(decl->getOverriddenDecls(),
+ [&](AssociatedTypeDecl *overridden) {
+ OS << overridden->getProtocol()->getName();
+ }, [&]() {
+ OS << ", ";
+ });
+ }
OS << ")";
}
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 8c44db6..ede44db 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1593,6 +1593,8 @@
return sdd->getOverriddenDecl();
if (auto cd = dyn_cast<ConstructorDecl>(this))
return cd->getOverriddenDecl();
+ if (auto at = dyn_cast<AssociatedTypeDecl>(this))
+ return at->getOverriddenDecl();
return nullptr;
}
@@ -2580,7 +2582,11 @@
TrailingWhereClause *trailingWhere)
: AbstractTypeParamDecl(DeclKind::AssociatedType, dc, name, nameLoc),
KeywordLoc(keywordLoc), DefaultDefinition(defaultDefinition),
- TrailingWhere(trailingWhere) {}
+ TrailingWhere(trailingWhere) {
+
+ AssociatedTypeDeclBits.ComputedOverridden = false;
+ AssociatedTypeDeclBits.HasOverridden = false;
+}
AssociatedTypeDecl::AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc,
Identifier name, SourceLoc nameLoc,
@@ -2591,6 +2597,8 @@
KeywordLoc(keywordLoc), TrailingWhere(trailingWhere),
Resolver(definitionResolver), ResolverContextData(resolverData) {
assert(Resolver && "missing resolver");
+ AssociatedTypeDeclBits.ComputedOverridden = false;
+ AssociatedTypeDeclBits.HasOverridden = false;
}
void AssociatedTypeDecl::computeType() {
@@ -2617,6 +2625,29 @@
return SourceRange(KeywordLoc, endLoc);
}
+AssociatedTypeDecl *AssociatedTypeDecl::getAssociatedTypeAnchor() const {
+ auto overridden = getOverriddenDecls();
+
+ // If this declaration does not override any other declarations, it's
+ // the anchor.
+ if (overridden.empty()) return const_cast<AssociatedTypeDecl *>(this);
+
+ // Find the best anchor among the anchors of the overridden decls.
+ AssociatedTypeDecl *bestAnchor = nullptr;
+ for (auto assocType : overridden) {
+ auto anchor = assocType->getAssociatedTypeAnchor();
+ if (!bestAnchor || compare(anchor, bestAnchor) < 0)
+ bestAnchor = anchor;
+ }
+
+ return bestAnchor;
+}
+
+AssociatedTypeDecl *AssociatedTypeDecl::getOverriddenDecl() const {
+ auto overridden = getOverriddenDecls();
+ return overridden.empty() ? nullptr : overridden.front();
+}
+
EnumDecl::EnumDecl(SourceLoc EnumLoc,
Identifier Name, SourceLoc NameLoc,
MutableArrayRef<TypeLoc> Inherited,
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index eb2de97..ba903ae 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -1604,6 +1604,13 @@
assocType2->getName().str()))
return result;
+ // Prefer an associated type with no overrides (i.e., an anchor) to one
+ // that has overrides.
+ bool hasOverridden1 = !assocType1->getOverriddenDecls().empty();
+ bool hasOverridden2 = !assocType2->getOverriddenDecls().empty();
+ if (hasOverridden1 != hasOverridden2)
+ return hasOverridden1 ? +1 : -1;
+
// - by protocol, so t_n_m.`P.T` < t_n_m.`Q.T` (given P < Q)
auto proto1 = assocType1->getProtocol();
auto proto2 = assocType2->getProtocol();
@@ -1655,6 +1662,7 @@
// Look for types with the given name in protocols that we know about.
AssociatedTypeDecl *bestAssocType = nullptr;
+ llvm::SmallSetVector<AssociatedTypeDecl *, 4> assocTypeAnchors;
SmallVector<TypeDecl *, 4> concreteDecls;
for (const auto &conforms : conformsTo) {
ProtocolDecl *proto = conforms.first;
@@ -1665,6 +1673,10 @@
// If this is an associated type, record whether it is the best
// associated type we've seen thus far.
if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
+ // Retrieve the associated type anchor.
+ assocType = assocType->getAssociatedTypeAnchor();
+ assocTypeAnchors.insert(assocType);
+
if (!bestAssocType ||
compareAssociatedTypes(assocType, bestAssocType) < 0)
bestAssocType = assocType;
@@ -1721,6 +1733,22 @@
}
}
+ // Infer same-type constraints among same-named associated type anchors.
+ if (assocTypeAnchors.size() > 1) {
+ auto &builder = *members.front()->getBuilder();
+ auto anchorType = getAnchor({ });
+ auto inferredSource = FloatingRequirementSource::forInferred(nullptr);
+ for (auto assocType : assocTypeAnchors) {
+ if (assocType == bestAssocType) continue;
+
+ builder.addRequirement(
+ Requirement(RequirementKind::SameType,
+ DependentMemberType::get(anchorType, bestAssocType),
+ DependentMemberType::get(anchorType, assocType)),
+ inferredSource, nullptr);
+ }
+ }
+
// Form the new cache entry.
CachedNestedType entry;
entry.numConformancesPresent = conformsTo.size();
@@ -1730,6 +1758,8 @@
entry.types.push_back(bestAssocType);
entry.types.insert(entry.types.end(),
concreteDecls.begin(), concreteDecls.end());
+ assert(bestAssocType->getOverriddenDecls().empty() &&
+ "Lookup should never keep a non-anchor associated type");
} else if (!concreteDecls.empty()) {
// Find the best concrete type.
auto bestConcreteTypeIter =
@@ -2552,6 +2582,11 @@
if (!type) return nullptr;
AssociatedTypeDecl *assocType = dyn_cast<AssociatedTypeDecl>(type);
+
+ // Always refer to the archetype anchor.
+ if (assocType)
+ assocType = assocType->getAssociatedTypeAnchor();
+
TypeDecl *concreteDecl = assocType ? nullptr : type;
// If we were asked for a complete, well-formed archetype, make sure we
@@ -3276,10 +3311,6 @@
// If we have inherited associated type...
if (auto inheritedAssocTypeDecl =
dyn_cast<AssociatedTypeDecl>(inheritedType)) {
- // Infer a same-type requirement among the same-named associated
- // types.
- addInferredSameTypeReq(assocTypeDecl, inheritedAssocTypeDecl);
-
// Complain about the first redeclaration.
if (shouldWarnAboutRedeclaration) {
auto inheritedFromProto = inheritedAssocTypeDecl->getProtocol();
@@ -5472,53 +5503,6 @@
collapsedParents.end());
}
-/// Check whether two potential archetypes "structurally" match, e.g.,
-/// the names match up to the root (which must match).
-static bool potentialArchetypesStructurallyMatch(PotentialArchetype *pa1,
- PotentialArchetype *pa2) {
- auto parent1 = pa1->getParent();
- auto parent2 = pa2->getParent();
- if (!parent1 && !parent2)
- return pa1->getGenericParamKey() == pa2->getGenericParamKey();
-
- // Check for depth mismatch.
- if (static_cast<bool>(parent1) != static_cast<bool>(parent2))
- return false;
-
- // Check names.
- if (pa1->getNestedName() != pa2->getNestedName())
- return false;
-
- return potentialArchetypesStructurallyMatch(parent1, parent2);
-}
-
-/// Look for structurally-equivalent types within the given equivalence class,
-/// collapsing their components.
-static void collapseStructurallyEquivalentSameTypeComponents(
- EquivalenceClass *equivClass,
- llvm::SmallDenseMap<PotentialArchetype *, unsigned> &componentOf,
- SmallVectorImpl<unsigned> &collapsedParents,
- unsigned &remainingComponents) {
- for (unsigned i : indices(equivClass->members)) {
- auto pa1 = equivClass->members[i];
- auto rep1 = findRepresentative(collapsedParents, componentOf[pa1]);
- for (unsigned j : indices(equivClass->members).slice(i + 1)) {
- auto pa2 = equivClass->members[j];
- auto rep2 = findRepresentative(collapsedParents, componentOf[pa2]);
- if (rep1 == rep2) continue;
-
- auto depth = pa1->getNestingDepth();
- if (depth < 2 || depth != pa2->getNestingDepth()) continue;
-
- if (potentialArchetypesStructurallyMatch(pa1, pa2) &&
- unionSets(collapsedParents, rep1, rep2)) {
- --remainingComponents;
- rep1 = findRepresentative(collapsedParents, componentOf[pa1]);
- }
- }
- }
-}
-
/// Collapse same-type components within an equivalence class, minimizing the
/// number of requirements required to express the equivalence class.
static void collapseSameTypeComponents(
@@ -5579,14 +5563,6 @@
builder, equivClass, componentOf, collapsedParents, remainingComponents);
}
- if (remainingComponents > 1) {
- // Collapse structurally-equivalent components.
- collapseStructurallyEquivalentSameTypeComponents(equivClass,
- componentOf,
- collapsedParents,
- remainingComponents);
- }
-
// If needed, collapse the same-type components merged by a derived
// nested-type-name-match edge.
unsigned maxComponents = equivClass->derivedSameTypeComponents.size();
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 09f2946..85059fa 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -1022,8 +1022,6 @@
std::get<1>(types))) {
return *result;
}
-
- // FIXME: Consider default arguments here?
}
// If the witness is 'throws', the requirement must be.
@@ -4276,7 +4274,6 @@
SWIFT_DEFER { Conformance->setState(initialState); };
for (auto assocType : Proto->getAssociatedTypeMembers()) {
-
// If we already have a type witness, do nothing.
if (Conformance->hasTypeWitness(assocType))
continue;
@@ -4599,6 +4596,24 @@
continue;
}
+ // If there is a generic parameter of the named type, use that.
+ if (auto gpList = DC->getGenericParamsOfContext()) {
+ GenericTypeParamDecl *foundGP = nullptr;
+ for (auto gp : *gpList) {
+ if (gp->getName() == assocType->getName()) {
+ foundGP = gp;
+ break;
+ }
+ }
+
+ if (foundGP) {
+ auto gpType = DC->mapTypeIntoContext(
+ foundGP->getDeclaredInterfaceType());
+ typeWitnesses.insert(assocType, {gpType, reqDepth});
+ continue;
+ }
+ }
+
// The solution is incomplete.
recordMissing();
return;
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 4730baf..18a430d 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -2502,11 +2502,13 @@
DeclContextID contextID;
TypeID defaultDefinitionID;
bool isImplicit;
+ ArrayRef<uint64_t> rawOverriddenIDs;
decls_block::AssociatedTypeDeclLayout::readRecord(scratch, nameID,
contextID,
defaultDefinitionID,
- isImplicit);
+ isImplicit,
+ rawOverriddenIDs);
auto DC = ForcedContext ? *ForcedContext : getDeclContext(contextID);
if (declOrOffset.isComplete())
@@ -2533,6 +2535,17 @@
assocType->setImplicit();
assocType->setCheckedInheritanceClause();
+
+ // Overridden associated types.
+ SmallVector<AssociatedTypeDecl *, 2> overriddenAssocTypes;
+ for (auto overriddenID : rawOverriddenIDs) {
+ if (auto overriddenAssocType =
+ dyn_cast_or_null<AssociatedTypeDecl>(getDecl(overriddenID))) {
+ overriddenAssocTypes.push_back(overriddenAssocType);
+ }
+ }
+ (void)assocType->setOverriddenDecls(overriddenAssocTypes);
+
break;
}
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 9340120..bb6ec14 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -2720,6 +2720,10 @@
verifyAttrSerializable(assocType);
auto contextID = addDeclContextRef(assocType->getDeclContext());
+ SmallVector<DeclID, 4> overriddenAssocTypeIDs;
+ for (auto overridden : assocType->getOverriddenDecls()) {
+ overriddenAssocTypeIDs.push_back(addDeclRef(overridden));
+ }
unsigned abbrCode = DeclTypeAbbrCodes[AssociatedTypeDeclLayout::Code];
AssociatedTypeDeclLayout::emitRecord(
@@ -2727,7 +2731,8 @@
addDeclBaseNameRef(assocType->getName()),
contextID,
addTypeRef(assocType->getDefaultDefinitionType()),
- assocType->isImplicit());
+ assocType->isImplicit(),
+ overriddenAssocTypeIDs);
break;
}
diff --git a/test/Generics/protocol_requirement_signatures.swift b/test/Generics/protocol_requirement_signatures.swift
index 1007e7b..676b1bf 100644
--- a/test/Generics/protocol_requirement_signatures.swift
+++ b/test/Generics/protocol_requirement_signatures.swift
@@ -33,16 +33,16 @@
// inheritance without any new requirements
// CHECK-LABEL: .Q3@
-// CHECK-NEXT: Requirement signature: <Self where Self : Q1, Self.X == Self.X>
-// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0 : Q1, τ_0_0.X == τ_0_0.X>
+// CHECK-NEXT: Requirement signature: <Self where Self : Q1>
+// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0 : Q1>
protocol Q3: Q1 {
associatedtype X // expected-warning{{redeclaration of associated type 'X'}}
}
// inheritance adding a new conformance
// CHECK-LABEL: .Q4@
-// CHECK-NEXT: Requirement signature: <Self where Self : Q1, Self.X : P2, Self.X == Self.X>
-// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0 : Q1, τ_0_0.X : P2, τ_0_0.X == τ_0_0.X>
+// CHECK-NEXT: Requirement signature: <Self where Self : Q1, Self.X : P2>
+// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0 : Q1, τ_0_0.X : P2>
protocol Q4: Q1 {
associatedtype X: P2 // expected-warning{{redeclaration of associated type 'X'}}
// expected-note@-1 2{{'X' declared here}}
@@ -56,8 +56,8 @@
// multiple inheritance without any new requirements
// CHECK-LABEL: .Q6@
-// CHECK-NEXT: Requirement signature: <Self where Self : Q2, Self : Q3, Self : Q4, Self.X == Self.X>
-// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0 : Q3, τ_0_0 : Q4, τ_0_0.X == τ_0_0.X>
+// 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>
protocol Q6: Q2, // expected-note{{conformance constraint 'Self.X': 'P1' implied here}}
Q3, Q4 {
associatedtype X: P1 // expected-warning{{redundant conformance constraint 'Self.X': 'P1'}}
@@ -66,8 +66,8 @@
// multiple inheritance with a new conformance
// CHECK-LABEL: .Q7@
-// CHECK-NEXT: Requirement signature: <Self where Self : Q2, Self : Q3, Self : Q4, Self.X : P3, Self.X == Self.X>
-// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0 : Q3, τ_0_0 : Q4, τ_0_0.X : P3, τ_0_0.X == τ_0_0.X>
+// CHECK-NEXT: Requirement signature: <Self where Self : Q2, Self : Q3, Self : Q4, Self.X : P3>
+// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0 : Q3, τ_0_0 : Q4, τ_0_0.X : P3>
protocol Q7: Q2, Q3, Q4 {
associatedtype X: P3 // expected-warning{{redeclaration of associated type 'X'}}
}
diff --git a/test/Generics/requirement_inference.swift b/test/Generics/requirement_inference.swift
index 1342d29..38fd692 100644
--- a/test/Generics/requirement_inference.swift
+++ b/test/Generics/requirement_inference.swift
@@ -158,7 +158,8 @@
func sameTypeConcrete1<T : P9 & P10>(_: T) where T.A == X3, T.C == T.B, T.C == Int { }
// CHECK-LABEL: sameTypeConcrete2@
-// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P10, τ_0_0 : P9, τ_0_0.A == τ_0_0.A, τ_0_0.B == X3, τ_0_0.C == X3>
+// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P10, τ_0_0 : P9, τ_0_0.B == X3, τ_0_0.C == X3>
+// FIXME: Should have τ_0_0.A == τ_0_0.A
func sameTypeConcrete2<T : P9 & P10>(_: T) where T.B : X3, T.C == T.B, T.C == X3 { }
// expected-warning@-1{{redundant superclass constraint 'T.B' : 'X3'}}
// expected-note@-2{{same-type constraint 'T.C' == 'X3' written here}}
@@ -396,5 +397,5 @@
protocol P31 { }
// CHECK-LABEL: .sameTypeNameMatch1@
-// Generic signature: <T where T : P29, T : P30, T.X : P31, T.X == T.X>
+// CHECK: Generic signature: <T where T : P29, T : P30, T.X : P31, T.X == T.X>
func sameTypeNameMatch1<T: P29 & P30>(_: T) where T.X: P31 { }
diff --git a/test/Generics/sr5726.swift b/test/Generics/sr5726.swift
new file mode 100644
index 0000000..70a04d5
--- /dev/null
+++ b/test/Generics/sr5726.swift
@@ -0,0 +1,16 @@
+// RUN: %target-typecheck-verify-swift
+
+// SR-5726
+protocol Foo
+{
+ associatedtype Bar
+ var bar: Bar { get }
+}
+
+extension Foo where Self: Collection, Bar: Collection, Self.SubSequence == Bar.SubSequence, Self.Index == Bar.Index
+{
+ subscript(_ bounds: Range<Index>) -> SubSequence
+ {
+ return bar[bounds]
+ }
+}
diff --git a/test/IRGen/associated_types.swift b/test/IRGen/associated_types.swift
index 62fb04d..7ddaf0e 100644
--- a/test/IRGen/associated_types.swift
+++ b/test/IRGen/associated_types.swift
@@ -66,11 +66,12 @@
// information for archetypes from all paths to that archetype, not just
// its parent relationships.
-func testFastRuncible<T: Runcible, U: FastRuncible where T.RuncerType == U.RuncerType>(_ t: T, u: U) {
+func testFastRuncible<T: Runcible, U: FastRuncible>(_ t: T, u: U)
+ where T.RuncerType == U.RuncerType {
U.RuncerType.Runcee.accelerate()
}
-// CHECK: define hidden swiftcc void @_T016associated_types16testFastRuncibleyx_q_1utAA0E0RzAA0dE0R_10RuncerTypeQy_AFRtzr0_lF(%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %T, %swift.type* %U, i8** %T.Runcible, i8** %U.FastRuncible) #0 {
+// CHECK: define hidden swiftcc void @_T016associated_types16testFastRuncibleyx_q_1utAA0E0RzAA0dE0R_10RuncerTypeQy_AFRtzAF_6RunceeAA0F0PQZAF_AiA0dF0PRTzr0_lF(%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %T, %swift.type* %U, i8** %T.Runcible, i8** %U.FastRuncible) #0 {
// 1. Get the type metadata for U.RuncerType.Runcee.
// 1a. Get the type metadata for U.RuncerType.
// Note that we actually look things up in T, which is going to prove unfortunate.
diff --git a/test/SourceKit/CursorInfo/cursor_overrides.swift b/test/SourceKit/CursorInfo/cursor_overrides.swift
index a302b79..1e6415a 100644
--- a/test/SourceKit/CursorInfo/cursor_overrides.swift
+++ b/test/SourceKit/CursorInfo/cursor_overrides.swift
@@ -16,6 +16,15 @@
x.meth()
}
+public protocol WithAssocType {
+ /// Some kind of associated type
+ associatedtype AssocType
+}
+
+public protocol WithInheritedAssocType : WithAssocType {
+ associatedtype AssocType = Int
+}
+
// REQUIRES: objc_interop
// RUN: %sourcekitd-test -req=cursor -pos=16:7 %s -- -embed-bitcode -I %S/Inputs/cursor-overrides %mcp_opt %s | %FileCheck -check-prefix=CHECK1 %s
// CHECK1: source.lang.swift.ref.function.method.instance (12:8-12:14)
@@ -28,3 +37,9 @@
// CHECK1-NEXT: c:objc(cs)B1(im)meth
// CHECK1-NEXT: c:objc(pl)P1(im)meth
// CHECK1-NEXT: OVERRIDES END
+
+// RUN: %sourcekitd-test -req=cursor -pos=25:20 %s -- -embed-bitcode -I %S/Inputs/cursor-overrides %mcp_opt %s | %FileCheck -check-prefix=CHECK2 %s
+// CHECK2: s:16cursor_overrides22WithInheritedAssocTypeP0eF0
+// CHECK2: OVERRIDES BEGIN
+// CHECK2-NEXT: s:16cursor_overrides13WithAssocTypeP0dE0
+// CHECK2-NEXT: OVERRIDES END
diff --git a/test/SourceKit/InterfaceGen/gen_swift_module.swift b/test/SourceKit/InterfaceGen/gen_swift_module.swift
index 7df6ce9..33c4418 100644
--- a/test/SourceKit/InterfaceGen/gen_swift_module.swift
+++ b/test/SourceKit/InterfaceGen/gen_swift_module.swift
@@ -15,12 +15,12 @@
// RUN: %swift -emit-module -o %t.mod/swift_mod_syn.swiftmodule %S/Inputs/swift_mod_syn.swift -parse-as-library
// RUN: %sourcekitd-test -req=interface-gen-open -module swift_mod_syn -- -I %t.mod == -req=cursor -pos=4:7 %s -- %s -I %t.mod | %FileCheck -check-prefix=SYNTHESIZED-USR1 %s
-// SYNTHESIZED-USR1: s:s17MutableCollectionPssAARzs012RandomAccessB0Rzs10Comparable7Elements013BidirectionalB0PRpzlE4sortyyF::SYNTHESIZED::s:Sa
+// SYNTHESIZED-USR1: s:s17MutableCollectionPssAARzs012RandomAccessB0Rzs10Comparable7Elements8SequencePRpzlE4sortyyF::SYNTHESIZED::s:Sa
// RUN: %sourcekitd-test -req=interface-gen-open -module Swift -synthesized-extension \
-// RUN: == -req=find-usr -usr "s:s17MutableCollectionPssAARzs012RandomAccessB0Rzs10Comparable7Elements013BidirectionalB0PRpzlE4sortyyF::SYNTHESIZED::s:Sa" | %FileCheck -check-prefix=SYNTHESIZED-USR2 %s
+// RUN: == -req=find-usr -usr "s:s17MutableCollectionPssAARzs012RandomAccessB0Rzs10Comparable7Elements8SequencePRpzlE4sortyyF::SYNTHESIZED::s:Sa" | %FileCheck -check-prefix=SYNTHESIZED-USR2 %s
// SYNTHESIZED-USR2-NOT: USR NOT FOUND
// RUN: %sourcekitd-test -req=interface-gen-open -module Swift \
-// RUN: == -req=find-usr -usr "s:s17MutableCollectionPssAARzs012RandomAccessB0Rzs10Comparable7Elements013BidirectionalB0PRpzlE4sortyyF::SYNTHESIZED::s:Sa::SYNTHESIZED::USRDOESNOTEXIST" | %FileCheck -check-prefix=SYNTHESIZED-USR3 %s
+// RUN: == -req=find-usr -usr "s:s17MutableCollectionPssAARzs012RandomAccessB0Rzs10Comparable7Elements8SequencePRpzlE4sortyyF::SYNTHESIZED::s:Sa::SYNTHESIZED::USRDOESNOTEXIST" | %FileCheck -check-prefix=SYNTHESIZED-USR3 %s
// SYNTHESIZED-USR3-NOT: USR NOT FOUND
diff --git a/test/decl/protocol/associated_type_overrides.swift b/test/decl/protocol/associated_type_overrides.swift
new file mode 100644
index 0000000..99e8eaf
--- /dev/null
+++ b/test/decl/protocol/associated_type_overrides.swift
@@ -0,0 +1,28 @@
+// RUN: %target-swift-frontend -typecheck -dump-ast %s 2>&1 | %FileCheck %s
+
+protocol P1 {
+ associatedtype A
+}
+
+// CHECK-LABEL: protocol "P2"
+// CHECK-NEXT: (associated_type_decl "A" {{.*}} overridden=P1))
+protocol P2 : P1 {
+ associatedtype A
+}
+
+protocol P3 {
+ associatedtype A
+}
+
+// CHECK-LABEL: protocol "P4"
+// CHECK-NEXT: (associated_type_decl "A" {{.*}} overridden=P2, P3))
+protocol P4 : P2, P3 {
+ associatedtype A
+}
+
+// CHECK-LABEL: protocol "P5"
+// CHECK-NEXT: (associated_type_decl "A" {{.*}} overridden=P4))
+protocol P5 : P4, P2 {
+ associatedtype A
+}
+
diff --git a/test/decl/protocol/req/associated_type_inference.swift b/test/decl/protocol/req/associated_type_inference.swift
index 43f99ad..5885342 100644
--- a/test/decl/protocol/req/associated_type_inference.swift
+++ b/test/decl/protocol/req/associated_type_inference.swift
@@ -195,9 +195,9 @@
func then(_ success: (_: T) -> T) -> Self
}
-public class CorePromise<T> : Thenable { // expected-error{{type 'CorePromise<T>' does not conform to protocol 'Thenable'}}
- public func then(_ success: @escaping (_ t: T, _: CorePromise<T>) -> T) -> Self {
- return self.then() { (t: T) -> T in
+public class CorePromise<U> : Thenable { // expected-error{{type 'CorePromise<U>' does not conform to protocol 'Thenable'}}
+ public func then(_ success: @escaping (_ t: U, _: CorePromise<U>) -> U) -> Self {
+ return self.then() { (t: U) -> U in // expected-error{{contextual closure type '(U, CorePromise<U>) -> U' expects 2 arguments, but 1 was used in closure body}}
return success(t: t, self)
}
}
@@ -390,3 +390,13 @@
struct S13 : P13 { // expected-error{{type 'S13' does not conform to protocol 'P13'}}
func foo(arg: inout Int) {}
}
+
+// "Infer" associated type from generic parameter.
+protocol P14 {
+ associatedtype Value
+}
+
+struct P14a<Value>: P14 { }
+
+struct P14b<Value> { }
+extension P14b: P14 { }
diff --git a/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift b/validation-test/compiler_crashers/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
similarity index 89%
rename from validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
rename to validation-test/compiler_crashers/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
index 3902655..b57ef5e 100644
--- a/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
+++ b/validation-test/compiler_crashers/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
@@ -6,5 +6,5 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// REQUIRES: asserts
-// RUN: not %target-swift-frontend %s -emit-ir
+// RUN: not --crash %target-swift-frontend %s -emit-ir
class a:RangeReplaceableCollection}protocol P{{}typealias e:a{{}}typealias e:Collection