Skip to content

Commit 4ec6dc1

Browse files
committed
Erase opaque types involving opened existential types to their upper bound.
1 parent 1e1b342 commit 4ec6dc1

File tree

3 files changed

+59
-1
lines changed

3 files changed

+59
-1
lines changed

lib/AST/Type.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,20 @@ Type TypeBase::typeEraseOpenedArchetypesWithRoot(
507507
return Type(ExistentialMetatypeType::get(erasedTy));
508508
}
509509

510+
// Opaque types whose substitutions involve this type parameter are
511+
// erased to their upper bound.
512+
if (auto opaque = dyn_cast<OpaqueTypeArchetypeType>(ty)) {
513+
for (auto replacementType :
514+
opaque->getSubstitutions().getReplacementTypes()) {
515+
if (replacementType->hasOpenedExistentialWithRoot(root)) {
516+
Type interfaceType = opaque->getInterfaceType();
517+
auto genericSig =
518+
opaque->getDecl()->getOpaqueInterfaceGenericSignature();
519+
return genericSig->getNonDependentUpperBounds(interfaceType);
520+
}
521+
}
522+
}
523+
510524
auto *const archetype = dyn_cast<OpenedArchetypeType>(ty);
511525
if (!archetype) {
512526
// Recurse.

lib/Sema/ConstraintSystem.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1777,6 +1777,19 @@ static Type typeEraseCovariantExistentialSelfReferences(Type refTy,
17771777

17781778
unsigned metatypeDepth = 0;
17791779

1780+
/// Check whether the given type has a reference to the generic parameter
1781+
/// that we are erasing.
1782+
auto hasErasedGenericParameter = [&](Type type) {
1783+
if (!type->hasTypeParameter())
1784+
return false;
1785+
1786+
return type.findIf([&](Type type) {
1787+
if (auto gp = type->getAs<GenericTypeParamType>())
1788+
return gp->getDepth() == 0;
1789+
return false;
1790+
});
1791+
};
1792+
17801793
std::function<Type(Type, TypePosition)> transformFn;
17811794
transformFn = [&](Type type, TypePosition initialPos) -> Type {
17821795
return type.transformWithPosition(
@@ -1798,6 +1811,20 @@ static Type typeEraseCovariantExistentialSelfReferences(Type refTy,
17981811
return Type(ExistentialMetatypeType::get(erasedTy));
17991812
}
18001813

1814+
// Opaque types whose substitutions involve this type parameter are
1815+
// erased to their upper bound.
1816+
if (auto opaque = dyn_cast<OpaqueTypeArchetypeType>(type.getPointer())) {
1817+
for (auto replacementType :
1818+
opaque->getSubstitutions().getReplacementTypes()) {
1819+
if (hasErasedGenericParameter(replacementType)) {
1820+
Type interfaceType = opaque->getInterfaceType();
1821+
auto genericSig =
1822+
opaque->getDecl()->getOpaqueInterfaceGenericSignature();
1823+
return genericSig->getNonDependentUpperBounds(interfaceType);
1824+
}
1825+
}
1826+
}
1827+
18011828
if (!t->isTypeParameter()) {
18021829
// Recurse.
18031830
return None;

test/Constraints/opened_existentials.swift

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -enable-experimental-opened-existential-types -enable-parameterized-protocol-types -enable-experimental-opaque-parameters
1+
// RUN: %target-typecheck-verify-swift -enable-experimental-opened-existential-types -enable-parametrized-protocol-types -enable-experimental-opaque-parameters
22

33
protocol Q { }
44

@@ -60,3 +60,20 @@ func testMultipleOpened(a: any P, b: any P & Q) {
6060
let r2 = a.combineThePs(b)
6161
let _: Int = r2 // expected-error{{cannot convert value of type '(Q, Q)?' to specified type 'Int'}}
6262
}
63+
64+
// --- With primary associated types and opaque parameter types
65+
protocol CollectionOf: Collection {
66+
@_primaryAssociatedType associatedtype Element
67+
}
68+
69+
extension Array: CollectionOf { }
70+
extension Set: CollectionOf { }
71+
72+
func reverseIt<T>(_ c: some CollectionOf<T>) -> some CollectionOf<T> {
73+
return c.reversed()
74+
}
75+
76+
func useReverseIt(_ c: any CollectionOf) {
77+
let c = reverseIt(c)
78+
let _: Int = c // expected-error{{cannot convert value of type 'CollectionOf' to specified type 'Int'}}
79+
}

0 commit comments

Comments
 (0)