Skip to content

Commit 7a7af62

Browse files
committed
ArchetypeBuilder: use enumerateRequirements() in getGenericSignature()
Instead of walking over PotentialArchetypes representatives directly and using a separate list to record same-type constraints, just use enumerateRequirements() and check the RequirementSource to drop redundant requirements. This means getGenericSignature() and getCanonicalManglingSignature() can share the same logic for collecting requirements; the only differences are the following: - both drop requirements from Redundant sources, but mangling signatures also drop requirements from Protocol sources - mangling signatures also canonicalize the types appearing in the final requirement
1 parent f19192d commit 7a7af62

11 files changed

+97
-286
lines changed

include/swift/AST/ArchetypeBuilder.h

+6-8
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,15 @@ class ArchetypeBuilder {
257257
/// \brief Get a generic signature based on the provided complete list
258258
/// of generic parameter types.
259259
///
260+
/// \param buildingCanonicalManglingSignature If true, requirements
261+
/// on associated types are dropped, and types in requirements
262+
/// are canonicalized.
263+
///
260264
/// \returns a generic signature built from the provided list of
261265
/// generic parameter types.
262266
GenericSignature *
263-
getGenericSignature(ArrayRef<GenericTypeParamType *> genericParamsTypes);
267+
getGenericSignature(ArrayRef<GenericTypeParamType *> genericParamsTypes,
268+
bool buildingCanonicalManglingSignature=false);
264269

265270
/// \brief Get a generic context based on the complete list of generic
266271
/// parameter types.
@@ -349,13 +354,6 @@ class ArchetypeBuilder {
349354
using SameTypeRequirement
350355
= std::pair<PotentialArchetype *,
351356
PointerUnion<Type, PotentialArchetype*>>;
352-
353-
/// Retrieve the set of same-type requirements that apply to the potential
354-
/// archetypes known to this builder.
355-
ArrayRef<SameTypeRequirement> getSameTypeRequirements() const;
356-
357-
// FIXME: Compute the set of 'extra' witness tables needed to express this
358-
// requirement set.
359357

360358
/// \brief Dump all of the requirements, both specified and inferred.
361359
LLVM_ATTRIBUTE_DEPRECATED(

lib/AST/ArchetypeBuilder.cpp

+54-194
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,6 @@ struct ArchetypeBuilder::Implementation {
123123
/// archetypes.
124124
llvm::MapVector<GenericTypeParamKey, PotentialArchetype*> PotentialArchetypes;
125125

126-
/// A vector containing the same-type requirements introduced into the
127-
/// system.
128-
SmallVector<SameTypeRequirement, 4> SameTypeRequirements;
129-
130126
/// The number of nested types that haven't yet been resolved to archetypes.
131127
/// Once all requirements have been added, this will be zero in well-formed
132128
/// code.
@@ -1131,8 +1127,6 @@ bool ArchetypeBuilder::addSameTypeRequirementBetweenArchetypes(
11311127
PotentialArchetype *T2,
11321128
RequirementSource Source)
11331129
{
1134-
auto OrigT1 = T1, OrigT2 = T2;
1135-
11361130
// Operate on the representatives
11371131
T1 = T1->getRepresentative();
11381132
T2 = T2->getRepresentative();
@@ -1199,11 +1193,6 @@ bool ArchetypeBuilder::addSameTypeRequirementBetweenArchetypes(
11991193
for (auto equiv : T2->EquivalenceClass)
12001194
T1->EquivalenceClass.push_back(equiv);
12011195

1202-
if (!T1->wasRenamed() && !T2->wasRenamed()) {
1203-
// Record this same-type requirement.
1204-
Impl->SameTypeRequirements.push_back({ OrigT1, OrigT2 });
1205-
}
1206-
12071196
// FIXME: superclass requirements!
12081197

12091198
// Add all of the protocol conformance requirements of T2 to T1.
@@ -1229,7 +1218,6 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
12291218
Type Concrete,
12301219
RequirementSource Source) {
12311220
// Operate on the representative.
1232-
auto OrigT = T;
12331221
T = T->getRepresentative();
12341222

12351223
assert(!T->ArchetypeOrConcreteType.getAsArchetype()
@@ -1279,8 +1267,6 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
12791267
T->ArchetypeOrConcreteType = NestedType::forConcreteType(Concrete);
12801268
T->SameTypeSource = Source;
12811269

1282-
Impl->SameTypeRequirements.push_back({OrigT, Concrete});
1283-
12841270
// Recursively resolve the associated types to their concrete types.
12851271
for (auto nested : T->getNestedTypes()) {
12861272
AssociatedTypeDecl *assocType
@@ -1804,11 +1790,6 @@ ArchetypeBuilder::getArchetype(GenericTypeParamDecl *GenericParam) {
18041790
return known->second->getType(*this).getAsArchetype();
18051791
}
18061792

1807-
ArrayRef<ArchetypeBuilder::SameTypeRequirement>
1808-
ArchetypeBuilder::getSameTypeRequirements() const {
1809-
return Impl->SameTypeRequirements;
1810-
}
1811-
18121793
template<typename F>
18131794
void ArchetypeBuilder::visitPotentialArchetypes(F f) {
18141795
// Stack containing all of the potential archetypes to visit.
@@ -1838,32 +1819,6 @@ void ArchetypeBuilder::visitPotentialArchetypes(F f) {
18381819
}
18391820
}
18401821

1841-
namespace {
1842-
/// \brief Function object that orders potential archetypes by name.
1843-
struct OrderPotentialArchetypeByName {
1844-
using PotentialArchetype = ArchetypeBuilder::PotentialArchetype;
1845-
1846-
bool operator()(std::pair<Identifier, PotentialArchetype *> X,
1847-
std::pair<Identifier, PotentialArchetype *> Y) const {
1848-
return X.first.str() < Y.second->getName().str();
1849-
}
1850-
1851-
bool operator()(std::pair<Identifier, PotentialArchetype *> X,
1852-
Identifier Y) const {
1853-
return X.first.str() < Y.str();
1854-
}
1855-
1856-
bool operator()(Identifier X,
1857-
std::pair<Identifier, PotentialArchetype *> Y) const {
1858-
return X.str() < Y.first.str();
1859-
}
1860-
1861-
bool operator()(Identifier X, Identifier Y) const {
1862-
return X.str() < Y.str();
1863-
}
1864-
};
1865-
}
1866-
18671822
void ArchetypeBuilder::enumerateRequirements(llvm::function_ref<
18681823
void (RequirementKind kind,
18691824
PotentialArchetype *archetype,
@@ -2061,173 +2016,78 @@ Type ArchetypeBuilder::substDependentType(Type type) {
20612016
return substConcreteTypesForDependentTypes(*this, type);
20622017
}
20632018

2064-
/// Add the requirements for the given potential archetype and its nested
2065-
/// potential archetypes to the set of requirements.
2066-
static void
2067-
addRequirements(
2068-
ArchetypeBuilder &builder, Type type,
2069-
ArchetypeBuilder::PotentialArchetype *pa,
2070-
llvm::SmallPtrSet<ArchetypeBuilder::PotentialArchetype *, 16> &knownPAs,
2071-
SmallVectorImpl<Requirement> &requirements) {
2072-
2073-
auto &ctx = builder.getASTContext();
2074-
2075-
// If the potential archetype has been bound away to a concrete type,
2076-
// it needs no requirements.
2077-
if (pa->isConcreteType())
2078-
return;
2079-
2080-
// Add a value witness marker.
2081-
requirements.push_back(Requirement(RequirementKind::WitnessMarker,
2082-
type, Type()));
2083-
2084-
// Add superclass requirement, if needed.
2085-
if (auto superclass = pa->getSuperclass()) {
2086-
// FIXME: What if the superclass type involves a type parameter?
2087-
requirements.push_back(Requirement(RequirementKind::Superclass,
2088-
type, superclass));
2089-
}
2090-
2091-
// Add conformance requirements.
2092-
SmallVector<ProtocolDecl *, 4> protocols;
2093-
for (const auto &conforms : pa->getConformsTo()) {
2094-
protocols.push_back(conforms.first);
2095-
}
2096-
2097-
ProtocolType::canonicalizeProtocols(protocols);
2098-
for (auto proto : protocols) {
2099-
requirements.push_back(Requirement(RequirementKind::Conformance, type,
2100-
ProtocolType::get(proto, ctx)));
2101-
}
2102-
}
2103-
2104-
static void
2105-
addNestedRequirements(
2106-
ArchetypeBuilder &builder,
2107-
ArchetypeBuilder::PotentialArchetype *pa,
2108-
llvm::SmallPtrSet<ArchetypeBuilder::PotentialArchetype *, 16> &knownPAs,
2109-
SmallVectorImpl<Requirement> &requirements) {
2110-
using PotentialArchetype = ArchetypeBuilder::PotentialArchetype;
2111-
2112-
// Collect the nested types, sorted by name.
2113-
// FIXME: Could collect these from the conformance requirements, above.
2114-
SmallVector<std::pair<Identifier, PotentialArchetype*>, 16> nestedTypes;
2115-
for (const auto &nested : pa->getNestedTypes()) {
2116-
// FIXME: Dropping requirements among different associated types of the
2117-
// same name.
2118-
// Skip type aliases, which are just shortcuts down the tree.
2119-
if (nested.second.front()->getTypeAliasDecl())
2120-
continue;
2121-
nestedTypes.push_back(std::make_pair(nested.first, nested.second.front()));
2122-
}
2123-
std::sort(nestedTypes.begin(), nestedTypes.end(),
2124-
OrderPotentialArchetypeByName());
2125-
2126-
// Add requirements for associated types.
2127-
for (const auto &nested : nestedTypes) {
2128-
auto rep = nested.second->getRepresentative();
2129-
if (knownPAs.insert(rep).second) {
2130-
// Form the dependent type that refers to this archetype.
2131-
auto assocType = nested.second->getResolvedAssociatedType();
2132-
if (!assocType)
2133-
continue; // FIXME: If we do this late enough, there will be no failure.
2134-
2135-
// Skip nested types bound to concrete types.
2136-
if (rep->isConcreteType())
2137-
continue;
2019+
/// Collect the set of requirements placed on the given generic parameters and
2020+
/// their associated types.
2021+
static void collectRequirements(ArchetypeBuilder &builder,
2022+
ArrayRef<GenericTypeParamType *> params,
2023+
SmallVectorImpl<Requirement> &requirements,
2024+
bool buildingCanonicalManglingSignature) {
2025+
builder.enumerateRequirements([&](RequirementKind kind,
2026+
ArchetypeBuilder::PotentialArchetype *archetype,
2027+
llvm::PointerUnion<Type, ArchetypeBuilder::PotentialArchetype *> type,
2028+
RequirementSource source) {
2029+
// Filter out redundant requirements.
2030+
switch (source.getKind()) {
2031+
case RequirementSource::Explicit:
2032+
case RequirementSource::Inferred:
2033+
// The requirement was explicit and required, keep it.
2034+
break;
21382035

2139-
auto nestedType =
2140-
rep->getDependentType(builder, /*allowUnresolved*/ false);
2036+
case RequirementSource::Protocol:
2037+
// We drop these requirements in canonical mangling signatures.
2038+
if (buildingCanonicalManglingSignature)
2039+
return;
2040+
break;
21412041

2142-
// Skip unresolved nested types.
2143-
if (nestedType->is<ErrorType>())
2144-
continue;
2042+
case RequirementSource::Redundant:
2043+
// The requirement was redundant, drop it.
2044+
return;
21452045

2146-
addRequirements(builder, nestedType, rep, knownPAs, requirements);
2147-
addNestedRequirements(builder, rep, knownPAs, requirements);
2046+
case RequirementSource::OuterScope:
2047+
assert(!buildingCanonicalManglingSignature &&
2048+
"mangling signature shouldn't have an outer scope");
2049+
break;
21482050
}
2149-
}
2150-
}
21512051

2052+
auto depTy = archetype->getDependentType(builder, false);
21522053

2153-
/// Collect the set of requirements placed on the given generic parameters and
2154-
/// their associated types.
2155-
static void collectRequirements(ArchetypeBuilder &builder,
2156-
ArrayRef<GenericTypeParamType *> params,
2157-
SmallVectorImpl<Requirement> &requirements) {
2158-
typedef ArchetypeBuilder::PotentialArchetype PotentialArchetype;
2159-
2160-
// Find the "primary" potential archetypes, from which we'll collect all
2161-
// of the requirements.
2162-
llvm::SmallPtrSet<PotentialArchetype *, 16> knownPAs;
2163-
llvm::SmallVector<GenericTypeParamType *, 8> primary;
2164-
for (auto param : params) {
2165-
auto pa = builder.resolveArchetype(param);
2166-
assert(pa && "Missing potential archetype for generic parameter");
2167-
2168-
// We only care about the representative.
2169-
pa = pa->getRepresentative();
2170-
2171-
if (knownPAs.insert(pa).second)
2172-
primary.push_back(param);
2173-
}
2054+
if (depTy->is<ErrorType>())
2055+
return;
21742056

2175-
// Add all of the conformance and superclass requirements placed on the given
2176-
// generic parameters and their associated types.
2177-
unsigned primaryIdx = 0, numPrimary = primary.size();
2178-
while (primaryIdx < numPrimary) {
2179-
unsigned depth = primary[primaryIdx]->getDepth();
2180-
2181-
// For each of the primary potential archetypes, add the requirements.
2182-
// Stop when we hit a parameter at a different depth.
2183-
// FIXME: This algorithm falls out from the way the "all archetypes" lists
2184-
// are structured. Once those lists no longer exist or are no longer
2185-
// "the truth", we can simplify this algorithm considerably.
2186-
unsigned lastPrimaryIdx = primaryIdx;
2187-
for (unsigned idx = primaryIdx;
2188-
idx < numPrimary && primary[idx]->getDepth() == depth;
2189-
++idx, ++lastPrimaryIdx) {
2190-
auto param = primary[idx];
2191-
auto pa = builder.resolveArchetype(param)->getRepresentative();
2192-
2193-
// Add other requirements.
2194-
addRequirements(builder, param, pa, knownPAs, requirements);
2057+
if (kind == RequirementKind::WitnessMarker) {
2058+
requirements.push_back(Requirement(kind, depTy, Type()));
2059+
return;
21952060
}
21962061

2197-
// For each of the primary potential archetypes, add the nested requirements.
2198-
for (unsigned idx = primaryIdx; idx < lastPrimaryIdx; ++idx) {
2199-
auto param = primary[idx];
2200-
auto pa = builder.resolveArchetype(param)->getRepresentative();
2201-
addNestedRequirements(builder, pa, knownPAs, requirements);
2062+
Type repTy;
2063+
if (auto concreteTy = type.dyn_cast<Type>()) {
2064+
// Maybe we were equated to a concrete type...
2065+
repTy = concreteTy;
2066+
} else {
2067+
// ...or to a dependent type.
2068+
repTy = type.get<ArchetypeBuilder::PotentialArchetype *>()
2069+
->getDependentType(builder, false);
22022070
}
22032071

2204-
primaryIdx = lastPrimaryIdx;
2205-
}
2206-
2207-
2208-
// Add all of the same-type requirements.
2209-
for (auto req : builder.getSameTypeRequirements()) {
2210-
auto firstType = req.first->getDependentType(builder, false);
2211-
Type secondType;
2212-
if (auto concrete = req.second.dyn_cast<Type>())
2213-
secondType = concrete;
2214-
else if (auto secondPA = req.second.dyn_cast<PotentialArchetype*>())
2215-
secondType = secondPA->getDependentType(builder, false);
2072+
if (repTy->is<ErrorType>())
2073+
return;
22162074

2217-
if (firstType->is<ErrorType>() || secondType->is<ErrorType>() ||
2218-
firstType->isEqual(secondType))
2219-
continue;
2075+
if (buildingCanonicalManglingSignature) {
2076+
depTy = depTy->getCanonicalType();
2077+
repTy = repTy->getCanonicalType();
2078+
}
22202079

2221-
requirements.push_back(Requirement(RequirementKind::SameType,
2222-
firstType, secondType));
2223-
}
2080+
requirements.push_back(Requirement(kind, depTy, repTy));
2081+
});
22242082
}
22252083

22262084
GenericSignature *ArchetypeBuilder::getGenericSignature(
2227-
ArrayRef<GenericTypeParamType *> genericParamTypes) {
2085+
ArrayRef<GenericTypeParamType *> genericParamTypes,
2086+
bool buildingCanonicalManglingSignature) {
22282087
// Collect the requirements placed on the generic parameter types.
22292088
SmallVector<Requirement, 4> requirements;
2230-
collectRequirements(*this, genericParamTypes, requirements);
2089+
collectRequirements(*this, genericParamTypes, requirements,
2090+
buildingCanonicalManglingSignature);
22312091

22322092
auto sig = GenericSignature::get(genericParamTypes, requirements);
22332093
return sig;

0 commit comments

Comments
 (0)