Skip to content

Commit 87479ee

Browse files
committed
[SILGen]: Emit ignored loads of uninhabited lvalues to address DI edge cases
Previously we would crash on this pattern: ```swift let x: Never switch x {} ``` This appears to be due to the fact that the switch over the uninhabited value did not result in any instructions DI considers a use being produced. This change adds special handling of this case so that we now emit a load of the value so DI correctly diagnoses the use before init.
1 parent 1bf2e8f commit 87479ee

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7628,6 +7628,19 @@ void SILGenFunction::emitIgnoredExpr(Expr *E) {
76287628
if (auto *LE = dyn_cast<LoadExpr>(E)) {
76297629
LValue lv = emitLValue(LE->getSubExpr(), SGFAccessKind::IgnoredRead);
76307630

7631+
if (LE->getType()->isStructurallyUninhabited()) {
7632+
// If the lvalue is structurally uninhabited, we emit the load so that
7633+
// DI will see any uses before initialization. It should not be possible
7634+
// to ever really load such a value, so this should result in some sort
7635+
// of downstream error.
7636+
//
7637+
// Failure to do this in the past resulted in this bug:
7638+
// https://github.com/swiftlang/swift/issues/74478.
7639+
7640+
emitLoadOfLValue(E, std::move(lv), SGFContext::AllowImmediatePlusZero);
7641+
return;
7642+
}
7643+
76317644
// If loading from the lvalue is guaranteed to have no side effects, we
76327645
// don't need to drill into it.
76337646
if (lv.isLoadingPure())

test/SILOptimizer/definite_init_diagnostics.swift

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -enable-copy-propagation=requested-passes-only -emit-sil -primary-file %s -o /dev/null -verify
1+
// RUN: %target-swift-emit-sil -enable-copy-propagation=requested-passes-only -primary-file %s -o /dev/null -verify
22

33
import Swift
44

@@ -1667,3 +1667,52 @@ final class HasInitAccessors {
16671667
ints.append(0)
16681668
}
16691669
}
1670+
1671+
// https://github.com/swiftlang/swift/issues/74478
1672+
1673+
func structurallyUninhabitedLvalueSwitch() {
1674+
1675+
enum NeverEver {}
1676+
1677+
func gh_74478() {
1678+
let x: Never // expected-note {{constant defined here}}
1679+
switch x {} // expected-error {{constant 'x' used before being initialized}}
1680+
}
1681+
1682+
func nested_switch() {
1683+
let x: Never // expected-note {{constant defined here}}
1684+
let y: Never = switch () {
1685+
default:
1686+
switch x { // expected-error {{constant 'x' used before being initialized}}
1687+
default: x
1688+
}
1689+
}
1690+
_ = y
1691+
}
1692+
1693+
func customNever() {
1694+
let x: NeverEver // expected-note {{constant defined here}}
1695+
switch x {} // expected-error {{constant 'x' used before being initialized}}
1696+
}
1697+
1698+
func structurallyUninhabited() {
1699+
let x: (Int, Never, Bool) // expected-note {{constant defined here}}
1700+
switch x {} // expected-error {{constant 'x.0' used before being initialized}}
1701+
}
1702+
1703+
func structurallyUninhabited_variant1() {
1704+
let x: (Int, NeverEver, Bool) // expected-note {{constant defined here}}
1705+
switch x.2 { default: fatalError() } // expected-error {{constant 'x.2' used before being initialized}}
1706+
}
1707+
}
1708+
1709+
protocol P_74478 {
1710+
associatedtype A
1711+
}
1712+
1713+
extension P_74478 where A == (Int, (Bool, Never)) {
1714+
func structurallyUninhabitedGenericIndirection() {
1715+
let x: A // expected-note {{constant defined here}}
1716+
switch x {} // expected-error {{constant 'x.0' used before being initialized}}
1717+
}
1718+
}

0 commit comments

Comments
 (0)