Skip to content

Commit 8299655

Browse files
committed
Sema: Use new form of getOpenedExistentialSignature() in typeEraseOpenedExistentialReference()
1 parent 6b67ba6 commit 8299655

File tree

2 files changed

+84
-89
lines changed

2 files changed

+84
-89
lines changed

lib/AST/ExistentialGeneralization.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ class Generalizer : public CanTypeVisitor<Generalizer, Type> {
8181
private:
8282
Type visitProtocolType(CanProtocolType type) {
8383
// Simple protocol types have no sub-structure.
84-
assert(!type.getParent() || !type.getParent()->isSpecialized());
8584
return type;
8685
}
8786

lib/Sema/ConstraintSystem.cpp

Lines changed: 84 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -2265,26 +2265,14 @@ static bool isMainDispatchQueueMember(ConstraintLocator *locator) {
22652265
return true;
22662266
}
22672267

2268-
/// Transforms `refTy` as follows.
2269-
///
2270-
/// For each occurrence of a type **type** that satisfies `predicateFn` in
2271-
/// covariant position:
2272-
/// 1. **type** is projected to a type parameter using `projectionFn`.
2273-
/// 2. If the type parameter is not bound to a concrete type, it is type-erased
2274-
/// to the most specific upper bounds using `existentialSig` and substituted
2275-
/// for **type**. Otherwise, the concrete type is transformed recursively.
2276-
/// The result is substituted for **type** unless it is an identity
2277-
/// transform.
2278-
///
2279-
/// `baseTy` is used as a ready substitution for the `Self` generic parameter.
2280-
///
2281-
/// @param force If `true`, proceeds regardless of a type's variance position.
2268+
/// For each occurrence of a type **type** in `refTy` that satisfies
2269+
/// `predicateFn` in covariant position, **type** is erased to an
2270+
/// existential using `eraseFn`.
22822271
static Type typeEraseExistentialSelfReferences(
2283-
Type refTy, Type baseTy, TypePosition outermostPosition,
2284-
GenericSignature existentialSig, llvm::function_ref<bool(Type)> containsFn,
2272+
Type refTy, TypePosition outermostPosition,
2273+
llvm::function_ref<bool(Type)> containsFn,
22852274
llvm::function_ref<bool(Type)> predicateFn,
2286-
llvm::function_ref<Type(Type)> projectionFn, bool force) {
2287-
assert(baseTy->isExistentialType());
2275+
llvm::function_ref<Type(Type, TypePosition)> eraseFn) {
22882276
if (!containsFn(refTy))
22892277
return refTy;
22902278

@@ -2298,8 +2286,8 @@ static Type typeEraseExistentialSelfReferences(
22982286
if (t->is<MetatypeType>()) {
22992287
const auto instanceTy = t->getMetatypeInstanceType();
23002288
auto erasedTy = typeEraseExistentialSelfReferences(
2301-
instanceTy, baseTy, currPos, existentialSig, containsFn,
2302-
predicateFn, projectionFn, force);
2289+
instanceTy, currPos,
2290+
containsFn, predicateFn, eraseFn);
23032291
if (instanceTy.getPointer() == erasedTy.getPointer()) {
23042292
return Type(t);
23052293
}
@@ -2327,8 +2315,8 @@ static Type typeEraseExistentialSelfReferences(
23272315
for (auto replacementType :
23282316
opaque->getSubstitutions().getReplacementTypes()) {
23292317
auto erasedReplacementType = typeEraseExistentialSelfReferences(
2330-
replacementType, baseTy, TypePosition::Covariant,
2331-
existentialSig, containsFn, predicateFn, projectionFn, force);
2318+
replacementType, TypePosition::Covariant,
2319+
containsFn, predicateFn, eraseFn);
23322320
if (erasedReplacementType.getPointer() !=
23332321
replacementType.getPointer())
23342322
return opaque->getExistentialType();
@@ -2340,8 +2328,8 @@ static Type typeEraseExistentialSelfReferences(
23402328
if (auto parameterized = dyn_cast<ParameterizedProtocolType>(t)) {
23412329
for (auto argType : parameterized->getArgs()) {
23422330
auto erasedArgType = typeEraseExistentialSelfReferences(
2343-
argType, baseTy, TypePosition::Covariant, existentialSig,
2344-
containsFn, predicateFn, projectionFn, force);
2331+
argType, TypePosition::Covariant,
2332+
containsFn, predicateFn, eraseFn);
23452333
if (erasedArgType.getPointer() != argType.getPointer())
23462334
return parameterized->getBaseType();
23472335
}
@@ -2351,9 +2339,8 @@ static Type typeEraseExistentialSelfReferences(
23512339
auto objTy = lvalue->getObjectType();
23522340
auto erasedTy =
23532341
typeEraseExistentialSelfReferences(
2354-
objTy, baseTy, currPos,
2355-
existentialSig, containsFn, predicateFn, projectionFn,
2356-
force);
2342+
objTy, currPos,
2343+
containsFn, predicateFn, eraseFn);
23572344
23582345
if (erasedTy.getPointer() == objTy.getPointer())
23592346
return Type(lvalue);
@@ -2367,52 +2354,10 @@ static Type typeEraseExistentialSelfReferences(
23672354
return std::nullopt;
23682355
}
23692356

2370-
auto paramTy = projectionFn(t);
2371-
if (!paramTy)
2357+
auto erasedTy = eraseFn(t, currPos);
2358+
if (!erasedTy)
23722359
return Type(t);
23732360

2374-
assert(paramTy->isTypeParameter());
2375-
2376-
// This can happen with invalid code.
2377-
if (!existentialSig->isValidTypeParameter(paramTy)) {
2378-
return Type(t);
2379-
}
2380-
2381-
// If the type parameter is fixed to a concrete type, recurse into it.
2382-
if (const auto concreteTy = existentialSig->getConcreteType(paramTy)) {
2383-
auto erasedTy = typeEraseExistentialSelfReferences(
2384-
concreteTy, baseTy, currPos, existentialSig,
2385-
[](Type t) { return t->hasTypeParameter(); },
2386-
[](Type t) { return t->isTypeParameter(); },
2387-
[](Type t) { return t; }, force);
2388-
if (erasedTy.getPointer() == concreteTy.getPointer()) {
2389-
return Type(t);
2390-
}
2391-
2392-
return erasedTy;
2393-
}
2394-
2395-
if (!force) {
2396-
switch (currPos) {
2397-
case TypePosition::Covariant:
2398-
break;
2399-
2400-
case TypePosition::Contravariant:
2401-
case TypePosition::Invariant:
2402-
case TypePosition::Shape:
2403-
return Type(t);
2404-
}
2405-
}
2406-
2407-
Type erasedTy;
2408-
2409-
// The upper bounds of 'Self' is the existential base type.
2410-
if (paramTy->is<GenericTypeParamType>()) {
2411-
erasedTy = baseTy;
2412-
} else {
2413-
erasedTy = existentialSig->getExistentialType(paramTy);
2414-
}
2415-
24162361
return erasedTy;
24172362
});
24182363
}
@@ -2422,58 +2367,109 @@ Type constraints::typeEraseOpenedExistentialReference(
24222367
TypePosition outermostPosition) {
24232368
auto existentialSig =
24242369
type->getASTContext().getOpenedExistentialSignature(
2425-
existentialBaseType, GenericSignature());
2426-
auto selfGP = existentialSig.getGenericParams()[0];
2370+
existentialBaseType);
2371+
2372+
auto applyOuterSubstitutions = [&](Type t) -> Type {
2373+
if (t->hasTypeParameter()) {
2374+
auto outerSubs = existentialSig.Generalization;
2375+
unsigned depth = existentialSig.OpenedSig->getMaxDepth();
2376+
OuterSubstitutions replacer{outerSubs, depth};
2377+
return t.subst(replacer, replacer);
2378+
}
2379+
2380+
return t;
2381+
};
2382+
2383+
auto erase = [&](Type paramTy, TypePosition currPos) -> Type {
2384+
switch (currPos) {
2385+
case TypePosition::Covariant:
2386+
break;
2387+
2388+
case TypePosition::Contravariant:
2389+
case TypePosition::Invariant:
2390+
case TypePosition::Shape:
2391+
return Type();
2392+
}
2393+
2394+
// The upper bounds of 'Self' is the existential base type.
2395+
if (paramTy->is<GenericTypeParamType>())
2396+
return existentialBaseType;
2397+
2398+
return applyOuterSubstitutions(
2399+
existentialSig.OpenedSig->getExistentialType(paramTy));
2400+
};
24272401

24282402
return typeEraseExistentialSelfReferences(
2429-
type, existentialBaseType, outermostPosition, existentialSig,
2403+
type,
2404+
outermostPosition,
24302405
/*containsFn=*/[](Type t) {
24312406
return t->hasTypeVariable();
24322407
},
24332408
/*predicateFn=*/[](Type t) {
24342409
return t->isTypeVariableOrMember();
24352410
},
2436-
/*projectionFn=*/[&](Type t) {
2411+
/*eraseFn=*/[&](Type t, TypePosition currPos) -> Type {
24372412
bool found = false;
2438-
auto result = t.transformRec([&](Type t) -> std::optional<Type> {
2413+
auto paramTy = t.transformRec([&](Type t) -> std::optional<Type> {
24392414
if (t.getPointer() == openedTypeVar) {
24402415
found = true;
2441-
return selfGP;
2416+
return existentialSig.SelfType;
24422417
}
24432418
return std::nullopt;
24442419
});
24452420

24462421
if (!found)
24472422
return Type();
24482423

2449-
assert(result->isTypeParameter());
2450-
return result;
2451-
},
2452-
/*force=*/false);
2424+
assert(paramTy->isTypeParameter());
2425+
2426+
// This can happen with invalid code.
2427+
if (!existentialSig.OpenedSig->isValidTypeParameter(paramTy)) {
2428+
return Type(t);
2429+
}
2430+
2431+
// Check if this existential fixes this `Self`-rooted type to something
2432+
// in the existential's outer generic signature.
2433+
Type reducedTy = existentialSig.OpenedSig.getReducedType(paramTy);
2434+
if (!reducedTy->isEqual(paramTy)) {
2435+
reducedTy = applyOuterSubstitutions(reducedTy);
2436+
2437+
auto erasedTy = typeEraseExistentialSelfReferences(
2438+
reducedTy, currPos,
2439+
[&](Type t) { return t->hasTypeParameter(); },
2440+
[&](Type t) { return t->isTypeParameter(); },
2441+
[&](Type t, TypePosition currPos) { return erase(t, currPos); });
2442+
if (erasedTy.getPointer() == reducedTy.getPointer()) {
2443+
return Type(t);
2444+
}
2445+
2446+
return erasedTy;
2447+
}
2448+
2449+
return erase(paramTy, currPos);
2450+
});
24532451
}
24542452

24552453
Type constraints::typeEraseOpenedArchetypesFromEnvironment(
24562454
Type type, GenericEnvironment *env) {
24572455
assert(env->getKind() == GenericEnvironment::Kind::OpenedExistential);
24582456

2459-
auto sig = env->getGenericSignature();
2460-
24612457
return typeEraseExistentialSelfReferences(
2462-
type, env->getOpenedExistentialType(), TypePosition::Covariant, sig,
2458+
type,
2459+
TypePosition::Covariant,
24632460
/*containsFn=*/[](Type t) {
24642461
return t->hasOpenedExistential();
24652462
},
24662463
/*predicateFn=*/[](Type t) {
24672464
return t->is<OpenedArchetypeType>();
24682465
},
2469-
/*projectionFn=*/[&](Type t) {
2466+
/*eraseFn=*/[&](Type t, TypePosition currPos) {
24702467
auto *openedTy = t->castTo<OpenedArchetypeType>();
24712468
if (openedTy->getGenericEnvironment() == env)
2472-
return openedTy->getInterfaceType();
2469+
return openedTy->getExistentialType();
24732470

24742471
return Type();
2475-
},
2476-
/*force=*/true);
2472+
});
24772473
}
24782474

24792475
static bool isExistentialMemberAccessWithExplicitBaseExpression(

0 commit comments

Comments
 (0)