Skip to content

Commit 44dbebd

Browse files
authored
Merge pull request swiftlang#76200 from slavapestov/type-subst-invariant
AST: Type substitution can skip subtrees that won't change
2 parents f34bcaa + 593358a commit 44dbebd

14 files changed

+112
-117
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;

include/swift/AST/LocalArchetypeRequirementCollector.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ struct MapLocalArchetypesOutOfContext {
5454
Type operator()(SubstitutableType *type) const;
5555
};
5656

57+
Type mapLocalArchetypesOutOfContext(Type type,
58+
GenericSignature baseGenericSig,
59+
ArrayRef<GenericEnvironment *> capturedEnvs);
60+
5761
struct MapIntoLocalArchetypeContext {
5862
GenericEnvironment *baseGenericEnv;
5963
ArrayRef<GenericEnvironment *> capturedEnvs;

include/swift/AST/Types.h

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6577,10 +6577,6 @@ class ArchetypeType : public SubstitutableType,
65776577
/// which the archetype conforms.
65786578
Type getNestedTypeByName(Identifier name);
65796579

6580-
/// Return the archetype that represents the root generic parameter of its
6581-
/// interface type.
6582-
ArchetypeType *getRoot() const;
6583-
65846580
/// Determine whether this is a root archetype within the environment.
65856581
bool isRoot() const;
65866582

@@ -6761,19 +6757,12 @@ class LocalArchetypeType : public ArchetypeType {
67616757
using ArchetypeType::ArchetypeType;
67626758

67636759
public:
6764-
LocalArchetypeType *getRoot() const {
6765-
return cast<LocalArchetypeType>(ArchetypeType::getRoot());
6766-
}
6767-
67686760
static bool classof(const TypeBase *type) {
67696761
return type->getKind() == TypeKind::OpenedArchetype ||
67706762
type->getKind() == TypeKind::ElementArchetype;
67716763
}
67726764
};
67736765
BEGIN_CAN_TYPE_WRAPPER(LocalArchetypeType, ArchetypeType)
6774-
CanLocalArchetypeType getRoot() const {
6775-
return CanLocalArchetypeType(getPointer()->getRoot());
6776-
}
67776766
END_CAN_TYPE_WRAPPER(LocalArchetypeType, ArchetypeType)
67786767

67796768
/// An archetype that represents the dynamic type of an opened existential.
@@ -6828,12 +6817,6 @@ class OpenedArchetypeType final : public LocalArchetypeType,
68286817
/// Retrieve the ID number of this opened existential.
68296818
UUID getOpenedExistentialID() const;
68306819

6831-
/// Return the archetype that represents the root generic parameter of its
6832-
/// interface type.
6833-
OpenedArchetypeType *getRoot() const {
6834-
return cast<OpenedArchetypeType>(ArchetypeType::getRoot());
6835-
}
6836-
68376820
static bool classof(const TypeBase *T) {
68386821
return T->getKind() == TypeKind::OpenedArchetype;
68396822
}
@@ -6846,9 +6829,6 @@ class OpenedArchetypeType final : public LocalArchetypeType,
68466829
RecursiveTypeProperties properties);
68476830
};
68486831
BEGIN_CAN_TYPE_WRAPPER(OpenedArchetypeType, LocalArchetypeType)
6849-
CanOpenedArchetypeType getRoot() const {
6850-
return CanOpenedArchetypeType(getPointer()->getRoot());
6851-
}
68526832
END_CAN_TYPE_WRAPPER(OpenedArchetypeType, LocalArchetypeType)
68536833

68546834
/// A wrapper around a shape type to use in ArchetypeTrailingObjects
@@ -6916,12 +6896,6 @@ class ElementArchetypeType final : public LocalArchetypeType,
69166896
/// Retrieve the ID number of this opened element.
69176897
UUID getOpenedElementID() const;
69186898

6919-
/// Return the archetype that represents the root generic parameter of its
6920-
/// interface type.
6921-
ElementArchetypeType *getRoot() const {
6922-
return cast<ElementArchetypeType>(ArchetypeType::getRoot());
6923-
}
6924-
69256899
static bool classof(const TypeBase *T) {
69266900
return T->getKind() == TypeKind::ElementArchetype;
69276901
}
@@ -6933,9 +6907,6 @@ class ElementArchetypeType final : public LocalArchetypeType,
69336907
LayoutConstraint layout);
69346908
};
69356909
BEGIN_CAN_TYPE_WRAPPER(ElementArchetypeType, LocalArchetypeType)
6936-
CanElementArchetypeType getRoot() const {
6937-
return CanElementArchetypeType(getPointer()->getRoot());
6938-
}
69396910
END_CAN_TYPE_WRAPPER(ElementArchetypeType, LocalArchetypeType)
69406911

69416912
template<typename Type>

include/swift/SIL/SILCloner.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,8 @@ struct SubstitutionMapWithLocalArchetypes {
6060

6161
// Map the local archetype to an interface type in the new generic
6262
// signature.
63-
MapLocalArchetypesOutOfContext mapOutOfContext(BaseGenericSig,
64-
CapturedEnvs);
65-
auto interfaceTy = mapOutOfContext(local);
63+
auto interfaceTy = mapLocalArchetypesOutOfContext(
64+
local, BaseGenericSig, CapturedEnvs);
6665

6766
// Map this interface type into the new generic environment to get
6867
// a primary archetype.

include/swift/SIL/SILModule.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,18 @@ class SILModule {
460460
SILValue getLocalGenericEnvironmentDef(GenericEnvironment *genericEnv,
461461
SILFunction *inFunction);
462462

463+
/// Returns the instruction which defines the given local generic environment,
464+
/// e.g. an open_existential_addr.
465+
///
466+
/// In contrast to getLocalGenericEnvironmentDef, it is required that all local
467+
/// generic environments are resolved.
468+
SingleValueInstruction *
469+
getLocalGenericEnvironmentDefInst(GenericEnvironment *genericEnv,
470+
SILFunction *inFunction) {
471+
return dyn_cast<SingleValueInstruction>(
472+
getLocalGenericEnvironmentDef(genericEnv, inFunction));
473+
}
474+
463475
/// Returns the instruction which defines the given root local archetype,
464476
/// e.g. an open_existential_addr.
465477
///

lib/AST/ASTMangler.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3796,12 +3796,8 @@ void ASTMangler::appendClosureComponents(CanType Ty, unsigned discriminator,
37963796
appendContext(parentContext, base, StringRef());
37973797

37983798
auto Sig = parentContext->getGenericSignatureOfContext();
3799-
3800-
Ty = Ty.subst(MapLocalArchetypesOutOfContext(Sig, capturedEnvs),
3801-
MakeAbstractConformanceForGenericType(),
3802-
SubstFlags::PreservePackExpansionLevel |
3803-
SubstFlags::SubstitutePrimaryArchetypes |
3804-
SubstFlags::SubstituteLocalArchetypes)->getCanonicalType();
3799+
Ty = mapLocalArchetypesOutOfContext(Ty, Sig, capturedEnvs)
3800+
->getCanonicalType();
38053801

38063802
appendType(Ty, Sig);
38073803
appendOperator(isImplicit ? "fu" : "fU", Index(discriminator));

lib/AST/LocalArchetypeRequirementCollector.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,17 @@ Type MapLocalArchetypesOutOfContext::operator()(SubstitutableType *type) const {
203203
return getInterfaceType(archetypeTy->getInterfaceType(), genericEnv);
204204
}
205205

206+
Type swift::mapLocalArchetypesOutOfContext(
207+
Type type,
208+
GenericSignature baseGenericSig,
209+
ArrayRef<GenericEnvironment *> capturedEnvs) {
210+
return type.subst(MapLocalArchetypesOutOfContext(baseGenericSig, capturedEnvs),
211+
MakeAbstractConformanceForGenericType(),
212+
SubstFlags::PreservePackExpansionLevel |
213+
SubstFlags::SubstitutePrimaryArchetypes |
214+
SubstFlags::SubstituteLocalArchetypes);
215+
}
216+
206217
static Type mapIntoLocalContext(GenericTypeParamType *param, unsigned baseDepth,
207218
ArrayRef<GenericEnvironment *> capturedEnvs) {
208219
assert(!param->isParameterPack());

lib/AST/ParameterPack.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "swift/AST/ASTContext.h"
1919
#include "swift/AST/Decl.h"
20+
#include "swift/AST/GenericEnvironment.h"
2021
#include "swift/AST/GenericParamList.h"
2122
#include "swift/AST/ParameterList.h"
2223
#include "swift/AST/Type.h"
@@ -161,7 +162,14 @@ void TypeBase::getTypeParameterPacks(
161162
if (paramTy->isParameterPack())
162163
rootParameterPacks.push_back(paramTy);
163164
} else if (auto *archetypeTy = t->getAs<PackArchetypeType>()) {
164-
rootParameterPacks.push_back(archetypeTy->getRoot());
165+
if (archetypeTy->isRoot()) {
166+
rootParameterPacks.push_back(archetypeTy);
167+
} else {
168+
auto *genericEnv = archetypeTy->getGenericEnvironment();
169+
auto paramTy = archetypeTy->getInterfaceType()->getRootGenericParam();
170+
rootParameterPacks.push_back(
171+
genericEnv->mapTypeIntoContext(paramTy));
172+
}
165173
}
166174

167175
return false;

lib/AST/Type.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3378,17 +3378,6 @@ ArchetypeType::ArchetypeType(TypeKind Kind,
33783378
getSubclassTrailingObjects<ProtocolDecl *>());
33793379
}
33803380

3381-
ArchetypeType *ArchetypeType::getRoot() const {
3382-
if (isRoot()) {
3383-
return const_cast<ArchetypeType *>(this);
3384-
}
3385-
3386-
auto gp = InterfaceType->getRootGenericParam();
3387-
assert(gp && "Missing root generic parameter?");
3388-
return getGenericEnvironment()->mapTypeIntoContext(
3389-
Type(gp))->castTo<ArchetypeType>();
3390-
}
3391-
33923381
bool ArchetypeType::isRoot() const {
33933382
return getInterfaceType()->is<GenericTypeParamType>();
33943383
}

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)