Skip to content

Commit 6764072

Browse files
committed
SILCloner: Map opened types using Type::subst instead of transform.
transform doesn't handle conformances properly, so it blows up on SILBoxTypes (and would eventually blow up on BoundGenericTypes if we ever model their arguments properly as substitution lists). Fixes rdar://problem/31941811.
1 parent e2fdea9 commit 6764072

File tree

3 files changed

+37
-21
lines changed

3 files changed

+37
-21
lines changed

include/swift/AST/Type.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ struct QueryTypeSubstitutionMap {
7272
Type operator()(SubstitutableType *type) const;
7373
};
7474

75+
/// A function object suitable for use as a \c TypeSubstitutionFn that
76+
/// queries an underlying \c TypeSubstitutionMap, or returns the original type
77+
/// if no match was found.
78+
struct QueryTypeSubstitutionMapOrIdentity {
79+
const TypeSubstitutionMap &substitutions;
80+
81+
Type operator()(SubstitutableType *type) const;
82+
};
83+
7584
/// A function object suitable for use as a \c TypeSubstitutionFn that
7685
/// queries an underlying \c SubstitutionMap.
7786
struct QuerySubstitutionMap {

include/swift/SIL/SILCloner.h

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,21 @@ class SILCloner : protected SILVisitor<ImplClass> {
118118
}
119119

120120
SILType getTypeInClonedContext(SILType Ty) {
121+
auto objectTy = Ty.getSwiftRValueType();
122+
// Do not substitute opened existential types, if we do not have any.
123+
if (!objectTy->hasOpenedExistential())
124+
return Ty;
125+
// Do not substitute opened existential types, if it is not required.
126+
// This is often the case when cloning basic blocks inside the same
127+
// function.
128+
if (OpenedExistentialSubs.empty())
129+
return Ty;
130+
121131
// Substitute opened existential types, if we have any.
122-
return SILType::getPrimitiveObjectType(
123-
getASTTypeInClonedContext(Ty.getSwiftRValueType()))
124-
.copyCategory(Ty);
132+
return Ty.subst(
133+
Builder.getModule(),
134+
QueryTypeSubstitutionMapOrIdentity{OpenedExistentialSubs},
135+
MakeAbstractConformanceForGenericType());
125136
}
126137
SILType getOpType(SILType Ty) {
127138
Ty = getTypeInClonedContext(Ty);
@@ -138,24 +149,10 @@ class SILCloner : protected SILVisitor<ImplClass> {
138149
if (OpenedExistentialSubs.empty())
139150
return ty->getCanonicalType();
140151

141-
return ty.transform(
142-
[&](Type t) -> Type {
143-
if (t->isOpenedExistential()) {
144-
auto found = OpenedExistentialSubs.find(
145-
t->castTo<ArchetypeType>());
146-
// If an opened existential is supposed to be
147-
// remapped, it is guaranteed by construction
148-
// to be in the OpenedExistentialSubs, because
149-
// a cloner always processes definitions of
150-
// opened existentials before their uses and
151-
// adds found opened existentials definitions
152-
// to the map.
153-
if (found != OpenedExistentialSubs.end())
154-
return found->second;
155-
return t;
156-
}
157-
return t;
158-
})->getCanonicalType();
152+
return ty.subst(
153+
QueryTypeSubstitutionMapOrIdentity{OpenedExistentialSubs},
154+
MakeAbstractConformanceForGenericType()
155+
)->getCanonicalType();
159156
}
160157

161158
CanType getOpASTType(CanType ty) {

lib/AST/Type.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ Type QueryTypeSubstitutionMap::operator()(SubstitutableType *type) const {
5050
return Type();
5151
}
5252

53+
Type
54+
QueryTypeSubstitutionMapOrIdentity::operator()(SubstitutableType *type) const {
55+
auto key = type->getCanonicalType()->castTo<SubstitutableType>();
56+
auto known = substitutions.find(key);
57+
if (known != substitutions.end() && known->second)
58+
return known->second;
59+
60+
return type;
61+
}
62+
5363
Type QuerySubstitutionMap::operator()(SubstitutableType *type) const {
5464
auto key = cast<SubstitutableType>(type->getCanonicalType());
5565
return subMap.lookupSubstitution(key);

0 commit comments

Comments
 (0)