Skip to content

Commit a5b7f8c

Browse files
authored
Merge pull request #4275 from milseman/3_0_noescape
[noescape-by-default] Improve diagnostics.
2 parents 98f1637 + f197f2a commit a5b7f8c

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3667,10 +3667,14 @@ static bool tryDiagnoseNonEscapingParameterToEscaping(Expr *expr, Type srcType,
36673667
!declRef->getType()->is<AnyFunctionType>())
36683668
return false;
36693669

3670-
// Must be from non-escaping function to escaping function
3670+
// Must be from non-escaping function to escaping function. For the
3671+
// destination type, we read through optionality to give better diagnostics in
3672+
// the event of an implicit promotion.
36713673
auto srcFT = srcType->getAs<AnyFunctionType>();
3672-
auto destFT = dstType->getAs<AnyFunctionType>();
3673-
if (!srcFT || !destFT || !srcFT->isNoEscape() || destFT->isNoEscape())
3674+
auto dstFT =
3675+
dstType->lookThroughAllAnyOptionalTypes()->getAs<AnyFunctionType>();
3676+
3677+
if (!srcFT || !dstFT || !srcFT->isNoEscape() || dstFT->isNoEscape())
36743678
return false;
36753679

36763680
// Pick a specific diagnostic for the specific use

test/attr/attr_escaping.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,18 @@ func callEscapingSuperGeneric(_ fn: () -> Sub) { // expected-note {{parameter 'f
9292
func callEscapingSuperGeneric<T: Sub>(_ fn: () -> T) { // expected-note {{parameter 'fn' is implicitly non-escaping}} {{45-45=@escaping }}
9393
takesEscapingSuperGeneric(fn) // expected-error {{passing non-escaping parameter 'fn' to function expecting an @escaping closure}}
9494
}
95+
96+
func testModuloOptionalness() {
97+
var iuoClosure: (() -> Void)! = nil
98+
func setIUOClosure(_ fn: () -> Void) { // expected-note {{parameter 'fn' is implicitly non-escaping}} {{28-28=@escaping }}
99+
iuoClosure = fn // expected-error{{assigning non-escaping parameter 'fn' to an @escaping closure}}
100+
}
101+
var iuoClosureExplicit: ImplicitlyUnwrappedOptional<() -> Void>
102+
func setExplicitIUOClosure(_ fn: () -> Void) { // expected-note {{parameter 'fn' is implicitly non-escaping}} {{36-36=@escaping }}
103+
iuoClosureExplicit = fn // expected-error{{assigning non-escaping parameter 'fn' to an @escaping closure}}
104+
}
105+
var deepOptionalClosure: (() -> Void)???
106+
func setDeepOptionalClosure(_ fn: () -> Void) { // expected-note {{parameter 'fn' is implicitly non-escaping}} {{37-37=@escaping }}
107+
deepOptionalClosure = fn // expected-error{{assigning non-escaping parameter 'fn' to an @escaping closure}}
108+
}
109+
}

0 commit comments

Comments
 (0)