In the following code, SILGen emits a mark_uninitialized instruction
on the projected box value, diagnosing the reference to 'x' before
it has been fully initialized:
var x: Int
x = { _ = x; 123 }()
However, when the binding has an initial value, we don't emit the
mark_uninitialized instruction, and the closure ends up capturing the
uninitialized box:
var x: Int = { _ = x; 123 }() // undefined behavior
Unfortunately, we can't unconditionally emit a mark_uninitialized here,
because DI does not recognize all the code patterns that SILGen can emit
when initializing an address-only value in-place.
Instead, what we want to do is only enter the box into SILGenFunction::VarLocs
after the initial value expression has been emitted. This ensures that the
forward-referenced-capture diagnostics catch this.
Note that this only addresses the case of a local binding; we still
generate invalid code here if you forward-reference a global 'var' in
this manner. Fixing that requires some additional changes.
Fixes https://bugs.swift.org/browse/SR-14747, rdar://problem/77933460.
While 'defer' is implemented as a local function, it doesn't
behave as one. In particular, since SILGen runs it after
destroying all local bindings that appear after the 'defer'
definition, the body of a 'defer' cannot forward reference
captured bindings the way that local functions can.
Note that I had to remove a SILGen test case for an older,
related issue. The new diagnostic in Sema catches these cases
earlier.
Fixes rdar://problem/75088379.
We used to take all the captures of a local function and treat them all
as read and write usages of vars from an outer scope. Instead, let's
refactor the analysis to walk into local functions.
Instead, check them and their error handling right away.
In addition to fixing the crash in the radar, this also causes
us to emit unused variable warnings in functions containing
local functions.
Eventually, TC.definedFunctions should go away altogether.
Fixes <rdar://problem/53956342>.
The new analysis simply checks if the captured value has been defined
yet; instead of asserting if it hasn't, we can now emit a diagnostic
using the source location tracked in the capture list.
Fixes <https://bugs.swift.org/browse/SR-4812>, <rdar://problem/40600800>.