Skip to content

Commit 8172343

Browse files
committed
Sema: Extract duplication between typeEraseOpenedExistentialReference() and typeEraseOpenedArchetypesWithRoot()
1 parent c0f9d29 commit 8172343

File tree

1 file changed

+83
-128
lines changed

1 file changed

+83
-128
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 83 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -2115,30 +2115,28 @@ static bool isMainDispatchQueueMember(ConstraintLocator *locator) {
21152115
}
21162116

21172117
/// Type-erase occurrences of covariant 'Self'-rooted type parameters to their
2118-
/// most specific non-dependent bounds throughout the given type, using
2119-
/// \p baseTy as the existential base object type.
2118+
/// most specific upper bounds throughout the given type, using \p baseTy as
2119+
/// the existential base object type.
21202120
///
21212121
/// \note If a 'Self'-rooted type parameter is bound to a concrete type, this
21222122
/// routine will recurse into the concrete type.
21232123
static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
2124-
TypePosition outermostPosition) {
2124+
TypePosition outermostPosition,
2125+
GenericSignature existentialSig,
2126+
llvm::function_ref<bool(Type)> containsFn,
2127+
llvm::function_ref<bool(Type)> predicateFn,
2128+
llvm::function_ref<Type(Type)> projectionFn,
2129+
bool force, unsigned metatypeDepth = 0) {
21252130
assert(baseTy->isExistentialType());
2126-
if (!refTy->hasTypeParameter()) {
2131+
if (!containsFn(refTy))
21272132
return refTy;
2128-
}
2129-
2130-
const auto existentialSig =
2131-
baseTy->getASTContext().getOpenedExistentialSignature(baseTy,
2132-
GenericSignature());
2133-
2134-
unsigned metatypeDepth = 0;
21352133

21362134
std::function<Type(Type, TypePosition)> transformFn;
21372135
transformFn = [&](Type type, TypePosition initialPos) -> Type {
21382136
return type.transformWithPosition(
21392137
initialPos,
21402138
[&](TypeBase *t, TypePosition currPos) -> llvm::Optional<Type> {
2141-
if (!t->hasTypeParameter()) {
2139+
if (!containsFn(t)) {
21422140
return Type(t);
21432141
}
21442142

@@ -2160,9 +2158,10 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
21602158
if (auto opaque = dyn_cast<OpaqueTypeArchetypeType>(t)) {
21612159
for (auto replacementType :
21622160
opaque->getSubstitutions().getReplacementTypes()) {
2163-
if (replacementType->hasTypeParameter()) {
2161+
auto erasedReplacementType = transformFn(replacementType,
2162+
TypePosition::Covariant);
2163+
if (erasedReplacementType.getPointer() != replacementType.getPointer())
21642164
return opaque->getExistentialType();
2165-
}
21662165
}
21672166
}
21682167

@@ -2175,21 +2174,31 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
21752174
return erased;
21762175
}
21772176

2178-
if (!t->isTypeParameter()) {
2177+
if (!predicateFn(t)) {
21792178
// Recurse.
21802179
return llvm::None;
21812180
}
21822181

2183-
assert(t->getRootGenericParam()->getDepth() == 0);
2182+
auto paramTy = projectionFn(t);
2183+
if (!paramTy)
2184+
return Type(t);
21842185

21852186
// This can happen with invalid code.
2186-
if (!existentialSig->isValidTypeParameter(t)) {
2187+
if (!existentialSig->isValidTypeParameter(paramTy)) {
21872188
return Type(t);
21882189
}
21892190

2190-
// If the type parameter is bound to a concrete type, recurse into it.
2191-
if (const auto concreteTy = existentialSig->getConcreteType(t)) {
2192-
const auto erasedTy = transformFn(concreteTy, currPos);
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);
21932202
if (erasedTy.getPointer() == concreteTy.getPointer()) {
21942203
// Don't return the concrete type if we haven't type-erased
21952204
// anything inside it, or else we might inadvertently transform a
@@ -2200,23 +2209,25 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
22002209
return erasedTy;
22012210
}
22022211

2203-
switch (currPos) {
2204-
case TypePosition::Covariant:
2205-
break;
2212+
if (!force) {
2213+
switch (currPos) {
2214+
case TypePosition::Covariant:
2215+
break;
22062216

2207-
case TypePosition::Contravariant:
2208-
case TypePosition::Invariant:
2209-
case TypePosition::Shape:
2210-
return Type(t);
2217+
case TypePosition::Contravariant:
2218+
case TypePosition::Invariant:
2219+
case TypePosition::Shape:
2220+
return Type(t);
2221+
}
22112222
}
22122223

22132224
Type erasedTy;
22142225

22152226
// The upper bounds of 'Self' is the existential base type.
2216-
if (t->is<GenericTypeParamType>()) {
2227+
if (paramTy->is<GenericTypeParamType>()) {
22172228
erasedTy = baseTy;
22182229
} else {
2219-
erasedTy = existentialSig->getUpperBound(t);
2230+
erasedTy = existentialSig->getUpperBound(paramTy);
22202231
}
22212232

22222233
if (metatypeDepth) {
@@ -2233,117 +2244,61 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
22332244
Type constraints::typeEraseOpenedExistentialReference(
22342245
Type type, Type existentialBaseType, TypeVariableType *openedTypeVar,
22352246
TypePosition outermostPosition) {
2236-
Type selfGP = GenericTypeParamType::get(false, 0, 0, type->getASTContext());
2237-
2238-
// First, temporarily reconstitute the 'Self' generic parameter.
2239-
type = type.transformRec([&](TypeBase *t) -> llvm::Optional<Type> {
2240-
// Don't recurse into children unless we have to.
2241-
if (!type->hasTypeVariable())
2242-
return Type(t);
2243-
2244-
if (isa<TypeVariableType>(t) && t->isEqual(openedTypeVar))
2245-
return selfGP;
2246-
2247-
// Recurse.
2248-
return llvm::None;
2249-
});
2250-
2251-
// Then, type-erase occurrences of covariant 'Self'-rooted type parameters.
2252-
type = typeEraseExistentialSelfReferences(type, existentialBaseType,
2253-
outermostPosition);
2254-
2255-
// Finally, swap the 'Self'-corresponding type variable back in.
2256-
return type.transformRec([&](TypeBase *t) -> llvm::Optional<Type> {
2257-
// Don't recurse into children unless we have to.
2258-
if (!type->hasTypeParameter())
2259-
return Type(t);
2247+
auto existentialSig =
2248+
type->getASTContext().getOpenedExistentialSignature(
2249+
existentialBaseType, GenericSignature());
2250+
auto selfGP = existentialSig.getGenericParams()[0];
2251+
2252+
return typeEraseExistentialSelfReferences(
2253+
type, existentialBaseType, outermostPosition, existentialSig,
2254+
/*containsFn=*/[](Type t) {
2255+
return t->hasTypeVariable();
2256+
},
2257+
/*predicateFn=*/[](Type t) {
2258+
return t->isTypeVariableOrMember();
2259+
},
2260+
/*projectionFn=*/[&](Type t) {
2261+
bool found = false;
2262+
auto result = t.transformRec([&](Type t) -> llvm::Optional<Type> {
2263+
if (t.getPointer() == openedTypeVar) {
2264+
found = true;
2265+
return selfGP;
2266+
}
2267+
return llvm::None;
2268+
});
22602269

2261-
if (isa<GenericTypeParamType>(t) && t->isEqual(selfGP))
2262-
return Type(openedTypeVar);
2270+
if (!found)
2271+
return Type();
22632272

2264-
// Recurse.
2265-
return llvm::None;
2266-
});
2273+
assert(result->isTypeParameter());
2274+
return result;
2275+
},
2276+
/*force=*/false);
22672277
}
22682278

22692279
Type constraints::typeEraseOpenedArchetypesWithRoot(
22702280
Type type, const OpenedArchetypeType *root) {
22712281
assert(root->isRoot() && "Expected a root archetype");
22722282

2273-
if (!type->hasOpenedExistential())
2274-
return type;
2275-
22762283
auto *env = root->getGenericEnvironment();
22772284
auto sig = env->getGenericSignature();
22782285

2279-
unsigned metatypeDepth = 0;
2280-
2281-
std::function<Type(Type)> transformFn;
2282-
transformFn = [&](Type type) -> Type {
2283-
return type.transformRec([&](TypeBase *ty) -> llvm::Optional<Type> {
2284-
// Don't recurse into children unless we have to.
2285-
if (!ty->hasOpenedExistential())
2286-
return Type(ty);
2287-
2288-
if (isa<MetatypeType>(ty)) {
2289-
const auto instanceTy = ty->getMetatypeInstanceType();
2290-
++metatypeDepth;
2291-
const auto erasedTy = transformFn(instanceTy);
2292-
--metatypeDepth;
2293-
2294-
if (instanceTy.getPointer() == erasedTy.getPointer()) {
2295-
return Type(ty);
2296-
}
2297-
2298-
return Type(ExistentialMetatypeType::get(erasedTy));
2299-
}
2300-
2301-
// Opaque types whose substitutions involve this type parameter are
2302-
// erased to their upper bound.
2303-
if (auto opaque = dyn_cast<OpaqueTypeArchetypeType>(ty)) {
2304-
for (auto replacementType :
2305-
opaque->getSubstitutions().getReplacementTypes()) {
2306-
if (replacementType->hasOpenedExistentialWithRoot(root)) {
2307-
return opaque->getExistentialType();
2308-
}
2309-
}
2310-
}
2311-
2312-
if (auto lvalue = dyn_cast<LValueType>(type)) {
2313-
auto objTy = lvalue->getObjectType();
2314-
auto erased = transformFn(objTy);
2315-
if (erased.getPointer() == objTy.getPointer())
2316-
return Type(lvalue);
2317-
2318-
return erased;
2319-
}
2320-
2321-
auto *const archetype = dyn_cast<OpenedArchetypeType>(ty);
2322-
if (!archetype) {
2323-
// Recurse.
2324-
return llvm::None;
2325-
}
2326-
2327-
if (archetype->getGenericEnvironment() != env)
2328-
return Type(ty);
2329-
2330-
Type erasedTy;
2331-
if (root->isEqual(archetype)) {
2332-
erasedTy = root->getExistentialType();
2333-
} else {
2334-
erasedTy = sig->getUpperBound(archetype->getInterfaceType());
2335-
}
2336-
2337-
if (metatypeDepth) {
2338-
if (const auto existential = erasedTy->getAs<ExistentialType>())
2339-
return existential->getConstraintType();
2340-
}
2341-
2342-
return erasedTy;
2343-
});
2344-
};
2286+
return typeEraseExistentialSelfReferences(
2287+
type, root->getExistentialType(), TypePosition::Covariant, sig,
2288+
/*containsFn=*/[](Type t) {
2289+
return t->hasOpenedExistential();
2290+
},
2291+
/*predicateFn=*/[](Type t) {
2292+
return t->is<OpenedArchetypeType>();
2293+
},
2294+
/*projectionFn=*/[&](Type t) {
2295+
auto *openedTy = t->castTo<OpenedArchetypeType>();
2296+
if (openedTy->getGenericEnvironment() == env)
2297+
return openedTy->getInterfaceType();
23452298

2346-
return transformFn(type);
2299+
return Type();
2300+
},
2301+
/*force=*/true);
23472302
}
23482303

23492304
Type ConstraintSystem::getMemberReferenceTypeFromOpenedType(

0 commit comments

Comments
 (0)