Skip to content

Commit b6d5443

Browse files
authored
Merge pull request #7398 from huonw/gsb-cleanups
[Generic signature builder] Substitute requirements instead of threading a PA around.
2 parents 1677701 + 923113d commit b6d5443

File tree

3 files changed

+90
-76
lines changed

3 files changed

+90
-76
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ class GenericSignatureBuilder {
172172
/// requirement mismatch.
173173
bool addSameTypeRequirement(
174174
Type T1, Type T2, RequirementSource Source,
175-
PotentialArchetype *basePA,
176175
llvm::function_ref<void(Type, Type)> diagnoseMismatch);
177176

178177
/// Add the requirements placed on the given abstract type parameter
@@ -258,7 +257,6 @@ class GenericSignatureBuilder {
258257
bool addRequirement(const Requirement &req, RequirementSource source);
259258

260259
bool addRequirement(const Requirement &req, RequirementSource source,
261-
PotentialArchetype *basePA,
262260
llvm::SmallPtrSetImpl<ProtocolDecl *> &Visited);
263261

264262
bool addLayoutRequirement(PotentialArchetype *PAT,
@@ -323,12 +321,7 @@ class GenericSignatureBuilder {
323321
/// signature are fully resolved).
324322
///
325323
/// For any type that cannot refer to an archetype, this routine returns null.
326-
///
327-
/// A non-null \c basePA is used in place of the "true" potential archetype
328-
/// for a GenericTypeParamType, effectively performing a substitution like,
329-
/// e.g., Self = <some PA>.
330-
PotentialArchetype *resolveArchetype(Type type,
331-
PotentialArchetype *basePA = nullptr);
324+
PotentialArchetype *resolveArchetype(Type type);
332325

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

include/swift/AST/Requirement.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,31 @@ class Requirement {
8686
return SecondType;
8787
}
8888

89+
/// \brief Subst the types involved in this requirement.
90+
///
91+
/// The \c args arguments are passed through to Type::subst. This doesn't
92+
/// touch the superclasses, protocols or layout constraints.
93+
template <typename... Args>
94+
Optional<Requirement> subst(Args &&... args) const {
95+
auto newFirst = getFirstType().subst(std::forward<Args>(args)...);
96+
if (!newFirst)
97+
return None;
98+
99+
switch (getKind()) {
100+
case RequirementKind::SameType: {
101+
auto newSecond = getSecondType().subst(std::forward<Args>(args)...);
102+
if (!newSecond)
103+
return None;
104+
return Requirement(getKind(), newFirst, newSecond);
105+
}
106+
case RequirementKind::Conformance:
107+
case RequirementKind::Superclass:
108+
return Requirement(getKind(), newFirst, getSecondType());
109+
case RequirementKind::Layout:
110+
return Requirement(getKind(), newFirst, getLayoutConstraint());
111+
}
112+
}
113+
89114
/// \brief Retrieve the layout constraint.
90115
LayoutConstraint getLayoutConstraint() const {
91116
assert(getKind() == RequirementKind::Layout);

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 64 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,19 @@ std::string GenericSignatureBuilder::PotentialArchetype::getDebugName() const {
136136
// Nested types.
137137
result += parent->getDebugName();
138138

139-
// When building the name for debugging purposes, include the
140-
// protocol into which the associated type was resolved.
139+
// When building the name for debugging purposes, include the protocol into
140+
// which the associated type or type alias was resolved.
141+
ProtocolDecl *proto = nullptr;
141142
if (auto assocType = getResolvedAssociatedType()) {
143+
proto = assocType->getProtocol();
144+
} else if (auto typeAlias = getTypeAliasDecl()) {
145+
proto = typeAlias->getParent()->getAsProtocolOrProtocolExtensionContext();
146+
}
147+
148+
if (proto) {
142149
result.push_back('[');
143150
result.push_back('.');
144-
result.append(assocType->getProtocol()->getName().str().begin(),
145-
assocType->getProtocol()->getName().str().end());
151+
result.append(proto->getName().str().begin(), proto->getName().str().end());
146152
result.push_back(']');
147153
}
148154

@@ -908,13 +914,11 @@ Type GenericSignatureBuilder::PotentialArchetype::getDependentType(
908914

909915
assert(isGenericParam() && "Not a generic parameter?");
910916

911-
unsigned index = getGenericParamKey().findIndexIn(genericParams);
912-
913917
// FIXME: This is a temporary workaround.
914-
if (genericParams.empty()) {
915-
return getBuilder()->Impl->GenericParams[index];
916-
}
918+
if (genericParams.empty())
919+
genericParams = getBuilder()->Impl->GenericParams;
917920

921+
unsigned index = getGenericParamKey().findIndexIn(genericParams);
918922
return genericParams[index];
919923
}
920924

@@ -1007,12 +1011,8 @@ LazyResolver *GenericSignatureBuilder::getLazyResolver() const {
10071011
return Context.getLazyResolver();
10081012
}
10091013

1010-
auto GenericSignatureBuilder::resolveArchetype(Type type, PotentialArchetype *basePA)
1011-
-> PotentialArchetype * {
1014+
auto GenericSignatureBuilder::resolveArchetype(Type type) -> PotentialArchetype * {
10121015
if (auto genericParam = type->getAs<GenericTypeParamType>()) {
1013-
if (basePA)
1014-
return basePA;
1015-
10161016
unsigned index = GenericParamKey(genericParam).findIndexIn(
10171017
Impl->GenericParams);
10181018
if (index < Impl->GenericParams.size())
@@ -1022,7 +1022,7 @@ auto GenericSignatureBuilder::resolveArchetype(Type type, PotentialArchetype *ba
10221022
}
10231023

10241024
if (auto dependentMember = type->getAs<DependentMemberType>()) {
1025-
auto base = resolveArchetype(dependentMember->getBase(), basePA);
1025+
auto base = resolveArchetype(dependentMember->getBase());
10261026
if (!base)
10271027
return nullptr;
10281028

@@ -1100,9 +1100,15 @@ bool GenericSignatureBuilder::addConformanceRequirement(PotentialArchetype *PAT,
11001100
if (Proto->isRequirementSignatureComputed()) {
11011101
auto reqSig = Proto->getRequirementSignature();
11021102

1103-
for (auto req : reqSig->getRequirements()) {
1103+
auto concreteSelf = T->getDependentType({}, /*allowUnresolved=*/true);
1104+
auto subMap = SubstitutionMap::getProtocolSubstitutions(
1105+
Proto, concreteSelf, ProtocolConformanceRef(Proto));
1106+
1107+
for (auto rawReq : reqSig->getRequirements()) {
1108+
auto req = rawReq.subst(subMap);
1109+
assert(req && "substituting Self in requirement shouldn't fail");
11041110
RequirementSource InnerSource(Kind, Source.getLoc());
1105-
addRequirement(req, InnerSource, T, Visited);
1111+
addRequirement(*req, InnerSource, Visited);
11061112
}
11071113
} else {
11081114
// Conformances to inherit protocols are explicit in a protocol requirement
@@ -1321,9 +1327,8 @@ bool GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
13211327
Type concrete2 = T2->getConcreteType();
13221328

13231329
if (concrete1 && concrete2) {
1324-
bool mismatch =
1325-
addSameTypeRequirement(concrete1, concrete2, Source, nullptr,
1326-
[&](Type type1, Type type2) {
1330+
bool mismatch = addSameTypeRequirement(
1331+
concrete1, concrete2, Source, [&](Type type1, Type type2) {
13271332
Diags.diagnose(Source.getLoc(),
13281333
diag::requires_same_type_conflict,
13291334
T1->getDependentType(/*FIXME: */{ }, true), type1,
@@ -1399,9 +1404,8 @@ bool GenericSignatureBuilder::addSameTypeRequirementToConcrete(
13991404
// If we've already been bound to a type, we're either done, or we have a
14001405
// problem.
14011406
if (auto oldConcrete = T->getConcreteType()) {
1402-
bool mismatch =
1403-
addSameTypeRequirement(oldConcrete, Concrete, Source, nullptr,
1404-
[&](Type type1, Type type2) {
1407+
bool mismatch = addSameTypeRequirement(
1408+
oldConcrete, Concrete, Source, [&](Type type1, Type type2) {
14051409
Diags.diagnose(Source.getLoc(),
14061410
diag::requires_same_type_conflict,
14071411
T->getDependentType(/*FIXME: */{ }, true), type1,
@@ -1474,30 +1478,25 @@ bool GenericSignatureBuilder::addSameTypeRequirementToConcrete(
14741478
}
14751479

14761480
bool GenericSignatureBuilder::addSameTypeRequirement(
1477-
Type type1, Type type2,
1478-
RequirementSource source,
1479-
PotentialArchetype *basePA,
1480-
llvm::function_ref<void(Type, Type)> diagnoseMismatch) {
1481+
Type type1, Type type2, RequirementSource source,
1482+
llvm::function_ref<void(Type, Type)> diagnoseMismatch) {
14811483
// Local class to handle matching the two sides of the same-type constraint.
14821484
class ReqTypeMatcher : public TypeMatcher<ReqTypeMatcher> {
14831485
GenericSignatureBuilder &builder;
14841486
RequirementSource source;
1485-
PotentialArchetype *basePA;
14861487
llvm::function_ref<void(Type, Type)> diagnoseMismatch;
14871488

14881489
public:
1489-
ReqTypeMatcher(GenericSignatureBuilder &builder,
1490-
RequirementSource source,
1491-
PotentialArchetype *basePA,
1490+
ReqTypeMatcher(GenericSignatureBuilder &builder, RequirementSource source,
14921491
llvm::function_ref<void(Type, Type)> diagnoseMismatch)
1493-
: builder(builder), source(source), basePA(basePA),
1494-
diagnoseMismatch(diagnoseMismatch) { }
1492+
: builder(builder), source(source), diagnoseMismatch(diagnoseMismatch) {
1493+
}
14951494

14961495
bool mismatch(TypeBase *firstType, TypeBase *secondType,
14971496
Type sugaredFirstType) {
14981497
// Find the potential archetypes.
1499-
PotentialArchetype *pa1 = builder.resolveArchetype(firstType, basePA);
1500-
PotentialArchetype *pa2 = builder.resolveArchetype(secondType, basePA);
1498+
PotentialArchetype *pa1 = builder.resolveArchetype(firstType);
1499+
PotentialArchetype *pa2 = builder.resolveArchetype(secondType);
15011500

15021501
// If both sides of the requirement are type parameters, equate them.
15031502
if (pa1 && pa2)
@@ -1515,7 +1514,7 @@ bool GenericSignatureBuilder::addSameTypeRequirement(
15151514
diagnoseMismatch(sugaredFirstType, secondType);
15161515
return false;
15171516
}
1518-
} matcher(*this, source, basePA, diagnoseMismatch);
1517+
} matcher(*this, source, diagnoseMismatch);
15191518

15201519
return !matcher.match(type1, type2);
15211520
}
@@ -1685,17 +1684,16 @@ bool GenericSignatureBuilder::addRequirement(const RequirementRepr &Req) {
16851684
bool GenericSignatureBuilder::addRequirement(const Requirement &req,
16861685
RequirementSource source) {
16871686
llvm::SmallPtrSet<ProtocolDecl *, 8> Visited;
1688-
return addRequirement(req, source, nullptr, Visited);
1687+
return addRequirement(req, source, Visited);
16891688
}
16901689

16911690
bool GenericSignatureBuilder::addRequirement(
16921691
const Requirement &req, RequirementSource source,
1693-
PotentialArchetype *basePA,
16941692
llvm::SmallPtrSetImpl<ProtocolDecl *> &Visited) {
16951693
switch (req.getKind()) {
16961694
case RequirementKind::Superclass: {
16971695
// FIXME: Diagnose this.
1698-
PotentialArchetype *pa = resolveArchetype(req.getFirstType(), basePA);
1696+
PotentialArchetype *pa = resolveArchetype(req.getFirstType());
16991697
if (!pa) return false;
17001698

17011699
assert(req.getSecondType()->getClassOrBoundGenericClass());
@@ -1704,15 +1702,15 @@ bool GenericSignatureBuilder::addRequirement(
17041702

17051703
case RequirementKind::Layout: {
17061704
// FIXME: Diagnose this.
1707-
PotentialArchetype *pa = resolveArchetype(req.getFirstType(), basePA);
1705+
PotentialArchetype *pa = resolveArchetype(req.getFirstType());
17081706
if (!pa) return false;
17091707

17101708
return addLayoutRequirement(pa, req.getLayoutConstraint(), source);
17111709
}
17121710

17131711
case RequirementKind::Conformance: {
17141712
// FIXME: Diagnose this.
1715-
PotentialArchetype *pa = resolveArchetype(req.getFirstType(), basePA);
1713+
PotentialArchetype *pa = resolveArchetype(req.getFirstType());
17161714
if (!pa) return false;
17171715

17181716
SmallVector<ProtocolDecl *, 4> conformsTo;
@@ -1732,7 +1730,7 @@ bool GenericSignatureBuilder::addRequirement(
17321730

17331731
case RequirementKind::SameType:
17341732
return addSameTypeRequirement(
1735-
req.getFirstType(), req.getSecondType(), source, basePA,
1733+
req.getFirstType(), req.getSecondType(), source,
17361734
[&](Type type1, Type type2) {
17371735
if (source.getLoc().isValid())
17381736
Diags.diagnose(source.getLoc(),
@@ -1792,25 +1790,21 @@ class GenericSignatureBuilder::InferRequirementsWalker : public TypeWalker {
17921790

17931791
// Handle the requirements.
17941792
RequirementSource source(RequirementSource::Inferred, Loc);
1795-
for (const auto &req : genericSig->getRequirements()) {
1796-
switch (req.getKind()) {
1797-
case RequirementKind::SameType: {
1798-
auto firstType = req.getFirstType().subst(
1799-
getTypeSubstitution,
1800-
Builder.getLookupConformanceFn());
1801-
if (!firstType)
1802-
break;
1793+
for (const auto &rawReq : genericSig->getRequirements()) {
1794+
auto req =
1795+
rawReq.subst(getTypeSubstitution, Builder.getLookupConformanceFn());
1796+
if (!req)
1797+
continue;
18031798

1799+
switch (req->getKind()) {
1800+
case RequirementKind::SameType: {
1801+
auto firstType = req->getFirstType();
18041802
auto firstPA = Builder.resolveArchetype(firstType);
18051803

18061804
if (firstPA && isOuterArchetype(firstPA))
18071805
return Action::Continue;
18081806

1809-
auto secondType = req.getSecondType().subst(
1810-
getTypeSubstitution,
1811-
Builder.getLookupConformanceFn());
1812-
if (!secondType)
1813-
break;
1807+
auto secondType = req->getSecondType();
18141808
auto secondPA = Builder.resolveArchetype(secondType);
18151809

18161810
if (firstPA && secondPA) {
@@ -1831,12 +1825,7 @@ class GenericSignatureBuilder::InferRequirementsWalker : public TypeWalker {
18311825
case RequirementKind::Superclass:
18321826
case RequirementKind::Layout:
18331827
case RequirementKind::Conformance: {
1834-
auto subjectType = req.getFirstType().subst(
1835-
getTypeSubstitution,
1836-
Builder.getLookupConformanceFn());
1837-
if (!subjectType)
1838-
break;
1839-
1828+
auto subjectType = req->getFirstType();
18401829
auto subjectPA = Builder.resolveArchetype(subjectType);
18411830
if (!subjectPA) {
18421831
break;
@@ -1845,22 +1834,29 @@ class GenericSignatureBuilder::InferRequirementsWalker : public TypeWalker {
18451834
if (isOuterArchetype(subjectPA))
18461835
return Action::Continue;
18471836

1848-
if (req.getKind() == RequirementKind::Conformance) {
1849-
auto proto = req.getSecondType()->castTo<ProtocolType>();
1837+
switch (req->getKind()) {
1838+
case RequirementKind::Conformance: {
1839+
auto proto = req->getSecondType()->castTo<ProtocolType>();
18501840
if (Builder.addConformanceRequirement(subjectPA, proto->getDecl(),
18511841
source)) {
18521842
return Action::Stop;
18531843
}
1854-
} else if (req.getKind() == RequirementKind::Layout) {
1855-
if (Builder.addLayoutRequirement(subjectPA, req.getLayoutConstraint(),
1856-
source)) {
1844+
break;
1845+
}
1846+
case RequirementKind::Layout:
1847+
if (Builder.addLayoutRequirement(
1848+
subjectPA, req->getLayoutConstraint(), source)) {
18571849
return Action::Stop;
18581850
}
1859-
} else {
1860-
if (Builder.addSuperclassRequirement(subjectPA, req.getSecondType(),
1851+
break;
1852+
case RequirementKind::Superclass:
1853+
if (Builder.addSuperclassRequirement(subjectPA, req->getSecondType(),
18611854
source)) {
18621855
return Action::Stop;
18631856
}
1857+
break;
1858+
case RequirementKind::SameType:
1859+
llvm_unreachable("covered by outer switch");
18641860
}
18651861
break;
18661862
}

0 commit comments

Comments
 (0)