Skip to content

Commit 1680382

Browse files
authored
Merge pull request swiftlang#73744 from jamieQ/diagnose-unreachable-opened-existentials
[SILGen]: diagnose unreachable opened existentials
2 parents 6637eb9 + 58166fc commit 1680382

File tree

2 files changed

+33
-15
lines changed

2 files changed

+33
-15
lines changed

lib/SILGen/SILGenStmt.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -356,21 +356,22 @@ void StmtEmitter::visitBraceStmt(BraceStmt *S) {
356356
continue;
357357
}
358358
} else if (auto *E = ESD.dyn_cast<Expr*>()) {
359-
// Optional chaining expressions are wrapped in a structure like.
360-
//
361-
// (optional_evaluation_expr implicit type='T?'
362-
// (call_expr type='T?'
363-
// (exprs...
364-
//
365-
// Walk through it to find out if the statement is actually implicit.
366-
if (auto *OEE = dyn_cast<OptionalEvaluationExpr>(E)) {
367-
if (auto *IIO = dyn_cast<InjectIntoOptionalExpr>(OEE->getSubExpr()))
368-
if (IIO->getSubExpr()->isImplicit()) continue;
369-
if (auto *C = dyn_cast<CallExpr>(OEE->getSubExpr()))
370-
if (C->isImplicit()) continue;
371-
} else if (E->isImplicit()) {
372-
// Ignore all other implicit expressions.
373-
continue;
359+
if (E->isImplicit()) {
360+
// Some expressions, like `OptionalEvaluationExpr` and
361+
// `OpenExistentialExpr`, are implicit but may contain non-implicit
362+
// children that should be diagnosed as unreachable. Check
363+
// descendants here to see if there is anything to diagnose.
364+
bool hasDiagnosableDescendant = false;
365+
E->forEachChildExpr([&](auto *childExpr) -> Expr * {
366+
if (!childExpr->isImplicit())
367+
hasDiagnosableDescendant = true;
368+
369+
return hasDiagnosableDescendant ? nullptr : childExpr;
370+
});
371+
372+
// If there's nothing to diagnose, ignore this expression.
373+
if (!hasDiagnosableDescendant)
374+
continue;
374375
}
375376
} else if (auto D = ESD.dyn_cast<Decl*>()) {
376377
// Local declarations aren't unreachable - only their usages can be. To

test/SILGen/unreachable_code.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,20 @@ func f_56075() -> Int {
159159
}
160160
func appendix() {} // no-warning
161161
}
162+
163+
// https://github.com/apple/swift/issues/73649
164+
func testUnreachableExistential() {
165+
protocol P {
166+
func run()
167+
}
168+
169+
func unreachableExistential(_ it: any P) -> Bool {
170+
return true
171+
it.run() // expected-warning {{code after 'return' will never be executed}}
172+
}
173+
174+
func unreachableOptionalChainedExistential(_ it: (any P)?) -> Bool {
175+
return false
176+
it?.run() // expected-warning {{code after 'return' will never be executed}}
177+
}
178+
}

0 commit comments

Comments
 (0)