Skip to content

Commit 39b4bda

Browse files
committed
AST: Introduce SubstFlags::SubstituteLocalArchetypes
1 parent 68dca61 commit 39b4bda

16 files changed

+185
-67
lines changed

include/swift/AST/InFlightSubstitution.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ class InFlightSubstitution {
138138
return Options.contains(SubstFlags::SubstituteOpaqueArchetypes);
139139
}
140140

141+
bool shouldSubstituteLocalArchetypes() const {
142+
return Options.contains(SubstFlags::SubstituteLocalArchetypes);
143+
}
144+
141145
/// Is the given type invariant to substitution?
142146
bool isInvariant(Type type) const;
143147
};

include/swift/AST/Type.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,20 +117,24 @@ class MakeAbstractConformanceForGenericType {
117117

118118
/// Flags that can be passed when substituting into a type.
119119
enum class SubstFlags {
120-
/// Allow substitutions to recurse into SILFunctionTypes.
121-
/// Normally, SILType::subst() should be used for lowered
122-
/// types, however in special cases where the substitution
123-
/// is just changing between contextual and interface type
124-
/// representations, using Type::subst() is allowed.
120+
/// Allow substitutions to recurse into SILFunctionTypes. Normally,
121+
/// SILType::subst() should be used for lowered types, however in special
122+
/// cases where the substitution is just changing between contextual and
123+
/// interface type representations, using Type::subst() is allowed.
125124
AllowLoweredTypes = 0x01,
126125
/// Map member types to their desugared witness type.
127126
DesugarMemberTypes = 0x02,
128-
/// Substitute types involving opaque type archetypes.
127+
/// Allow opaque archetypes to themselves be the subject of substitution,
128+
/// used when erasing them to their underlying types. otherwise, we
129+
/// recursively substitute their substitutions, instead, preserving the
130+
/// opaque archetype.
129131
SubstituteOpaqueArchetypes = 0x04,
132+
/// Allow local archetypes to themselves be the subject of substitution.
133+
SubstituteLocalArchetypes = 0x08,
130134
/// Don't increase pack expansion level for free pack references.
131135
/// Do not introduce new usages of this flag.
132136
/// FIXME: Remove this.
133-
PreservePackExpansionLevel = 0x08,
137+
PreservePackExpansionLevel = 0x10,
134138
};
135139

136140
/// Options for performing substitutions into a type.

include/swift/SIL/SILCloner.h

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ struct SubstitutionMapWithLocalArchetypes {
5757

5858
return ProtocolConformanceRef(proto);
5959
}
60+
61+
void dump(llvm::raw_ostream &out) const {
62+
if (SubsMap)
63+
SubsMap->dump(out);
64+
for (auto pair : LocalArchetypeSubs) {
65+
out << "---\n";
66+
pair.first->dump(out);
67+
pair.second->dump(out);
68+
}
69+
}
6070
};
6171

6272
/// SILCloner - Abstract SIL visitor which knows how to clone instructions and
@@ -231,8 +241,7 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
231241
for (auto substConf : substSubs.getConformances()) {
232242
if (substConf.isInvalid()) {
233243
llvm::errs() << "Invalid conformance in SIL cloner:\n";
234-
if (Functor.SubsMap)
235-
Functor.SubsMap->dump(llvm::errs());
244+
Functor.dump(llvm::errs());
236245
llvm::errs() << "\nsubstitution map:\n";
237246
Subs.dump(llvm::errs());
238247
llvm::errs() << "\n";
@@ -363,11 +372,10 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
363372
#ifndef NDEBUG
364373
if (substConf.isInvalid()) {
365374
llvm::errs() << "Invalid conformance in SIL cloner:\n";
366-
if (Functor.SubsMap)
367-
Functor.SubsMap->dump(llvm::errs());
375+
Functor.dump(llvm::errs());
368376
llvm::errs() << "\nconformance:\n";
369377
conformance.dump(llvm::errs());
370-
llvm::errs() << "original type:\n";
378+
llvm::errs() << "\noriginal type:\n";
371379
ty.dump(llvm::errs());
372380
abort();
373381
}
@@ -460,8 +468,12 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
460468

461469
SILType remapType(SILType Ty) {
462470
if (Functor.SubsMap || Ty.hasLocalArchetype()) {
471+
SubstOptions options(std::nullopt);
472+
if (!Functor.LocalArchetypeSubs.empty())
473+
options |= SubstFlags::SubstituteLocalArchetypes;
474+
463475
Ty = Ty.subst(Builder.getModule(), Functor, Functor,
464-
CanGenericSignature());
476+
CanGenericSignature(), options);
465477
}
466478

467479
if (asImpl().shouldSubstOpaqueArchetypes()) {
@@ -480,8 +492,13 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
480492
}
481493

482494
CanType remapASTType(CanType ty) {
483-
if (Functor.SubsMap || ty->hasLocalArchetype())
484-
ty = ty.subst(Functor, Functor)->getCanonicalType();
495+
if (Functor.SubsMap || ty->hasLocalArchetype()) {
496+
SubstOptions options(std::nullopt);
497+
if (!Functor.LocalArchetypeSubs.empty())
498+
options |= SubstFlags::SubstituteLocalArchetypes;
499+
500+
ty = ty.subst(Functor, Functor, options)->getCanonicalType();
501+
}
485502

486503
if (asImpl().shouldSubstOpaqueArchetypes()) {
487504
auto context = getBuilder().getTypeExpansionContext();
@@ -500,9 +517,13 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
500517

501518
ProtocolConformanceRef remapConformance(Type Ty, ProtocolConformanceRef C) {
502519
if (Functor.SubsMap || Ty->hasLocalArchetype()) {
503-
C = C.subst(Ty, Functor, Functor);
520+
SubstOptions options(std::nullopt);
521+
if (!Functor.LocalArchetypeSubs.empty())
522+
options |= SubstFlags::SubstituteLocalArchetypes;
523+
524+
C = C.subst(Ty, Functor, Functor, options);
504525
if (asImpl().shouldSubstOpaqueArchetypes())
505-
Ty = Ty.subst(Functor, Functor);
526+
Ty = Ty.subst(Functor, Functor, options);
506527
}
507528

508529
if (asImpl().shouldSubstOpaqueArchetypes()) {
@@ -520,8 +541,13 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
520541

521542
SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) {
522543
// If we have local archetypes to substitute, do so now.
523-
if (Subs.getRecursiveProperties().hasLocalArchetype() || Functor.SubsMap)
524-
Subs = Subs.subst(Functor, Functor);
544+
if (Subs.getRecursiveProperties().hasLocalArchetype() || Functor.SubsMap) {
545+
SubstOptions options(std::nullopt);
546+
if (!Functor.LocalArchetypeSubs.empty())
547+
options |= SubstFlags::SubstituteLocalArchetypes;
548+
549+
Subs = Subs.subst(Functor, Functor, options);
550+
}
525551

526552
if (asImpl().shouldSubstOpaqueArchetypes()) {
527553
auto context = getBuilder().getTypeExpansionContext();

lib/AST/ASTMangler.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3800,7 +3800,8 @@ void ASTMangler::appendClosureComponents(CanType Ty, unsigned discriminator,
38003800

38013801
Ty = Ty.subst(MapLocalArchetypesOutOfContext(Sig, capturedEnvs),
38023802
MakeAbstractConformanceForGenericType(),
3803-
SubstFlags::PreservePackExpansionLevel)->getCanonicalType();
3803+
SubstFlags::PreservePackExpansionLevel |
3804+
SubstFlags::SubstituteLocalArchetypes)->getCanonicalType();
38043805

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

lib/AST/GenericEnvironment.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,8 @@ GenericEnvironment::mapElementTypeIntoPackContext(Type type) const {
717717
},
718718
MakeAbstractConformanceForGenericType(),
719719
SubstFlags::AllowLoweredTypes |
720-
SubstFlags::PreservePackExpansionLevel);
720+
SubstFlags::PreservePackExpansionLevel |
721+
SubstFlags::SubstituteLocalArchetypes);
721722

722723
auto shapeClass = elementEnv->getOpenedElementShapeClass();
723724

lib/AST/TypeSubstitution.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -472,10 +472,13 @@ InFlightSubstitution::lookupConformance(CanType dependentType,
472472
}
473473

474474
bool InFlightSubstitution::isInvariant(Type derivedType) const {
475-
return !derivedType->hasArchetype()
476-
&& !derivedType->hasTypeParameter()
477-
&& (!shouldSubstituteOpaqueArchetypes()
478-
|| !derivedType->hasOpaqueArchetype());
475+
if (derivedType->hasPrimaryArchetype() || derivedType->hasTypeParameter())
476+
return false;
477+
if (shouldSubstituteLocalArchetypes() && derivedType->hasLocalArchetype())
478+
return false;
479+
if (shouldSubstituteOpaqueArchetypes() && derivedType->hasOpaqueArchetype())
480+
return false;
481+
return true;
479482
}
480483

481484
namespace {
@@ -524,6 +527,12 @@ TypeSubstituter::transform(TypeBase *type, TypePosition position) {
524527
&& isa<OpaqueTypeArchetypeType>(substOrig))
525528
return std::nullopt;
526529

530+
// Local types can't normally be directly substituted unless we
531+
// specifically were asked to substitute them.
532+
if (!IFS.shouldSubstituteLocalArchetypes()
533+
&& isa<LocalArchetypeType>(substOrig))
534+
return std::nullopt;
535+
527536
// If we have a substitution for this type, use it.
528537
if (auto known = IFS.substType(substOrig, level)) {
529538
if (IFS.shouldSubstituteOpaqueArchetypes() &&

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1969,7 +1969,8 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
19691969

19701970
t = t.subst(MapLocalArchetypesOutOfContext(origGenericSig, capturedEnvs),
19711971
MakeAbstractConformanceForGenericType(),
1972-
SubstFlags::PreservePackExpansionLevel);
1972+
SubstFlags::PreservePackExpansionLevel |
1973+
SubstFlags::SubstituteLocalArchetypes);
19731974

19741975
LLVM_DEBUG(llvm::dbgs() << "-- maps to " << t->getCanonicalType() << "\n");
19751976
return t->getCanonicalType();
@@ -2958,7 +2959,8 @@ buildThunkSignature(SILFunction *fn,
29582959
auto thunkInterfaceType = Type(localArchetype).subst(
29592960
mapOutOfContext,
29602961
MakeAbstractConformanceForGenericType(),
2961-
SubstFlags::PreservePackExpansionLevel);
2962+
SubstFlags::PreservePackExpansionLevel |
2963+
SubstFlags::SubstituteLocalArchetypes);
29622964
auto thunkArchetype = genericEnv->mapTypeIntoContext(
29632965
thunkInterfaceType);
29642966
contextLocalArchetypes.insert(std::make_pair(localArchetype,
@@ -3026,25 +3028,27 @@ CanSILFunctionType swift::buildSILFunctionThunkType(
30263028
// Does the thunk type involve a local archetype type?
30273029
SmallVector<CanLocalArchetypeType, 8> localArchetypes;
30283030
auto archetypeVisitor = [&](CanType t) {
3029-
if (auto archetypeTy = dyn_cast<ArchetypeType>(t)) {
3030-
if (auto local = dyn_cast<LocalArchetypeType>(archetypeTy)) {
3031-
auto root = local.getRoot();
3032-
if (llvm::find(localArchetypes, root) == localArchetypes.end())
3033-
localArchetypes.push_back(root);
3034-
}
3031+
if (auto local = dyn_cast<LocalArchetypeType>(t)) {
3032+
auto root = local.getRoot();
3033+
if (llvm::find(localArchetypes, root) == localArchetypes.end())
3034+
localArchetypes.push_back(root);
30353035
}
30363036
};
30373037

3038+
if (expectedType->hasLocalArchetype())
3039+
expectedType.visit(archetypeVisitor);
3040+
if (sourceType->hasLocalArchetype())
3041+
sourceType.visit(archetypeVisitor);
3042+
30383043
// Use the generic signature from the context if the thunk involves
30393044
// generic parameters.
30403045
CanGenericSignature genericSig;
30413046
SubstitutionMap contextSubs;
30423047
llvm::DenseMap<ArchetypeType*, Type> contextLocalArchetypes;
30433048

3044-
if (expectedType->hasArchetype() || sourceType->hasArchetype()) {
3045-
expectedType.visit(archetypeVisitor);
3046-
sourceType.visit(archetypeVisitor);
3047-
3049+
if (!localArchetypes.empty() ||
3050+
expectedType->hasPrimaryArchetype() ||
3051+
sourceType->hasPrimaryArchetype()) {
30483052
genericSig = buildThunkSignature(fn,
30493053
localArchetypes,
30503054
genericEnv,
@@ -3079,13 +3083,16 @@ CanSILFunctionType swift::buildSILFunctionThunkType(
30793083
// opened existential with the new archetype.
30803084
auto substFormalTypeIntoThunkContext =
30813085
[&](CanType t) -> CanType {
3082-
return t.subst(substTypeHelper, substConformanceHelper)
3086+
return t.subst(substTypeHelper, substConformanceHelper,
3087+
SubstFlags::SubstituteLocalArchetypes)
30833088
->getCanonicalType();
30843089
};
30853090
auto substLoweredTypeIntoThunkContext =
30863091
[&](CanSILFunctionType t) -> CanSILFunctionType {
30873092
return SILType::getPrimitiveObjectType(t)
3088-
.subst(fn->getModule(), substTypeHelper, substConformanceHelper)
3093+
.subst(fn->getModule(), substTypeHelper, substConformanceHelper,
3094+
CanGenericSignature(),
3095+
SubstFlags::SubstituteLocalArchetypes)
30893096
.castTo<SILFunctionType>();
30903097
};
30913098

lib/SIL/IR/TypeLowering.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3909,7 +3909,8 @@ getAnyFunctionRefInterfaceType(TypeConverter &TC,
39093909
auto substType = Type(funcType).subst(
39103910
MapLocalArchetypesOutOfContext(sig.baseGenericSig, sig.capturedEnvs),
39113911
MakeAbstractConformanceForGenericType(),
3912-
SubstFlags::PreservePackExpansionLevel);
3912+
SubstFlags::PreservePackExpansionLevel |
3913+
SubstFlags::SubstituteLocalArchetypes);
39133914
funcType = cast<FunctionType>(substType->getCanonicalType());
39143915
}
39153916

@@ -4991,7 +4992,8 @@ TypeConverter::getInterfaceBoxTypeForCapture(ValueDecl *captured,
49914992
mapOutOfContext,
49924993
MakeAbstractConformanceForGenericType(),
49934994
SubstFlags::PreservePackExpansionLevel |
4994-
SubstFlags::AllowLoweredTypes)->getCanonicalType();
4995+
SubstFlags::AllowLoweredTypes |
4996+
SubstFlags::SubstituteLocalArchetypes)->getCanonicalType();
49954997

49964998
// If the type is not dependent at all, we can form a concrete box layout.
49974999
// We don't need to capture the generic environment.

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6310,7 +6310,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
63106310
substTypes,
63116311
LookUpConformanceInModule(),
63126312
CanGenericSignature(),
6313-
SubstFlags::PreservePackExpansionLevel);
6313+
SubstFlags::PreservePackExpansionLevel |
6314+
SubstFlags::SubstituteLocalArchetypes);
63146315
requireSameType(indexedElementSILType, substTargetElementSILType,
63156316
"lanewise-substituted pack element type didn't "
63166317
"match expected element type");

lib/SILGen/ResultPlan.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ mapTypeOutOfOpenedExistentialContext(CanType t) {
145145

146146
return params[index];
147147
},
148-
MakeAbstractConformanceForGenericType());
148+
MakeAbstractConformanceForGenericType(),
149+
SubstFlags::SubstituteLocalArchetypes);
149150

150151
return std::make_pair(mappedTy->getCanonicalType(), mappedSubs);
151152
}

0 commit comments

Comments
 (0)