Skip to content

Commit c906c18

Browse files
committed
AST: More direct implementation of SubstitutionMap::subst()
Instead of using the callback form of SubstitutionMap::get(), let's use the lower-level form that takes the replacement array and conformances array directly, allowing us to bypass several calls of subst() on 'this'.
1 parent e78f16f commit c906c18

File tree

1 file changed

+38
-14
lines changed

1 file changed

+38
-14
lines changed

lib/AST/SubstitutionMap.cpp

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -437,20 +437,44 @@ SubstitutionMap SubstitutionMap::subst(TypeSubstitutionFn subs,
437437
LookupConformanceFn conformances) const {
438438
if (empty()) return SubstitutionMap();
439439

440-
return get(
441-
getGenericSignature(),
442-
[&](SubstitutableType *type) {
443-
return Type(type).subst(*this, SubstFlags::UseErrorType)
444-
.subst(subs, conformances, SubstFlags::UseErrorType);
445-
},
446-
[&](CanType dependentType, Type replacementType,
447-
ProtocolDecl *proto) ->Optional<ProtocolConformanceRef> {
448-
auto conformance =
449-
lookupConformance(dependentType, proto)
450-
.getValueOr(ProtocolConformanceRef::forInvalid());
451-
auto substType = dependentType.subst(*this, SubstFlags::UseErrorType);
452-
return conformance.subst(substType, subs, conformances);
453-
});
440+
SmallVector<Type, 4> newSubs;
441+
for (Type type : getReplacementTypes()) {
442+
if (!type) {
443+
// Non-canonical parameter.
444+
newSubs.push_back(Type());
445+
continue;
446+
}
447+
newSubs.push_back(type.subst(subs, conformances, SubstFlags::UseErrorType));
448+
}
449+
450+
SmallVector<ProtocolConformanceRef, 4> newConformances;
451+
auto oldConformances = getConformances();
452+
453+
auto *genericSig = getGenericSignature();
454+
for (const auto &req : genericSig->getRequirements()) {
455+
if (req.getKind() != RequirementKind::Conformance) continue;
456+
457+
auto conformance = oldConformances[0];
458+
459+
// Fast path for concrete case -- we don't need to compute substType
460+
// at all.
461+
if (conformance.isConcrete()) {
462+
newConformances.push_back(
463+
ProtocolConformanceRef(
464+
conformance.getConcrete()->subst(subs, conformances)));
465+
} else {
466+
auto origType = req.getFirstType();
467+
auto substType = origType.subst(*this, SubstFlags::UseErrorType);
468+
469+
newConformances.push_back(
470+
conformance.subst(substType, subs, conformances));
471+
}
472+
473+
oldConformances = oldConformances.slice(1);
474+
}
475+
476+
assert(oldConformances.empty());
477+
return SubstitutionMap(genericSig, newSubs, newConformances);
454478
}
455479

456480
SubstitutionMap

0 commit comments

Comments
 (0)