Skip to content

Commit 6ef4b0d

Browse files
authored
[SILGen] Emit unreachable code diagnostic for single expression closures with implicit returns too (#33604)
* [SILGen] Emit unreachable code diagnostics for single expression closures with implicit returns too * [Test] Update diagnostic in test/SILGen/functions_uninhabited_param.swift
1 parent 4d875ee commit 6ef4b0d

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

lib/SILGen/SILGenStmt.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,23 @@ void StmtEmitter::visitBraceStmt(BraceStmt *S) {
292292
// If this is an implicit statement or expression, just skip over it,
293293
// don't emit a diagnostic here.
294294
if (auto *S = ESD.dyn_cast<Stmt*>()) {
295-
if (S->isImplicit()) continue;
295+
// Return statement in a single-expression closure or function is
296+
// implicit, but the result isn't. So, skip over return statements
297+
// that are implicit and either have no results or the result is
298+
// implicit. Otherwise, don't so we can emit unreachable code
299+
// diagnostics.
300+
if (S->isImplicit() && isa<ReturnStmt>(S)) {
301+
auto returnStmt = cast<ReturnStmt>(S);
302+
if (!returnStmt->hasResult()) {
303+
continue;
304+
}
305+
if (returnStmt->getResult()->isImplicit()) {
306+
continue;
307+
}
308+
}
309+
if (S->isImplicit() && !isa<ReturnStmt>(S)) {
310+
continue;
311+
}
296312
} else if (auto *E = ESD.dyn_cast<Expr*>()) {
297313
// Optional chaining expressions are wrapped in a structure like.
298314
//

test/SILGen/functions_uninhabited_param.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,21 @@ func foo(baz: Never) -> Int { // expected-note {{'baz' is uninhabited, so this f
99

1010
func bar(baz: Never) -> Int {} // ok
1111

12+
// SR-13432
13+
func map<T>(_ block: (Never) -> T) {}
14+
map { arg in // expected-note {{'arg' is uninhabited, so this function body can never be executed}}
15+
5 // expected-warning {{will never be executed}}
16+
}
17+
18+
map { arg in // expected-note {{'arg' is uninhabited, so this function body can never be executed}}
19+
return 5 // expected-warning {{will never be executed}}
20+
}
21+
1222
// We used to crash when emitting the closure below.
1323
enum E {
1424
static func f(_: E) {}
1525
}
1626

1727
let _: (E.Type) -> (E) -> () = { s in { e in s.f(e) } }
28+
// expected-warning@-1 {{will never be executed}}
29+
// expected-note@-2 {{'e' is uninhabited, so this function body can never be executed}}

0 commit comments

Comments
 (0)