Skip to content

Commit 8b8e002

Browse files
committed
[CSBindings] Allow hack that drops noEscape bit from function types to work during constraint generation phase
Previously bindings were inferred only during solving but now they are inferred as soon as something changes in the constraint graph, so the hack that dropped `noEscape` bit from function type when inferred for generic parameter should be allowed during constraint generation as well.
1 parent e5c686a commit 8b8e002

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,9 +1112,16 @@ PotentialBindings::inferFromRelational(Constraint *constraint) {
11121112
// whether the parameter is a function type and if so whether it
11131113
// should be allowed to escape. As a result we allow anything
11141114
// passed in to escape.
1115-
if (auto *fnTy = type->getAs<AnyFunctionType>())
1116-
if (isGenericParameter() && !CS.shouldAttemptFixes())
1115+
if (auto *fnTy = type->getAs<AnyFunctionType>()) {
1116+
// Since inference now happens during constraint generation,
1117+
// this hack should be allowed in both `Solving`
1118+
// (during non-diagnostic mode) and `ConstraintGeneration` phases.
1119+
if (isGenericParameter() &&
1120+
(!CS.shouldAttemptFixes() ||
1121+
CS.getPhase() == ConstraintSystemPhase::ConstraintGeneration)) {
11171122
type = fnTy->withExtInfo(fnTy->getExtInfo().withNoEscape(false));
1123+
}
1124+
}
11181125

11191126
// Check whether we can perform this binding.
11201127
if (auto boundType = checkTypeOfBinding(TypeVar, type)) {

test/Constraints/function.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,25 @@ func test_passing_nonescaping_to_escaping_function() {
223223
bar(handler) // expected-error {{passing non-escaping parameter 'handler' to function expecting an @escaping closure}}
224224
}
225225
}
226+
227+
func test_passing_noescape_function_ref_to_generic_parameter() {
228+
func cast<T, U>(_ t: T) -> U {
229+
return t as! U
230+
}
231+
232+
class A {
233+
required init(factory: () -> Self) {
234+
fatalError()
235+
}
236+
}
237+
238+
struct S {
239+
func converter() -> B { fatalError() }
240+
}
241+
242+
class B : A {
243+
class func test(value: S) {
244+
_ = self.init(factory: cast(value.converter)) // Ok
245+
}
246+
}
247+
}

0 commit comments

Comments
 (0)