Skip to content

Commit a97d416

Browse files
authored
Merge pull request #14084 from rudkx/partial-fix-rdar24097075
Fix one source of problems with allowing @NoEscape functions to escape.
2 parents bcc6c36 + 3aa8cfd commit a97d416

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,14 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
241241
});
242242
}
243243

244+
if (auto *AE = dyn_cast<CollectionExpr>(E)) {
245+
visitCollectionElements(AE, [&](unsigned argIndex, Expr *arg) {
246+
arg = lookThroughArgument(arg);
247+
if (auto *DRE = dyn_cast<DeclRefExpr>(arg))
248+
checkNoEscapeParameterUse(DRE, AE, OperandKind::Argument);
249+
});
250+
}
251+
244252
// Check decl refs in withoutActuallyEscaping blocks.
245253
if (auto MakeEsc = dyn_cast<MakeTemporarilyEscapableExpr>(E)) {
246254
if (auto DRE =
@@ -417,6 +425,13 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
417425
argExprVisitArguments(arg, fn);
418426
}
419427

428+
static void visitCollectionElements(CollectionExpr *collection,
429+
llvm::function_ref<void(unsigned, Expr*)> fn) {
430+
auto elts = collection->getElements();
431+
for (auto i : indices(elts))
432+
fn(i, elts[i]);
433+
}
434+
420435
static Expr *lookThroughArgument(Expr *arg) {
421436
while (1) {
422437
if (auto conv = dyn_cast<ImplicitConversionExpr>(arg))

test/attr/attr_noescape.swift

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,24 @@ func doesEscape(_ fn : @escaping () -> Int) {}
1010
func takesGenericClosure<T>(_ a : Int, _ fn : @noescape () -> T) {} // expected-warning{{@noescape is the default and is deprecated}} {{47-57=}}
1111

1212

13+
func takesArray(_ fns: [() -> Int]) {
14+
doesEscape(fns[0]) // Okay - array-of-function parameters are escaping
15+
}
16+
17+
func takesVariadic(_ fns: () -> Int...) {
18+
doesEscape(fns[0]) // Okay - variadic-of-function parameters are escaping
19+
}
20+
1321
func takesNoEscapeClosure(_ fn : () -> Int) {
1422
// expected-note@-1{{parameter 'fn' is implicitly non-escaping}} {{34-34=@escaping }}
1523
// expected-note@-2{{parameter 'fn' is implicitly non-escaping}} {{34-34=@escaping }}
1624
// expected-note@-3{{parameter 'fn' is implicitly non-escaping}} {{34-34=@escaping }}
1725
// expected-note@-4{{parameter 'fn' is implicitly non-escaping}} {{34-34=@escaping }}
26+
// expected-note@-5{{parameter 'fn' is implicitly non-escaping}} {{34-34=@escaping }}
27+
// expected-note@-6{{parameter 'fn' is implicitly non-escaping}} {{34-34=@escaping }}
28+
// expected-note@-7{{parameter 'fn' is implicitly non-escaping}} {{34-34=@escaping }}
29+
// expected-note@-8{{parameter 'fn' is implicitly non-escaping}} {{34-34=@escaping }}
30+
// expected-note@-9{{parameter 'fn' is implicitly non-escaping}} {{34-34=@escaping }}
1831
takesNoEscapeClosure { 4 } // ok
1932

2033
_ = fn() // ok
@@ -37,6 +50,13 @@ func takesNoEscapeClosure(_ fn : () -> Int) {
3750
doesEscape(fn) // expected-error {{passing non-escaping parameter 'fn' to function expecting an @escaping closure}}
3851
takesGenericClosure(4, fn) // ok
3952
takesGenericClosure(4) { fn() } // ok.
53+
54+
_ = [fn] // expected-error {{non-escaping parameter 'fn' may only be called}}
55+
_ = [doesEscape(fn)] // expected-error {{'(() -> Int) -> ()' is not convertible to '(@escaping () -> Int) -> ()'}}
56+
_ = [1 : fn] // expected-error {{non-escaping parameter 'fn' may only be called}}
57+
_ = [1 : doesEscape(fn)] // expected-error {{passing non-escaping parameter 'fn' to function expecting an @escaping closure}}
58+
_ = "\(doesEscape(fn))" // expected-error {{passing non-escaping parameter 'fn' to function expecting an @escaping closure}}
59+
_ = "\(takesArray([fn]))" // expected-error {{using non-escaping parameter 'fn' in a context expecting an @escaping closure}}
4060
}
4161

4262
class SomeClass {
@@ -340,4 +360,3 @@ func noescapeD_noescapeT(@noescape f: @noescape () -> Bool) {} // expected-error
340360

341361
func autoclosureD_noescapeT(@autoclosure f: @noescape () -> Bool) {} // expected-error {{attribute can only be applied to types, not declarations}}
342362
// expected-warning@-1{{@noescape is the default and is deprecated}} {{45-55=}}
343-

0 commit comments

Comments
 (0)