Skip to content

Commit cf411ed

Browse files
committed
Merge pull request #627 from swiftix/wip-archetype-builder-refactoring
Add getGenericSignature() helper method to ArchetypeBuilder
2 parents cb94f5f + 52147ec commit cf411ed

File tree

3 files changed

+177
-193
lines changed

3 files changed

+177
-193
lines changed

include/swift/AST/ArchetypeBuilder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,14 @@ class ArchetypeBuilder {
251251
bool addGenericSignature(GenericSignature *sig, bool adoptArchetypes,
252252
bool treatRequirementsAsExplicit = false);
253253

254+
/// \brief Get a generic signature based on the provided complete list
255+
/// of generic parameter types.
256+
///
257+
/// \returns a generic signature build based on the provided list of
258+
/// generic parameter types.
259+
GenericSignature *
260+
getGenericSignature(ArrayRef<GenericTypeParamType *> genericParamsTypes);
261+
254262
/// Infer requirements from the given type, recursively.
255263
///
256264
/// This routine infers requirements from a type that occurs within the

lib/AST/ArchetypeBuilder.cpp

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1845,3 +1845,169 @@ bool ArchetypeBuilder::addGenericSignature(GenericSignature *sig,
18451845
Type ArchetypeBuilder::substDependentType(Type type) {
18461846
return substConcreteTypesForDependentTypes(*this, type);
18471847
}
1848+
1849+
/// Add the requirements for the given potential archetype and its nested
1850+
/// potential archetypes to the set of requirements.
1851+
static void
1852+
addRequirements(
1853+
Module &mod, Type type,
1854+
ArchetypeBuilder::PotentialArchetype *pa,
1855+
llvm::SmallPtrSet<ArchetypeBuilder::PotentialArchetype *, 16> &knownPAs,
1856+
SmallVectorImpl<Requirement> &requirements) {
1857+
// If the potential archetype has been bound away to a concrete type,
1858+
// it needs no requirements.
1859+
if (pa->isConcreteType())
1860+
return;
1861+
1862+
// Add a value witness marker.
1863+
requirements.push_back(Requirement(RequirementKind::WitnessMarker,
1864+
type, Type()));
1865+
1866+
// Add superclass requirement, if needed.
1867+
if (auto superclass = pa->getSuperclass()) {
1868+
// FIXME: Distinguish superclass from conformance?
1869+
// FIXME: What if the superclass type involves a type parameter?
1870+
requirements.push_back(Requirement(RequirementKind::Conformance,
1871+
type, superclass));
1872+
}
1873+
1874+
// Add conformance requirements.
1875+
SmallVector<ProtocolDecl *, 4> protocols;
1876+
for (const auto &conforms : pa->getConformsTo()) {
1877+
protocols.push_back(conforms.first);
1878+
}
1879+
1880+
ProtocolType::canonicalizeProtocols(protocols);
1881+
for (auto proto : protocols) {
1882+
requirements.push_back(Requirement(RequirementKind::Conformance,
1883+
type, proto->getDeclaredType()));
1884+
}
1885+
}
1886+
1887+
static void
1888+
addNestedRequirements(
1889+
Module &mod, Type type,
1890+
ArchetypeBuilder::PotentialArchetype *pa,
1891+
llvm::SmallPtrSet<ArchetypeBuilder::PotentialArchetype *, 16> &knownPAs,
1892+
SmallVectorImpl<Requirement> &requirements) {
1893+
using PotentialArchetype = ArchetypeBuilder::PotentialArchetype;
1894+
1895+
// Collect the nested types, sorted by name.
1896+
// FIXME: Could collect these from the conformance requirements, above.
1897+
SmallVector<std::pair<Identifier, PotentialArchetype*>, 16> nestedTypes;
1898+
for (const auto &nested : pa->getNestedTypes()) {
1899+
// FIXME: Dropping requirements among different associated types of the
1900+
// same name.
1901+
nestedTypes.push_back(std::make_pair(nested.first, nested.second.front()));
1902+
}
1903+
std::sort(nestedTypes.begin(), nestedTypes.end(),
1904+
OrderPotentialArchetypeByName());
1905+
1906+
// Add requirements for associated types.
1907+
for (const auto &nested : nestedTypes) {
1908+
auto rep = nested.second->getRepresentative();
1909+
if (knownPAs.insert(rep).second) {
1910+
// Form the dependent type that refers to this archetype.
1911+
auto assocType = nested.second->getResolvedAssociatedType();
1912+
if (!assocType)
1913+
continue; // FIXME: If we do this late enough, there will be no failure.
1914+
1915+
// Skip nested types bound to concrete types.
1916+
if (rep->isConcreteType())
1917+
continue;
1918+
1919+
auto nestedType = DependentMemberType::get(type, assocType,
1920+
mod.getASTContext());
1921+
1922+
addRequirements(mod, nestedType, rep, knownPAs, requirements);
1923+
addNestedRequirements(mod, nestedType, rep, knownPAs, requirements);
1924+
}
1925+
}
1926+
}
1927+
1928+
1929+
/// Collect the set of requirements placed on the given generic parameters and
1930+
/// their associated types.
1931+
static void collectRequirements(ArchetypeBuilder &builder,
1932+
ArrayRef<GenericTypeParamType *> params,
1933+
SmallVectorImpl<Requirement> &requirements) {
1934+
typedef ArchetypeBuilder::PotentialArchetype PotentialArchetype;
1935+
1936+
// Find the "primary" potential archetypes, from which we'll collect all
1937+
// of the requirements.
1938+
llvm::SmallPtrSet<PotentialArchetype *, 16> knownPAs;
1939+
llvm::SmallVector<GenericTypeParamType *, 8> primary;
1940+
for (auto param : params) {
1941+
auto pa = builder.resolveArchetype(param);
1942+
assert(pa && "Missing potential archetype for generic parameter");
1943+
1944+
// We only care about the representative.
1945+
pa = pa->getRepresentative();
1946+
1947+
if (knownPAs.insert(pa).second)
1948+
primary.push_back(param);
1949+
}
1950+
1951+
// Add all of the conformance and superclass requirements placed on the given
1952+
// generic parameters and their associated types.
1953+
unsigned primaryIdx = 0, numPrimary = primary.size();
1954+
while (primaryIdx < numPrimary) {
1955+
unsigned depth = primary[primaryIdx]->getDepth();
1956+
1957+
// For each of the primary potential archetypes, add the requirements.
1958+
// Stop when we hit a parameter at a different depth.
1959+
// FIXME: This algorithm falls out from the way the "all archetypes" lists
1960+
// are structured. Once those lists no longer exist or are no longer
1961+
// "the truth", we can simplify this algorithm considerably.
1962+
unsigned lastPrimaryIdx = primaryIdx;
1963+
for (unsigned idx = primaryIdx;
1964+
idx < numPrimary && primary[idx]->getDepth() == depth;
1965+
++idx, ++lastPrimaryIdx) {
1966+
auto param = primary[idx];
1967+
auto pa = builder.resolveArchetype(param)->getRepresentative();
1968+
1969+
// Add other requirements.
1970+
addRequirements(builder.getModule(), param, pa, knownPAs,
1971+
requirements);
1972+
}
1973+
1974+
// For each of the primary potential archetypes, add the nested requirements.
1975+
for (unsigned idx = primaryIdx; idx < lastPrimaryIdx; ++idx) {
1976+
auto param = primary[idx];
1977+
auto pa = builder.resolveArchetype(param)->getRepresentative();
1978+
addNestedRequirements(builder.getModule(), param, pa, knownPAs,
1979+
requirements);
1980+
}
1981+
1982+
primaryIdx = lastPrimaryIdx;
1983+
}
1984+
1985+
1986+
// Add all of the same-type requirements.
1987+
for (auto req : builder.getSameTypeRequirements()) {
1988+
auto firstType = req.first->getDependentType(builder, false);
1989+
Type secondType;
1990+
if (auto concrete = req.second.dyn_cast<Type>())
1991+
secondType = concrete;
1992+
else if (auto secondPA = req.second.dyn_cast<PotentialArchetype*>())
1993+
secondType = secondPA->getDependentType(builder, false);
1994+
1995+
if (firstType->is<ErrorType>() || secondType->is<ErrorType>() ||
1996+
firstType->isEqual(secondType))
1997+
continue;
1998+
1999+
requirements.push_back(Requirement(RequirementKind::SameType,
2000+
firstType, secondType));
2001+
}
2002+
}
2003+
2004+
GenericSignature *ArchetypeBuilder::getGenericSignature(
2005+
ArrayRef<GenericTypeParamType *> genericParamTypes) {
2006+
// Collect the requirements placed on the generic parameter types.
2007+
SmallVector<Requirement, 4> requirements;
2008+
collectRequirements(*this, genericParamTypes, requirements);
2009+
2010+
auto sig = GenericSignature::get(genericParamTypes, requirements);
2011+
return sig;
2012+
}
2013+

0 commit comments

Comments
 (0)