Skip to content

Commit cf4043b

Browse files
committed
AST: Get rid of old form of Type::subst()
First, add some new utility methods to create SubstitutionMaps: - GenericSignature::getSubstitutionMap() -- provides a new way to directly build a SubstitutionMap. It takes a TypeSubstitutionFn and LookupConformanceFn. This is equivalent to first calling getSubstitutions() with the two functions to create an ArrayRef<Substitution>, followed by the old form of getSubstitutionMap() on the result. - TypeBase::getContextSubstitutionMap() -- replacement for getContextSubstitutions(), returning a SubstitutionMap. - TypeBase::getMemberSubstitutionMap() -- replacement for getMemberSubstitutions(), returning a SubstitutionMap. With these in place, almost all existing uses of subst() taking a ModuleDecl can now use the new form taking a SubstitutionMap instead. The few remaining cases are explicitly written to use a TypeSubstitutionFn and LookupConformanceFn.
1 parent 5a9f674 commit cf4043b

18 files changed

+181
-100
lines changed

include/swift/AST/GenericSignature.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,12 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
141141
void getSubstitutionMap(ArrayRef<Substitution> args,
142142
SubstitutionMap &subMap) const;
143143

144+
/// Build an interface type substitution map from a type substitution function
145+
/// and conformance lookup function.
146+
SubstitutionMap
147+
getSubstitutionMap(TypeSubstitutionFn subs,
148+
LookupConformanceFn lookupConformance) const;
149+
144150
using GenericFunction = auto(CanType canType, Type conformingReplacementType,
145151
ProtocolType *conformedProtocol)
146152
->Optional<ProtocolConformanceRef>;

include/swift/AST/Type.h

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -249,21 +249,6 @@ class Type {
249249
});
250250
}
251251

252-
/// Replace references to substitutable types with new, concrete types and
253-
/// return the substituted result.
254-
///
255-
/// \param module The module to use for conformance lookups.
256-
///
257-
/// \param substitutions The mapping from substitutable types to their
258-
/// replacements.
259-
///
260-
/// \param options Options that affect the substitutions.
261-
///
262-
/// \returns the substituted type, or a null type if an error occurred.
263-
Type subst(ModuleDecl *module,
264-
const TypeSubstitutionMap &substitutions,
265-
SubstOptions options = None) const;
266-
267252
/// Replace references to substitutable types with new, concrete types and
268253
/// return the substituted result.
269254
///

include/swift/AST/Types.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -873,13 +873,21 @@ class alignas(1 << TypeAlignInBits) TypeBase {
873873
/// the context of the extension above will produce substitutions T
874874
/// -> Int and U -> String suitable for mapping the type of
875875
/// \c SomeArray.
876+
SubstitutionMap getContextSubstitutionMap(ModuleDecl *module,
877+
const DeclContext *dc);
878+
879+
/// Deprecated version of the above.
876880
TypeSubstitutionMap getContextSubstitutions(const DeclContext *dc);
877881

878882
/// Get the substitutions to apply to the type of the given member as seen
879883
/// from this base type.
880884
///
881885
/// If the member has its own generic parameters, they will remain unchanged
882886
/// by the substitution.
887+
SubstitutionMap getMemberSubstitutionMap(ModuleDecl *module,
888+
const ValueDecl *member);
889+
890+
/// Deprecated version of the above.
883891
TypeSubstitutionMap getMemberSubstitutions(const ValueDecl *member);
884892

885893
/// Retrieve the type of the given member as seen through the given base

lib/AST/ASTPrinter.cpp

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -224,19 +224,18 @@ struct SynthesizedExtensionAnalyzer::Implementation {
224224
// Get the substitutions from the generic signature of
225225
// the extension to the interface types of the base type's
226226
// declaration.
227-
TypeSubstitutionMap subMap;
228-
if (!BaseType->isExistentialType())
229-
subMap = BaseType->getContextSubstitutions(Ext);
230227
auto *M = DC->getParentModule();
228+
SubstitutionMap subMap;
229+
if (!BaseType->isExistentialType())
230+
subMap = BaseType->getContextSubstitutionMap(M, Ext);
231231

232232
assert(Ext->getGenericSignature() && "No generic signature.");
233233
for (auto Req : Ext->getGenericSignature()->getRequirements()) {
234234
auto Kind = Req.getKind();
235235

236-
Type First = Req.getFirstType().subst(
237-
M, subMap, SubstOptions());
238-
Type Second = Req.getSecondType().subst(
239-
M, subMap, SubstOptions());
236+
Type First = Req.getFirstType().subst(subMap);
237+
Type Second = Req.getSecondType().subst(subMap);
238+
240239
if (!First || !Second) {
241240
// Substitution with interface type bases can only fail
242241
// if a concrete type fails to conform to a protocol.
@@ -874,9 +873,9 @@ class PrintAST : public ASTVisitor<PrintAST> {
874873
assert(DC->isTypeContext());
875874

876875
// Get the substitutions from our base type.
877-
auto subMap = CurrentType->getContextSubstitutions(DC);
878876
auto *M = DC->getParentModule();
879-
T = T.subst(M, subMap, SubstFlags::DesugarMemberTypes);
877+
auto subMap = CurrentType->getContextSubstitutionMap(M, DC);
878+
T = T.subst(subMap, SubstFlags::DesugarMemberTypes);
880879
}
881880

882881
printType(T);
@@ -995,9 +994,9 @@ class PrintAST : public ASTVisitor<PrintAST> {
995994
Type OldType = CurrentType;
996995
if (CurrentType && (Old != nullptr || Options.PrintAsMember)) {
997996
if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
998-
CurrentType = NTD->getDeclaredInterfaceType().subst(
999-
Options.CurrentModule,
1000-
CurrentType->getContextSubstitutions(NTD->getDeclContext()));
997+
auto Subs = CurrentType->getContextSubstitutionMap(
998+
Options.CurrentModule, NTD->getDeclContext());
999+
CurrentType = NTD->getDeclaredInterfaceType().subst(Subs);
10011000
}
10021001
}
10031002

@@ -1268,17 +1267,19 @@ void PrintAST::printSingleDepthOfGenericSignature(
12681267
bool printParams = (flags & PrintParams);
12691268
bool printRequirements = (flags & PrintRequirements);
12701269

1271-
TypeSubstitutionMap subMap;
1272-
ModuleDecl *M = nullptr;
1273-
1270+
SubstitutionMap subMap;
12741271
if (CurrentType) {
12751272
if (!CurrentType->isExistentialType()) {
12761273
auto *DC = Current->getInnermostDeclContext()->getInnermostTypeContext();
1277-
subMap = CurrentType->getContextSubstitutions(DC);
1278-
M = DC->getParentModule();
1274+
auto *M = DC->getParentModule();
1275+
subMap = CurrentType->getContextSubstitutionMap(M, DC);
12791276
}
12801277
}
12811278

1279+
auto substParam = [&](Type param) -> Type {
1280+
return param.subst(subMap);
1281+
};
1282+
12821283
if (printParams) {
12831284
// Print the generic parameters.
12841285
Printer << "<";
@@ -1290,7 +1291,7 @@ void PrintAST::printSingleDepthOfGenericSignature(
12901291
Printer << ", ";
12911292

12921293
if (!subMap.empty()) {
1293-
if (auto argTy = Type(param).subst(M, subMap))
1294+
if (auto argTy = substParam(param))
12941295
printType(argTy);
12951296
else
12961297
printType(param);
@@ -1322,10 +1323,10 @@ void PrintAST::printSingleDepthOfGenericSignature(
13221323
}
13231324

13241325
if (!subMap.empty()) {
1325-
if (Type subFirst = first.subst(M, subMap))
1326+
if (Type subFirst = substParam(first))
13261327
first = subFirst;
13271328
if (second) {
1328-
if (Type subSecond = second.subst(M, subMap))
1329+
if (Type subSecond = substParam(second))
13291330
second = subSecond;
13301331
if (!(first->is<ArchetypeType>() || first->isTypeParameter()) &&
13311332
!(second->is<ArchetypeType>() || second->isTypeParameter()))

lib/AST/GenericSignature.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,62 @@ GenericSignature::getSubstitutionMap(ArrayRef<Substitution> subs,
347347
assert(subs.empty() && "did not use all substitutions?!");
348348
}
349349

350+
SubstitutionMap
351+
GenericSignature::
352+
getSubstitutionMap(TypeSubstitutionFn subs,
353+
GenericSignature::LookupConformanceFn lookupConformance) const {
354+
SubstitutionMap subMap;
355+
356+
// Enumerate all of the requirements that require substitution.
357+
enumeratePairedRequirements([&](Type depTy, ArrayRef<Requirement> reqs) {
358+
auto canTy = depTy->getCanonicalType();
359+
360+
// Compute the replacement type.
361+
Type currentReplacement = depTy.subst(subs, lookupConformance,
362+
SubstFlags::UseErrorType);
363+
if (auto substTy = dyn_cast<SubstitutableType>(canTy))
364+
subMap.addSubstitution(substTy, currentReplacement);
365+
366+
// Collect the conformances.
367+
for (auto req: reqs) {
368+
assert(req.getKind() == RequirementKind::Conformance);
369+
auto protoType = req.getSecondType()->castTo<ProtocolType>();
370+
if (auto conformance = lookupConformance(canTy,
371+
currentReplacement,
372+
protoType)) {
373+
subMap.addConformance(canTy, *conformance);
374+
}
375+
}
376+
377+
return false;
378+
});
379+
380+
for (auto reqt : getRequirements()) {
381+
if (reqt.getKind() != RequirementKind::SameType)
382+
continue;
383+
384+
auto first = reqt.getFirstType();
385+
auto second = reqt.getSecondType();
386+
387+
if (!first->isTypeParameter() || !second->isTypeParameter())
388+
continue;
389+
390+
if (auto *firstMemTy = first->getAs<DependentMemberType>()) {
391+
subMap.addParent(second->getCanonicalType(),
392+
firstMemTy->getBase()->getCanonicalType(),
393+
firstMemTy->getAssocType());
394+
}
395+
396+
if (auto *secondMemTy = second->getAs<DependentMemberType>()) {
397+
subMap.addParent(first->getCanonicalType(),
398+
secondMemTy->getBase()->getCanonicalType(),
399+
secondMemTy->getAssocType());
400+
}
401+
}
402+
403+
return subMap;
404+
}
405+
350406
SmallVector<Type, 4> GenericSignature::getAllDependentTypes() const {
351407
SmallVector<Type, 4> result;
352408
enumeratePairedRequirements([&](Type type, ArrayRef<Requirement>) {

lib/AST/LookupVisibleDecls.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -732,8 +732,8 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer {
732732

733733
auto FoundSignature = VD->getOverloadSignature();
734734
if (FoundSignature.InterfaceType && shouldSubst) {
735-
auto subs = BaseTy->getMemberSubstitutions(VD);
736-
if (auto CT = FoundSignature.InterfaceType.subst(M, subs, None))
735+
auto subs = BaseTy->getMemberSubstitutionMap(M, VD);
736+
if (auto CT = FoundSignature.InterfaceType.subst(subs))
737737
FoundSignature.InterfaceType = CT->getCanonicalType();
738738
}
739739

@@ -748,8 +748,8 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer {
748748

749749
auto OtherSignature = OtherVD->getOverloadSignature();
750750
if (OtherSignature.InterfaceType && shouldSubst) {
751-
auto subs = BaseTy->getMemberSubstitutions(OtherVD);
752-
if (auto CT = OtherSignature.InterfaceType.subst(M, subs, None))
751+
auto subs = BaseTy->getMemberSubstitutionMap(M, OtherVD);
752+
if (auto CT = OtherSignature.InterfaceType.subst(subs))
753753
OtherSignature.InterfaceType = CT->getCanonicalType();
754754
}
755755

lib/AST/SubstitutionMap.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,12 @@ Optional<T> SubstitutionMap::forEachConformance(
9393
return found;
9494
}
9595
} else {
96-
auto sub = conformance.getConcrete()->getTypeWitnessSubstAndDecl(
96+
auto sub = conformance.getConcrete()->getTypeWitnessSubstAndDecl(
9797
protoAssocType, nullptr).first;
98-
for (auto subConformance : sub.getConformances()) {
99-
if (auto found = fn(subConformance))
100-
return found;
101-
}
98+
for (auto subConformance : sub.getConformances()) {
99+
if (auto found = fn(subConformance))
100+
return found;
101+
}
102102
}
103103
}
104104

@@ -233,8 +233,7 @@ SubstitutionMap::getOverrideSubstitutions(const ClassDecl *baseClass,
233233
auto baseClassTy = derivedClassTy->getSuperclassForDecl(baseClass, resolver);
234234

235235
auto *M = baseClass->getParentModule();
236-
auto subs = baseClassTy->gatherAllSubstitutions(M, resolver);
237-
genericSig->getSubstitutionMap(subs, subMap);
236+
subMap = baseClassTy->getContextSubstitutionMap(M, baseClass);
238237

239238
minDepth = genericSig->getGenericParams().back()->getDepth() + 1;
240239
}

lib/AST/Type.cpp

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3087,15 +3087,6 @@ static Type substType(Type derivedType,
30873087
});
30883088
}
30893089

3090-
Type Type::subst(ModuleDecl *module,
3091-
const TypeSubstitutionMap &substitutions,
3092-
SubstOptions options) const {
3093-
return substType(*this,
3094-
QueryTypeSubstitutionMap{substitutions},
3095-
LookUpConformanceInModule(module),
3096-
options);
3097-
}
3098-
30993090
Type Type::subst(const SubstitutionMap &substitutions,
31003091
SubstOptions options) const {
31013092
return substType(*this,
@@ -3215,6 +3206,16 @@ TypeSubstitutionMap TypeBase::getContextSubstitutions(const DeclContext *dc) {
32153206
return substitutions;
32163207
}
32173208

3209+
SubstitutionMap TypeBase::getContextSubstitutionMap(
3210+
ModuleDecl *module, const DeclContext *dc) {
3211+
auto *genericSig = dc->getGenericSignatureOfContext();
3212+
if (genericSig == nullptr)
3213+
return SubstitutionMap();
3214+
return genericSig->getSubstitutionMap(
3215+
QueryTypeSubstitutionMap{getContextSubstitutions(dc)},
3216+
LookUpConformanceInModule(module));
3217+
}
3218+
32183219
TypeSubstitutionMap TypeBase::getMemberSubstitutions(const ValueDecl *member) {
32193220
auto *memberDC = member->getDeclContext();
32203221

@@ -3243,6 +3244,17 @@ TypeSubstitutionMap TypeBase::getMemberSubstitutions(const ValueDecl *member) {
32433244
return substitutions;
32443245
}
32453246

3247+
SubstitutionMap TypeBase::getMemberSubstitutionMap(
3248+
ModuleDecl *module, const ValueDecl *member) {
3249+
auto *genericSig = member->getInnermostDeclContext()
3250+
->getGenericSignatureOfContext();
3251+
if (genericSig == nullptr)
3252+
return SubstitutionMap();
3253+
return genericSig->getSubstitutionMap(
3254+
QueryTypeSubstitutionMap{getMemberSubstitutions(member)},
3255+
LookUpConformanceInModule(module));
3256+
}
3257+
32463258
Type TypeBase::getTypeOfMember(ModuleDecl *module, const ValueDecl *member,
32473259
Type memberType) {
32483260
// If no member type was provided, use the member's type.
@@ -3251,8 +3263,8 @@ Type TypeBase::getTypeOfMember(ModuleDecl *module, const ValueDecl *member,
32513263

32523264
assert(memberType);
32533265

3254-
auto substitutions = getMemberSubstitutions(member);
3255-
return memberType.subst(module, substitutions, SubstFlags::UseErrorType);
3266+
auto substitutions = getMemberSubstitutionMap(module, member);
3267+
return memberType.subst(substitutions, SubstFlags::UseErrorType);
32563268
}
32573269

32583270
Type TypeBase::adjustSuperclassMemberDeclType(const ValueDecl *baseDecl,

lib/ClangImporter/ImportType.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1861,11 +1861,11 @@ Type ClangImporter::Implementation::importMethodType(
18611861
// Get the substitutions that we need to access a member of
18621862
// 'origDC' on 'dc'.
18631863
auto subs = dc->getDeclaredTypeInContext()
1864-
->getContextSubstitutions(origDC);
1864+
->getContextSubstitutionMap(dc->getParentModule(), origDC);
18651865

18661866
// Apply them to the interface type to produce the final
18671867
// substituted type.
1868-
type = type.subst(dc->getParentModule(), subs);
1868+
type = type.subst(subs);
18691869
}
18701870
return type;
18711871
};
@@ -2170,11 +2170,11 @@ Type ClangImporter::Implementation::importAccessorMethodType(
21702170
// Get the substitutions that we need to access a member of
21712171
// 'origDC' on 'dc'.
21722172
auto subs = dc->getDeclaredTypeInContext()
2173-
->getContextSubstitutions(origDC);
2173+
->getContextSubstitutionMap(dc->getParentModule(), origDC);
21742174

21752175
// Apply them to the interface type to produce the final
21762176
// substituted type.
2177-
type = type.subst(dc->getParentModule(), subs);
2177+
type = type.subst(subs);
21782178
}
21792179
return type;
21802180
};

lib/IDE/CodeCompletion.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2003,12 +2003,13 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
20032003
return T;
20042004

20052005
// For everything else, substitute in the base type.
2006-
auto Subs = MaybeNominalType->getMemberSubstitutions(VD);
2006+
auto Subs = MaybeNominalType->getMemberSubstitutionMap(M, VD);
20072007

20082008
// Pass in DesugarMemberTypes so that we see the actual
20092009
// concrete type witnesses instead of type alias types.
2010-
T = T.subst(M, Subs, (SubstFlags::DesugarMemberTypes |
2011-
SubstFlags::UseErrorType));
2010+
T = T.subst(Subs,
2011+
(SubstFlags::DesugarMemberTypes |
2012+
SubstFlags::UseErrorType));
20122013
}
20132014
}
20142015

0 commit comments

Comments
 (0)