Skip to content

Commit 73b16ba

Browse files
committed
[CSFix] Refine coercion check for dependent member chains
For types like `<Base>.B.C` we need to check that neither `B` nor `C` have any additional requirements because they cannot be expressed in the existential type.
1 parent f08eec4 commit 73b16ba

File tree

2 files changed

+20
-2
lines changed

2 files changed

+20
-2
lines changed

lib/Sema/CSFix.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2247,7 +2247,7 @@ bool AddExplicitExistentialCoercion::isRequired(
22472247
// If result is an existential type and the base has `where` clauses
22482248
// associated with its associated types, the call needs a coercion.
22492249
if (erasedMemberTy->isExistentialType() &&
2250-
hasConstrainedAssociatedTypes(opened->second)) {
2250+
hasConstrainedAssociatedTypes(member)) {
22512251
RequiresCoercion = true;
22522252
return Action::Stop;
22532253
}
@@ -2273,6 +2273,19 @@ bool AddExplicitExistentialCoercion::isRequired(
22732273
}
22742274

22752275
private:
2276+
bool hasConstrainedAssociatedTypes(DependentMemberType *member) {
2277+
auto *assocType = member->getAssocType();
2278+
2279+
// If this member has associated type requirements, we are done.
2280+
if (assocType->getTrailingWhereClause())
2281+
return true;
2282+
2283+
if (auto *DMT = member->getBase()->getAs<DependentMemberType>())
2284+
return hasConstrainedAssociatedTypes(DMT);
2285+
2286+
return false;
2287+
}
2288+
22762289
bool hasConstrainedAssociatedTypes(ArchetypeType *archetypeTy) {
22772290
assert(archetypeTy);
22782291
for (auto *protocol : archetypeTy->getConformsTo()) {

test/Constraints/opened_existentials.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ func testTakeValueAndClosure(p: any P) {
213213

214214
protocol B {
215215
associatedtype C: P where C.A == Double
216+
associatedtype D: P
216217
}
217218

218219
func testExplicitCoercionRequirement(v: any B) {
@@ -222,7 +223,7 @@ func testExplicitCoercionRequirement(v: any B) {
222223
func getComplex<T: B>(_: T) -> ([(x: (a: T.C, b: Int), y: Int)], [Int: T.C]) { fatalError() }
223224

224225
func overloaded<T: B>(_: T) -> (x: Int, y: T.C) { fatalError() }
225-
// expected-note@-1 {{inferred result type '(x: Int, y: any P)' requires explicit coercion due to loss of generic requirements}} {{240:20-20=as (x: Int, y: any P)}}
226+
// expected-note@-1 {{inferred result type '(x: Int, y: any P)' requires explicit coercion due to loss of generic requirements}} {{241:20-20=as (x: Int, y: any P)}}
226227
func overloaded<T: P>(_: T) -> Int { 42 }
227228
// expected-note@-1 {{candidate requires that 'any B' conform to 'P' (requirement specified as 'T' : 'P')}}
228229

@@ -238,4 +239,8 @@ func testExplicitCoercionRequirement(v: any B) {
238239
_ = getComplex(v) as ([(x: (a: any P, b: Int), y: Int)], [Int : any P]) // Ok
239240

240241
_ = overloaded(v) // expected-error {{no exact matches in call to local function 'overloaded'}}
242+
243+
func getAssocNoRequirements<T: B>(_: T) -> (Int, [T.D]) { fatalError() }
244+
245+
_ = getAssocNoRequirements(v) // Ok, `D` doesn't have any requirements
241246
}

0 commit comments

Comments
 (0)