Handle storing to a mutable property implemented as unsafeMutableAddress. In
SIL, the stored address comes from pointer_to_address. Recognize the addressor
pattern and handle the store as if it writes to a regular property of 'self'.
Required for UnsafePointer<~Escapable>.pointee.
When a non-Escapable value depends on the address of a trivial value, we use a
special computeAddressableRange analysis to compute the trivial value's
scope. Extend that analysis to include unreachable paths.
Fixes this pattern:
inlineStorage.span.withUnsafeBytes
where inlineStorage is a trivial type defined in the user module. This
does not reproduce directly with InlineArray, but it is a problem for
user modules that have their own trivial wrapper around an InlineArray.
Fixes rdar://161630684 (Incorrect diagnostic: lifetime-dependent value escapes its scope)
When the source of a lifetime dependency is a stack-allocated address, extend
the stack allocation to cover all dependent uses.
This avoids miscompilations for "addressable" dependencies which arise in code
built with -enable-experimental-feature AddressableTypes or
AddressableParameters. It is always an error for SILGen to emit the alloc_stack
in such cases. Nonetheless, we want to handle these unexpected cases gracefully
in SIL as a diagnostic error rather than allowing a miscompile.
Fixes rdar://159680262 ([nonescapable] diagnose dependence on a
temporary copy of a global array)
Add a diagnostic to catch addressable dependencies on a trivial values that have
been copied to a temporary stack location. SILGen should never copy the source
of an addressable dependency to a temporary stack location, but this diagnostic
catches such compiler bugs rather than allowing miscompilation.
Fixes rdar://159680262 ([nonescapable] diagnose dependence on a temporary copy
of a global array)
Add a fake use for dead-end blocks. This allows gatherKnownLifetimeUses to be
used for local liveness by considering an "unreachable" instruction to generate
liveness. This is important when liveness is used as a boundary within which
access scopes may be extended. Otherwise, we are unable to extend access scopes
into dead-end blocks.
Fixes rdar://154406790 (Lifetime-dependent variable 'X' escapes its
scope but only if actor/class is final)
switch_enum_addr was being treated like a store instruction, which killed
the local enum's liveness. This could result local variable analysis reporting a
shorter lifetime for the local.
This showed up as a missing exclusivity diagnostic because an access scope was
not fully extended across a dependent local variable of Optional type.
This prevents the following pattern from miscompiling. It should report an exclusivity violation:
var mutableView = getOpaqueOptionalView(holder: &holder)!
mutate(&holder)
mutableView.modify()
Fixes rdar://151231236 ([~Escapable] Missing 'overlapping acceses' error when
called from client code, but exact same code produces error in same module)
When extending an access scope over a coroutines, instead of simply
considering the lifetime of the coroutine scope, recurse through all
uses of yielded values. They may be copyable, non-Escapable values
that depend on the coroutine operand.
Fixes rdar://152693622 (Extend coroutines over copied yields)
Add support for diagnosing calls to closures that return a generic
non-Escapable result.
Closures do not yet model lifetime dependencies. The diagnostics have
a special case for handling nonescaple result with no lifetime
dependence, but it previously only handled direct results. This fix handles
cases like the following:
func callIndirectClosure<T>(f: () -> NE<T>) -> NE<T> {
f()
}
Fixes rdar://134318846 ([nonescapable] diagnose function types with nonescapable results)
* Move the mutating APIs into Context.swift, because SIL can only be mutated through a MutatingContext
* move the `baseOperand` and `base` properties from the instruction classes to the `MarkDependenceInstruction` protocol
* add `valueOrAddressOperand` and `valueOrAddress` in the `MarkDependenceInstruction` protocol
This utility is used by DependentAddressUseDefWalker which now conservatively
follows all possible uses. This could result in the same address being reached
multiple times during a def-use walk. Ensure that we don't infinitely recurse.
There is no small test case for this, but the fix is trivial and standard
practice for such walkers, and this is hit quickly in real usage, so there is no
danger of it regressing.
Fixes rdar://150403948 ([nonescapable] Infinite recursion compiler crash in
lifetime dependence checking)
Ensure that we always issue a diagnostic on error, but avoid emitting any notes that don't have source locations.
With implicit accessors and thunks, report the correct line number and indicate which accessor generates the error.
Always check for debug_value users.
Consistently handle access scopes across diagnostic analysis and diagnostic messages.
Fix a simple typo that results in infinite recursion on invalid code.
Fixes rdar://147470493 ([nonescapable] LifetimeDependenceInsertion: infinite
recursion in VariableUseDefWalker.walkup with immortal setter)
Add a case to LifetimeDependence.Scope to support dependencies on address-only
'let' variables. This comes up with C++ interop.
Fixes rdar://147500193 (Spurious lifetime error with closures)
Add support for returnValue phis (e.g. to return an Optional .some or .none).
Fixes rdar://149397018 (Wrapping non escapable in an Optional
(or any copy lifetime wrapper) is an escape)
This allows further extension of access scopes.
Fixes rdar://143992296 (Use of `RawSpan` in switch context causes compiler crash
in AddressOwnershipLiveRange)
Only return false if the visitor returns false. Clients were ignoring the
result.
If the BorrowingOperand does not create a borrow scope, call visitUnknownUse
instead.
Until we have complete lifetimes, to avoid breaking code that cannot handle dead
defs, consider a dead borrow scope to be an unknown use.
Functional changes:
Improved modeling of dependence on local variable scopes.
For nested modify->read accesses, only extend the read accesses.
Avoid making a read access dependent on an inout argument.
The following needs to be an error to prevent span storage from being modified:
@lifetime(owner)
foo(owner: inout Owner) -> Span {
owner.span
}
Improve usability of borrowing trivial values (UnsafePointer). Allow:
let span = Span(buffer.baseAddress)
Ignore access scopes for trivial values.
Structural changes:
Delete the LifetimeDependenceUseDefWalker.
Encapsulate all logic for variable introducers within the LifetimeDependenceInsertion pass. Once mark_dependence instructions are inserted, no subsequent pass needs to think about the "root" of a dependence.
Fixes: rdar://142451725 (Escape analysis fails with mutations)
The problem with `is_escaping_closure` was that it didn't consume its operand and therefore reference count checks were unreliable.
For example, copy-propagation could break it.
As this instruction was always used together with an immediately following `destroy_value` of the closure, it makes sense to combine both into a `destroy_not_escaped_closure`.
It
1. checks the reference count and returns true if it is 1
2. consumes and destroys the operand
Record a forwarding mark_dependence as a local access. This is necessary because
we now emit a mark_dependence for @out arguments, which will be the starting
point for diagnostics:
%out = alloc_stack
apply %f(%owned, %out) : $(Owner) -> @lifetime(borrow 0) @out View
%unused = mark_dependence [unresolved] %out on %owner
%dependentValue = load %out
This mark_dependence has no uses. Instead, it simply records the dependency of
the in-memory value on the owner. Consequently, simply walking the uses of
LifetimeDependence.dependentValue does fails to diagnose any escapes. Instead,
if the dependentValue is an address-type mark_dependence, treat it as a local
access to the address that it forwards. Then we find any reachable uses of that
local variable as a potential escape.
Fixes rdar://143040479
(Borrow diagnostics not triggered for @out return values)
Unlike @in, treat @in_guaranteed like a caller-side dependence
scope because there is not need to look for the end of the lifetime in the
current function.
Completely fixes rdar://142847915 (Crash during lifetime checking
while building new swift standard library `Span`-related features)
This encourages AccessPathWalker clients to handle enclosing mark_deps. In
some cases, it is necessary. The accessBaseWithScopes API now provides both
nested begin_access and mark_dependence.
Recognize dependence on the address of a trivial 'var' as an "access" dependence
instead of an "unknown" dependence. This allows the mark_dependence to be
resolved as "[nonescaping]".
This pass rewrites mark_depenendence to ignore "useless" borrow scopes. It was
also accidentally rewriting a dependence on a loaded value, which may redirect the
dependence to the access scope used to load that value. That access scope may be
narrower than the lifetime of the loaded value which could result in invalid
SIL. Do not rewrite this mark_dependence:
%access = begin_access [read] [unknown] %base
%load = load [trivial] %access
end_access %access
%adr = pointer_to_address
%md = mark_dependence [unresolved] %adr on %load
Fixes rdar://142424000 (Swift compiler crashes with Assertion failed
(isa<UnreachableInst>(block->getTerminator())))