Skip to content

Commit ae2287d

Browse files
authored
Merge pull request #66551 from hamishknight/never-say-never
2 parents fc24471 + cca5a6e commit ae2287d

File tree

3 files changed

+112
-2
lines changed

3 files changed

+112
-2
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2174,11 +2174,26 @@ RValue RValueEmitter::visitEnumIsCaseExpr(EnumIsCaseExpr *E,
21742174

21752175
RValue RValueEmitter::visitSingleValueStmtExpr(SingleValueStmtExpr *E,
21762176
SGFContext C) {
2177+
auto emitStmt = [&]() {
2178+
SGF.emitStmt(E->getStmt());
2179+
2180+
// A switch of an uninhabited value gets emitted as an unreachable. In that
2181+
// case we need to emit a block to emit the rest of the expression code
2182+
// into. This block will be unreachable, so will be eliminated by the
2183+
// SILOptimizer. This is easier than handling unreachability throughout
2184+
// expression emission, as eventually SingleValueStmtExprs ought to be able
2185+
// to appear in arbitrary expression position. The rest of the emission
2186+
// will reference the uninitialized temporary variable, but that's fine
2187+
// because it'll be eliminated.
2188+
if (!SGF.B.hasValidInsertionPoint())
2189+
SGF.B.emitBlock(SGF.createBasicBlock());
2190+
};
2191+
21772192
// A void SingleValueStmtExpr either only has Void expression branches, or
21782193
// we've decided that it should have purely statement semantics. In either
21792194
// case, we can just emit the statement as-is, and produce the void rvalue.
21802195
if (E->getType()->isVoid()) {
2181-
SGF.emitStmt(E->getStmt());
2196+
emitStmt();
21822197
return SGF.emitEmptyTupleRValue(E, C);
21832198
}
21842199
auto &lowering = SGF.getTypeLowering(E->getType());
@@ -2201,7 +2216,7 @@ RValue RValueEmitter::visitSingleValueStmtExpr(SingleValueStmtExpr *E,
22012216
// Push the initialization for branches of the statement to initialize into.
22022217
SGF.SingleValueStmtInitStack.push_back(std::move(initInfo));
22032218
SWIFT_DEFER { SGF.SingleValueStmtInitStack.pop_back(); };
2204-
SGF.emitStmt(E->getStmt());
2219+
emitStmt();
22052220
return RValue(SGF, E, SGF.emitManagedRValueWithCleanup(resultAddr));
22062221
}
22072222

test/SILGen/if_expr.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,3 +500,11 @@ struct TestLValues {
500500
opt![keyPath: kp] = if .random() { 1 } else { throw Err() }
501501
}
502502
}
503+
504+
func testNever1() -> Never {
505+
if case let x = fatalError() { x } else { fatalError() }
506+
}
507+
508+
func testNever2() -> Never {
509+
if .random() { fatalError() } else { fatalError() }
510+
}

test/SILGen/switch_expr.swift

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,3 +616,90 @@ func exprPatternInClosure() {
616616
}
617617
}
618618
}
619+
620+
func testNeverSwitch1() {
621+
let x = switch fatalError() {}
622+
return x
623+
}
624+
625+
func testNeverSwitch2() -> Never {
626+
let x = switch fatalError() {
627+
case let x: x
628+
}
629+
return x
630+
}
631+
632+
func testNeverSwitch3() -> Int {
633+
let x = switch fatalError() {
634+
case fatalError(): 0
635+
case _ where .random(): 1
636+
default: 2
637+
}
638+
return x
639+
}
640+
641+
func testNeverSwitch4() {
642+
let x: Void
643+
x = switch fatalError() {}
644+
return x
645+
}
646+
647+
func testNeverSwitch5() -> Never {
648+
let x: Never
649+
x = switch fatalError() {
650+
case let x: x
651+
}
652+
return x
653+
}
654+
655+
func testNeverSwitch6() -> Int {
656+
let x: Int
657+
x = switch fatalError() {
658+
case fatalError(): 0
659+
case _ where .random(): 1
660+
default: 2
661+
}
662+
return x
663+
}
664+
665+
func testNeverSwitch7() {
666+
let _ = switch fatalError() {}
667+
let _ = switch fatalError() { case let x: x }
668+
let _ = switch fatalError() { default: "" }
669+
}
670+
671+
func testNeverSwitch8() {
672+
let _ = switch fatalError() { default: C() }
673+
}
674+
675+
func testNeverSwitch9() {
676+
let i = switch Bool.random() {
677+
case true:
678+
switch fatalError() {}
679+
case false:
680+
switch fatalError() {}
681+
}
682+
return i
683+
}
684+
685+
func testNeverSwitch10() -> Never {
686+
switch fatalError() {}
687+
}
688+
689+
func testNeverSwitch11() {
690+
return switch fatalError() {}
691+
}
692+
693+
func testNeverSwitch12() -> Never {
694+
return switch fatalError() { case let x: x }
695+
}
696+
697+
func testNeverSwitch13() {
698+
return switch fatalError() { case let x: x }
699+
}
700+
701+
extension Never {
702+
init(value: Self) {
703+
self = switch value { case let v: v }
704+
}
705+
}

0 commit comments

Comments
 (0)