Skip to content

Commit f08eec4

Browse files
committed
[CSSimplify] Start checking whether result type of a call needs a coercion
If there is going to be any loss of generic requirements in the result, a result of a call has to use explicit coercion.
1 parent fc1ed43 commit f08eec4

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11449,6 +11449,18 @@ ConstraintSystem::simplifyApplicableFnConstraint(
1144911449
result2, opened.second->getExistentialType(), opened.first,
1145011450
TypePosition::Covariant);
1145111451
}
11452+
11453+
// If result type has any erased existential types it requires explicit
11454+
// `as` coercion.
11455+
if (AddExplicitExistentialCoercion::isRequired(
11456+
*this, func2->getResult(), openedExistentials, locator)) {
11457+
if (!shouldAttemptFixes())
11458+
return SolutionKind::Error;
11459+
11460+
if (recordFix(AddExplicitExistentialCoercion::create(
11461+
*this, result2, getConstraintLocator(locator))))
11462+
return SolutionKind::Error;
11463+
}
1145211464
}
1145311465

1145411466
// The result types are equivalent.

test/Constraints/opened_existentials.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,32 @@ func testTakeValueAndClosure(p: any P) {
210210
// expected-note@-1{{did you mean to use 'as!' to force downcast?}}
211211
p)
212212
}
213+
214+
protocol B {
215+
associatedtype C: P where C.A == Double
216+
}
217+
218+
func testExplicitCoercionRequirement(v: any B) {
219+
func getC<T: B>(_: T) -> T.C { fatalError() }
220+
func getTuple<T: B>(_: T) -> (T, T.C) { fatalError() }
221+
func getNoError<T: B>(_: T) -> T.C.A { fatalError() }
222+
func getComplex<T: B>(_: T) -> ([(x: (a: T.C, b: Int), y: Int)], [Int: T.C]) { fatalError() }
223+
224+
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+
func overloaded<T: P>(_: T) -> Int { 42 }
227+
// expected-note@-1 {{candidate requires that 'any B' conform to 'P' (requirement specified as 'T' : 'P')}}
228+
229+
_ = getC(v) // expected-error {{inferred result type 'any P' requires explicit coercion due to loss of generic requirements}} {{14-14=as any P}}
230+
_ = getC(v) as any P // Ok
231+
232+
_ = getTuple(v) // expected-error {{inferred result type '(any B, any P)' requires explicit coercion due to loss of generic requirements}} {{18-18=as (any B, any P)}}
233+
_ = getTuple(v) as (any B, any P) // Ok
234+
235+
_ = getNoError(v) // Ok because T.C.A == Double
236+
237+
_ = getComplex(v) // expected-error {{inferred result type '([(x: (a: any P, b: Int), y: Int)], [Int : any P])' requires explicit coercion due to loss of generic requirements}} {{20-20=as ([(x: (a: any P, b: Int), y: Int)], [Int : any P])}}
238+
_ = getComplex(v) as ([(x: (a: any P, b: Int), y: Int)], [Int : any P]) // Ok
239+
240+
_ = overloaded(v) // expected-error {{no exact matches in call to local function 'overloaded'}}
241+
}

0 commit comments

Comments
 (0)