Skip to content

Commit add36f0

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 specially 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 add36f0

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
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+
// In the past we perhaps tried a bit too hard to avoid emitting a load,
7632+
// which led to this bug: https://github.com/swiftlang/swift/issues/74478.
7633+
if (LE->getType()->isStructurallyUninhabited()) {
7634+
// If the lvalue is structurally uninhabited, we emit the load so that
7635+
// DI will not miss potential uses before initialization. It should not
7636+
// be possible to ever really load such a value, so this should result
7637+
// in some form of downstream error.
7638+
7639+
// TODO: check if this seems like the right emission & params
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: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,3 +1667,30 @@ 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 customNever() {
1683+
let x: NeverEver // expected-note {{constant defined here}}
1684+
switch x {} // expected-error {{constant 'x' used before being initialized}}
1685+
}
1686+
1687+
func structurallyUninhabited() {
1688+
let x: (Int, Never, Bool) // expected-note {{constant defined here}}
1689+
switch x {} // expected-error {{constant 'x.0' used before being initialized}}
1690+
}
1691+
1692+
func structurallyUninhabited_variant1() {
1693+
let x: (Int, NeverEver, Bool) // expected-note {{constant defined here}}
1694+
switch x.2 { default: fatalError() } // expected-error {{constant 'x.2' used before being initialized}}
1695+
}
1696+
}

0 commit comments

Comments
 (0)