Skip to content

Commit 863afad

Browse files
authored
Merge pull request swiftlang#75947 from slavapestov/type-subst-rework-2
Type::subst() rework, part 2
2 parents a25f29a + 8e256d9 commit 863afad

37 files changed

+502
-493
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/SubstitutionMap.h

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace swift {
3434

3535
class GenericEnvironment;
3636
class GenericParamList;
37+
class RecursiveTypeProperties;
3738
class SubstitutableType;
3839
typedef CanTypeWrapper<GenericTypeParamType> CanGenericTypeParamType;
3940

@@ -150,19 +151,7 @@ class SubstitutionMap {
150151
/// parameters.
151152
ArrayRef<Type> getInnermostReplacementTypes() const;
152153

153-
/// Query whether any replacement types in the map contain archetypes.
154-
bool hasArchetypes() const;
155-
156-
/// Query whether any replacement types in the map contain an opened
157-
/// existential or opened element.
158-
bool hasLocalArchetypes() const;
159-
160-
/// Query whether any replacement types in the map contain an opaque
161-
/// return type.
162-
bool hasOpaqueArchetypes() const;
163-
164-
/// Query whether any replacement types in the map contain dynamic Self.
165-
bool hasDynamicSelf() const;
154+
RecursiveTypeProperties getRecursiveProperties() const;
166155

167156
/// Whether the replacement types are all canonical.
168157
bool isCanonical() const;

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/AST/TypeTransform.h

Lines changed: 101 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,16 @@ case TypeKind::Id:
112112
case TypeKind::Unresolved:
113113
case TypeKind::TypeVariable:
114114
case TypeKind::Placeholder:
115-
case TypeKind::GenericTypeParam:
116115
case TypeKind::SILToken:
117116
case TypeKind::Module:
118117
case TypeKind::BuiltinTuple:
119118
return t;
120119

120+
case TypeKind::GenericTypeParam: {
121+
auto *param = cast<GenericTypeParamType>(base);
122+
return asDerived().transformGenericTypeParam(param, pos);
123+
}
124+
121125
case TypeKind::Enum:
122126
case TypeKind::Struct:
123127
case TypeKind::Class:
@@ -164,64 +168,50 @@ case TypeKind::Id:
164168
case TypeKind::SILBox: {
165169
bool changed = false;
166170
auto boxTy = cast<SILBoxType>(base);
167-
#ifndef NDEBUG
168-
// This interface isn't suitable for updating the substitution map in a
169-
// generic SILBox.
170-
for (Type type : boxTy->getSubstitutions().getReplacementTypes()) {
171-
assert(type->isEqual(
172-
doIt(type, TypePosition::Invariant)) &&
173-
"SILBoxType substitutions can't be transformed");
174-
}
175-
#endif
171+
176172
SmallVector<SILField, 4> newFields;
177173
auto *l = boxTy->getLayout();
178174
for (auto f : l->getFields()) {
179175
auto fieldTy = f.getLoweredType();
180-
auto transformed = doIt(fieldTy, TypePosition::Invariant)
181-
->getCanonicalType();
176+
auto transformed = asDerived().transformSILField(
177+
fieldTy, TypePosition::Invariant);
182178
changed |= fieldTy != transformed;
183179
newFields.push_back(SILField(transformed, f.isMutable()));
184180
}
181+
182+
auto oldSubMap = boxTy->getSubstitutions();
183+
auto newSubMap = asDerived().transformSubMap(oldSubMap);
184+
if (oldSubMap && !newSubMap)
185+
return Type();
186+
changed |= (oldSubMap != newSubMap);
185187
if (!changed)
186188
return t;
187189
boxTy = SILBoxType::get(ctx,
188190
SILLayout::get(ctx,
189191
l->getGenericSignature(),
190192
newFields,
191193
l->capturesGenericEnvironment()),
192-
boxTy->getSubstitutions());
194+
newSubMap);
193195
return boxTy;
194196
}
195197

196198
case TypeKind::SILFunction: {
197199
auto fnTy = cast<SILFunctionType>(base);
198-
bool changed = false;
199-
auto updateSubs = [&](SubstitutionMap &subs) -> bool {
200-
// This interface isn't suitable for doing most transformations on
201-
// a substituted SILFunctionType, but it's too hard to come up with
202-
// an assertion that meaningfully captures what restrictions are in
203-
// place. Generally the restriction that you can't naively substitute
204-
// a SILFunctionType using AST mechanisms will have to be good enough.
205-
SmallVector<Type, 4> newReplacements;
206-
for (Type type : subs.getReplacementTypes()) {
207-
auto transformed = doIt(type, TypePosition::Invariant);
208-
newReplacements.push_back(transformed->getCanonicalType());
209-
if (!type->isEqual(transformed))
210-
changed = true;
211-
}
212-
213-
if (changed) {
214-
subs = SubstitutionMap::get(subs.getGenericSignature(),
215-
newReplacements,
216-
subs.getConformances());
217-
}
218-
219-
return changed;
220-
};
221200

222201
if (fnTy->isPolymorphic())
223202
return fnTy;
224203

204+
auto updateSubs = [&](SubstitutionMap &subs) -> bool {
205+
auto newSubs = asDerived().transformSubMap(subs);
206+
if (subs && !newSubs)
207+
return false;
208+
if (subs == newSubs)
209+
return false;
210+
211+
subs = newSubs;
212+
return true;
213+
};
214+
225215
if (auto subs = fnTy->getInvocationSubstitutions()) {
226216
if (updateSubs(subs)) {
227217
return fnTy->withInvocationSubstitutions(subs);
@@ -236,6 +226,8 @@ case TypeKind::Id:
236226
return fnTy;
237227
}
238228

229+
bool changed = false;
230+
239231
SmallVector<SILParameterInfo, 8> transInterfaceParams;
240232
for (SILParameterInfo param : fnTy->getParameters()) {
241233
if (transformSILParameter(pos.flipped(), param, changed))
@@ -433,23 +425,28 @@ case TypeKind::Id:
433425
if (!newParentType) return newUnderlyingTy;
434426
}
435427

436-
auto subMap = alias->getSubstitutionMap();
437-
for (Type oldReplacementType : subMap.getReplacementTypes()) {
438-
Type newReplacementType = doIt(oldReplacementType, TypePosition::Invariant);
439-
if (!newReplacementType)
440-
return newUnderlyingTy;
428+
if (newParentType && newParentType->isExistentialType())
429+
return newUnderlyingTy;
441430

442-
// If anything changed with the replacement type, we lose the sugar.
443-
// FIXME: This is really unfortunate.
444-
if (newReplacementType.getPointer() != oldReplacementType.getPointer())
445-
return newUnderlyingTy;
446-
}
431+
auto oldSubMap = alias->getSubstitutionMap();
432+
auto newSubMap = asDerived().transformSubMap(oldSubMap);
433+
if (oldSubMap && !newSubMap)
434+
return Type();
447435

448436
if (oldParentType.getPointer() == newParentType.getPointer() &&
449-
oldUnderlyingTy.getPointer() == newUnderlyingTy.getPointer())
437+
oldUnderlyingTy.getPointer() == newUnderlyingTy.getPointer() &&
438+
oldSubMap == newSubMap)
450439
return t;
451440

452-
return TypeAliasType::get(alias->getDecl(), newParentType, subMap,
441+
// Don't leave local archetypes and type variables behind in sugar
442+
// if they don't appear in the underlying type, to avoid confusion.
443+
auto props = newSubMap.getRecursiveProperties();
444+
if (props.hasLocalArchetype() && !newUnderlyingTy->hasLocalArchetype())
445+
return newUnderlyingTy;
446+
if (props.hasTypeVariable() && !newUnderlyingTy->hasTypeVariable())
447+
return newUnderlyingTy;
448+
449+
return TypeAliasType::get(alias->getDecl(), newParentType, newSubMap,
453450
newUnderlyingTy);
454451
}
455452

@@ -593,43 +590,13 @@ case TypeKind::Id:
593590
}
594591

595592
case TypeKind::PackExpansion: {
596-
auto expand = cast<PackExpansionType>(base);
597-
598-
// Substitution completely replaces this.
599-
600-
Type transformedPat = doIt(expand->getPatternType(), pos);
601-
if (!transformedPat)
602-
return Type();
603-
604-
Type transformedCount = doIt(expand->getCountType(), TypePosition::Shape);
605-
if (!transformedCount)
606-
return Type();
607-
608-
if (transformedPat.getPointer() == expand->getPatternType().getPointer() &&
609-
transformedCount.getPointer() == expand->getCountType().getPointer())
610-
return t;
611-
612-
// // If we transform the count to a pack type, expand the pattern.
613-
// // This is necessary because of how we piece together types in
614-
// // the constraint system.
615-
// if (auto countPack = transformedCount->getAs<PackType>()) {
616-
// return PackExpansionType::expand(transformedPat, countPack);
617-
// }
618-
619-
return PackExpansionType::get(transformedPat, transformedCount);
593+
auto *expand = cast<PackExpansionType>(base);
594+
return asDerived().transformPackExpansion(expand, pos);
620595
}
621596

622597
case TypeKind::PackElement: {
623598
auto element = cast<PackElementType>(base);
624-
625-
Type transformedPack = doIt(element->getPackType(), pos);
626-
if (!transformedPack)
627-
return Type();
628-
629-
if (transformedPack.getPointer() == element->getPackType().getPointer())
630-
return t;
631-
632-
return PackElementType::get(transformedPack, element->getLevel());
599+
return asDerived().transformPackElement(element, pos);
633600
}
634601

635602
case TypeKind::Tuple: {
@@ -695,17 +662,7 @@ case TypeKind::Id:
695662

696663
case TypeKind::DependentMember: {
697664
auto dependent = cast<DependentMemberType>(base);
698-
auto dependentBase = doIt(dependent->getBase(), pos);
699-
if (!dependentBase)
700-
return Type();
701-
702-
if (dependentBase.getPointer() == dependent->getBase().getPointer())
703-
return t;
704-
705-
if (auto assocType = dependent->getAssocType())
706-
return DependentMemberType::get(dependentBase, assocType);
707-
708-
return DependentMemberType::get(dependentBase, dependent->getName());
665+
return asDerived().transformDependentMember(dependent, pos);
709666
}
710667

711668
case TypeKind::GenericFunction:
@@ -1008,8 +965,59 @@ case TypeKind::Id:
1008965
QueryReplacementTypeArray{sig, newSubs},
1009966
LookUpConformanceInModule());
1010967
}
968+
969+
CanType transformSILField(CanType fieldTy, TypePosition pos) {
970+
return doIt(fieldTy, pos)->getCanonicalType();
971+
}
972+
973+
Type transformGenericTypeParam(GenericTypeParamType *param, TypePosition pos) {
974+
return param;
975+
}
976+
977+
Type transformPackExpansion(PackExpansionType *expand, TypePosition pos) {
978+
// Substitution completely replaces this.
979+
980+
Type transformedPat = doIt(expand->getPatternType(), pos);
981+
if (!transformedPat)
982+
return Type();
983+
984+
Type transformedCount = doIt(expand->getCountType(), TypePosition::Shape);
985+
if (!transformedCount)
986+
return Type();
987+
988+
if (transformedPat.getPointer() == expand->getPatternType().getPointer() &&
989+
transformedCount.getPointer() == expand->getCountType().getPointer())
990+
return expand;
991+
992+
return PackExpansionType::get(transformedPat, transformedCount);
993+
}
994+
995+
Type transformPackElement(PackElementType *element, TypePosition pos) {
996+
Type transformedPack = doIt(element->getPackType(), pos);
997+
if (!transformedPack)
998+
return Type();
999+
1000+
if (transformedPack.getPointer() == element->getPackType().getPointer())
1001+
return element;
1002+
1003+
return PackElementType::get(transformedPack, element->getLevel());
1004+
}
1005+
1006+
Type transformDependentMember(DependentMemberType *dependent, TypePosition pos) {
1007+
auto dependentBase = doIt(dependent->getBase(), pos);
1008+
if (!dependentBase)
1009+
return Type();
1010+
1011+
if (dependentBase.getPointer() == dependent->getBase().getPointer())
1012+
return dependent;
1013+
1014+
if (auto assocType = dependent->getAssocType())
1015+
return DependentMemberType::get(dependentBase, assocType);
1016+
1017+
return DependentMemberType::get(dependentBase, dependent->getName());
1018+
}
10111019
};
10121020

10131021
}
10141022

1015-
#endif
1023+
#endif

include/swift/AST/Types.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,11 @@ class RecursiveTypeProperties {
246246
/// they have a type variable originator.
247247
bool isSolverAllocated() const { return Bits & SolverAllocated; }
248248

249+
/// Determine whether the type involves a primary, pack or local archetype.
250+
bool hasArchetype() const {
251+
return hasPrimaryArchetype() || hasLocalArchetype();
252+
}
253+
249254
/// Does a type with these properties structurally contain a local
250255
/// archetype?
251256
bool hasLocalArchetype() const {
@@ -720,10 +725,8 @@ class alignas(1 << TypeAlignInBits) TypeBase
720725
}
721726

722727
/// Determine whether the type involves a primary, pack or local archetype.
723-
///
724-
/// FIXME: Replace all remaining callers with a more precise check.
725728
bool hasArchetype() const {
726-
return hasPrimaryArchetype() || hasLocalArchetype();
729+
return getRecursiveProperties().hasArchetype();
727730
}
728731

729732
/// Determine whether the type involves an opened existential archetype.
@@ -780,10 +783,6 @@ class alignas(1 << TypeAlignInBits) TypeBase
780783
/// Determine whether the type is an opened existential type with Error inside
781784
bool isOpenedExistentialWithError();
782785

783-
/// Retrieve the set of root opened archetypes that occur within this type.
784-
void getRootOpenedExistentials(
785-
SmallVectorImpl<OpenedArchetypeType *> &rootOpenedArchetypes) const;
786-
787786
/// Retrieve the set of type parameter packs that occur within this type.
788787
void getTypeParameterPacks(SmallVectorImpl<Type> &rootParameterPacks);
789788

0 commit comments

Comments
 (0)