Skip to content

Commit 593358a

Browse files
committed
AST: Type substitution can skip subtrees that won't change
1 parent e79763b commit 593358a

File tree

2 files changed

+39
-14
lines changed

2 files changed

+39
-14
lines changed

include/swift/AST/InFlightSubstitution.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class InFlightSubstitution {
3131
SubstOptions Options;
3232
TypeSubstitutionFn BaselineSubstType;
3333
LookupConformanceFn BaselineLookupConformance;
34+
RecursiveTypeProperties Props;
3435

3536
struct ActivePackExpansion {
3637
bool isSubstExpansion = false;
@@ -41,10 +42,7 @@ class InFlightSubstitution {
4142
public:
4243
InFlightSubstitution(TypeSubstitutionFn substType,
4344
LookupConformanceFn lookupConformance,
44-
SubstOptions options)
45-
: Options(options),
46-
BaselineSubstType(substType),
47-
BaselineLookupConformance(lookupConformance) {}
45+
SubstOptions options);
4846

4947
InFlightSubstitution(const InFlightSubstitution &) = delete;
5048
InFlightSubstitution &operator=(const InFlightSubstitution &) = delete;

lib/AST/TypeSubstitution.cpp

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,40 @@ static Type substGenericFunctionType(GenericFunctionType *genericFnType,
359359
fnType->getResult(), fnType->getExtInfo());
360360
}
361361

362+
InFlightSubstitution::InFlightSubstitution(TypeSubstitutionFn substType,
363+
LookupConformanceFn lookupConformance,
364+
SubstOptions options)
365+
: Options(options),
366+
BaselineSubstType(substType),
367+
BaselineLookupConformance(lookupConformance) {
368+
// FIXME: Don't substitute type parameters if one of the special flags is set.
369+
Props |= RecursiveTypeProperties::HasTypeParameter;
370+
371+
// If none of the special flags are set, we substitute type parameters and
372+
// primary archetypes only.
373+
if (!Options.contains(SubstFlags::SubstitutePrimaryArchetypes) &&
374+
!Options.contains(SubstFlags::SubstituteLocalArchetypes) &&
375+
!Options.contains(SubstFlags::SubstituteOpaqueArchetypes)) {
376+
Props |= RecursiveTypeProperties::HasPrimaryArchetype;
377+
}
378+
379+
if (Options.contains(SubstFlags::SubstitutePrimaryArchetypes))
380+
Props |= RecursiveTypeProperties::HasPrimaryArchetype;
381+
382+
if (Options.contains(SubstFlags::SubstituteLocalArchetypes)) {
383+
Props |= RecursiveTypeProperties::HasOpenedExistential;
384+
Props |= RecursiveTypeProperties::HasElementArchetype;
385+
}
386+
387+
if (Options.contains(SubstFlags::SubstituteOpaqueArchetypes))
388+
Props |= RecursiveTypeProperties::HasOpaqueArchetype;
389+
}
390+
391+
bool InFlightSubstitution::isInvariant(Type derivedType) const {
392+
// If none of the bits are set, the type won't be changed by substitution.
393+
return !(derivedType->getRecursiveProperties().getBits() & Props.getBits());
394+
}
395+
362396
void InFlightSubstitution::expandPackExpansionShape(Type origShape,
363397
llvm::function_ref<void(Type substComponentShape)> handleComponent) {
364398

@@ -470,16 +504,6 @@ InFlightSubstitution::lookupConformance(CanType dependentType,
470504
return substPackPatterns[index];
471505
}
472506

473-
bool InFlightSubstitution::isInvariant(Type derivedType) const {
474-
if (derivedType->hasPrimaryArchetype() || derivedType->hasTypeParameter())
475-
return false;
476-
if (shouldSubstituteLocalArchetypes() && derivedType->hasLocalArchetype())
477-
return false;
478-
if (shouldSubstituteOpaqueArchetypes() && derivedType->hasOpaqueArchetype())
479-
return false;
480-
return true;
481-
}
482-
483507
namespace {
484508

485509
class TypeSubstituter : public TypeTransform<TypeSubstituter> {
@@ -522,6 +546,9 @@ class TypeSubstituter : public TypeTransform<TypeSubstituter> {
522546

523547
std::optional<Type>
524548
TypeSubstituter::transform(TypeBase *type, TypePosition position) {
549+
if (IFS.isInvariant(type))
550+
return Type(type);
551+
525552
return std::nullopt;
526553
}
527554

0 commit comments

Comments
 (0)