Skip to content

Commit 6fb5b94

Browse files
committed
Sema: Simplify recursion in typeEraseExistentialSelfReferences()
1 parent 8172343 commit 6fb5b94

File tree

1 file changed

+94
-91
lines changed

1 file changed

+94
-91
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 94 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,114 +2131,117 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
21312131
if (!containsFn(refTy))
21322132
return refTy;
21332133

2134-
std::function<Type(Type, TypePosition)> transformFn;
2135-
transformFn = [&](Type type, TypePosition initialPos) -> Type {
2136-
return type.transformWithPosition(
2137-
initialPos,
2138-
[&](TypeBase *t, TypePosition currPos) -> llvm::Optional<Type> {
2139-
if (!containsFn(t)) {
2140-
return Type(t);
2141-
}
2134+
return refTy.transformWithPosition(
2135+
outermostPosition,
2136+
[&](TypeBase *t, TypePosition currPos) -> llvm::Optional<Type> {
2137+
if (!containsFn(t)) {
2138+
return Type(t);
2139+
}
21422140

2143-
if (t->is<MetatypeType>()) {
2144-
const auto instanceTy = t->getMetatypeInstanceType();
2145-
++metatypeDepth;
2146-
const auto erasedTy = transformFn(instanceTy, currPos);
2147-
--metatypeDepth;
2141+
if (t->is<MetatypeType>()) {
2142+
const auto instanceTy = t->getMetatypeInstanceType();
2143+
const auto erasedTy =
2144+
typeEraseExistentialSelfReferences(
2145+
instanceTy, baseTy, currPos,
2146+
existentialSig, containsFn, predicateFn, projectionFn,
2147+
force, metatypeDepth + 1);
21482148

2149-
if (instanceTy.getPointer() == erasedTy.getPointer()) {
2150-
return Type(t);
2151-
}
2149+
if (instanceTy.getPointer() == erasedTy.getPointer()) {
2150+
return Type(t);
2151+
}
21522152

2153-
return Type(ExistentialMetatypeType::get(erasedTy));
2154-
}
2153+
return Type(ExistentialMetatypeType::get(erasedTy));
2154+
}
21552155

2156-
// Opaque types whose substitutions involve this type parameter are
2157-
// erased to their upper bound.
2158-
if (auto opaque = dyn_cast<OpaqueTypeArchetypeType>(t)) {
2159-
for (auto replacementType :
2160-
opaque->getSubstitutions().getReplacementTypes()) {
2161-
auto erasedReplacementType = transformFn(replacementType,
2162-
TypePosition::Covariant);
2163-
if (erasedReplacementType.getPointer() != replacementType.getPointer())
2164-
return opaque->getExistentialType();
2165-
}
2166-
}
2156+
// Opaque types whose substitutions involve this type parameter are
2157+
// erased to their upper bound.
2158+
if (auto opaque = dyn_cast<OpaqueTypeArchetypeType>(t)) {
2159+
for (auto replacementType :
2160+
opaque->getSubstitutions().getReplacementTypes()) {
2161+
auto erasedReplacementType =
2162+
typeEraseExistentialSelfReferences(
2163+
replacementType, baseTy, TypePosition::Covariant,
2164+
existentialSig, containsFn, predicateFn, projectionFn,
2165+
force, metatypeDepth);
2166+
if (erasedReplacementType.getPointer() != replacementType.getPointer())
2167+
return opaque->getExistentialType();
2168+
}
2169+
}
21672170

2168-
if (auto lvalue = dyn_cast<LValueType>(t)) {
2169-
auto objTy = lvalue->getObjectType();
2170-
auto erased = transformFn(objTy, currPos);
2171-
if (erased.getPointer() == objTy.getPointer())
2172-
return Type(lvalue);
2171+
if (auto lvalue = dyn_cast<LValueType>(t)) {
2172+
auto objTy = lvalue->getObjectType();
2173+
auto erasedTy =
2174+
typeEraseExistentialSelfReferences(
2175+
objTy, baseTy, currPos,
2176+
existentialSig, containsFn, predicateFn, projectionFn,
2177+
force, metatypeDepth);
21732178

2174-
return erased;
2175-
}
2179+
if (erasedTy.getPointer() == objTy.getPointer())
2180+
return Type(lvalue);
21762181

2177-
if (!predicateFn(t)) {
2178-
// Recurse.
2179-
return llvm::None;
2180-
}
2182+
return erasedTy;
2183+
}
21812184

2182-
auto paramTy = projectionFn(t);
2183-
if (!paramTy)
2184-
return Type(t);
2185+
if (!predicateFn(t)) {
2186+
// Recurse.
2187+
return llvm::None;
2188+
}
21852189

2186-
// This can happen with invalid code.
2187-
if (!existentialSig->isValidTypeParameter(paramTy)) {
2188-
return Type(t);
2189-
}
2190+
auto paramTy = projectionFn(t);
2191+
if (!paramTy)
2192+
return Type(t);
21902193

2191-
// If the type parameter is fixed to a concrete type, recurse into it.
2192-
if (const auto concreteTy = existentialSig->getConcreteType(paramTy)) {
2193-
auto erasedTy = typeEraseExistentialSelfReferences(
2194-
concreteTy, baseTy, currPos, existentialSig,
2195-
[](Type t) { return t->hasTypeParameter(); },
2196-
[](Type t) { return t->isTypeParameter(); },
2197-
[](Type t) {
2198-
assert(t->isTypeParameter());
2199-
return t;
2200-
},
2201-
metatypeDepth);
2202-
if (erasedTy.getPointer() == concreteTy.getPointer()) {
2203-
// Don't return the concrete type if we haven't type-erased
2204-
// anything inside it, or else we might inadvertently transform a
2205-
// normal metatype into an existential one.
2206-
return Type(t);
2207-
}
2194+
// This can happen with invalid code.
2195+
if (!existentialSig->isValidTypeParameter(paramTy)) {
2196+
return Type(t);
2197+
}
22082198

2209-
return erasedTy;
2210-
}
2199+
// If the type parameter is fixed to a concrete type, recurse into it.
2200+
if (const auto concreteTy = existentialSig->getConcreteType(paramTy)) {
2201+
auto erasedTy = typeEraseExistentialSelfReferences(
2202+
concreteTy, baseTy, currPos, existentialSig,
2203+
[](Type t) { return t->hasTypeParameter(); },
2204+
[](Type t) { return t->isTypeParameter(); },
2205+
[](Type t) { return t; },
2206+
force, metatypeDepth);
2207+
if (erasedTy.getPointer() == concreteTy.getPointer()) {
2208+
// Don't return the concrete type if we haven't type-erased
2209+
// anything inside it, or else we might inadvertently transform a
2210+
// normal metatype into an existential one.
2211+
return Type(t);
2212+
}
22112213

2212-
if (!force) {
2213-
switch (currPos) {
2214-
case TypePosition::Covariant:
2215-
break;
2214+
return erasedTy;
2215+
}
22162216

2217-
case TypePosition::Contravariant:
2218-
case TypePosition::Invariant:
2219-
case TypePosition::Shape:
2220-
return Type(t);
2221-
}
2222-
}
2217+
if (!force) {
2218+
switch (currPos) {
2219+
case TypePosition::Covariant:
2220+
break;
22232221

2224-
Type erasedTy;
2222+
case TypePosition::Contravariant:
2223+
case TypePosition::Invariant:
2224+
case TypePosition::Shape:
2225+
return Type(t);
2226+
}
2227+
}
22252228

2226-
// The upper bounds of 'Self' is the existential base type.
2227-
if (paramTy->is<GenericTypeParamType>()) {
2228-
erasedTy = baseTy;
2229-
} else {
2230-
erasedTy = existentialSig->getUpperBound(paramTy);
2231-
}
2229+
Type erasedTy;
22322230

2233-
if (metatypeDepth) {
2234-
if (const auto existential = erasedTy->getAs<ExistentialType>())
2235-
return existential->getConstraintType();
2236-
}
2231+
// The upper bounds of 'Self' is the existential base type.
2232+
if (paramTy->is<GenericTypeParamType>()) {
2233+
erasedTy = baseTy;
2234+
} else {
2235+
erasedTy = existentialSig->getUpperBound(paramTy);
2236+
}
22372237

2238-
return erasedTy;
2239-
});
2240-
};
2241-
return transformFn(refTy, outermostPosition);
2238+
if (metatypeDepth) {
2239+
if (const auto existential = erasedTy->getAs<ExistentialType>())
2240+
return existential->getConstraintType();
2241+
}
2242+
2243+
return erasedTy;
2244+
});
22422245
}
22432246

22442247
Type constraints::typeEraseOpenedExistentialReference(

0 commit comments

Comments
 (0)