This fix enables exclusive access to a MutableSpan created from an UnsafeMutablePointer.
The compiler has a special case that allows MutableSpan to depend on a mutable
pointer *without* extending that pointer's access scope. That lets us implement
standard library code like this:
mutating public func extracting(droppingLast k: Int) -> Self {
//...
let newSpan = unsafe Self(_unchecked: _pointer, byteCount: newCount)
return unsafe _overrideLifetime(newSpan, mutating: &self)
Refine this special case so that is does not apply to inout parameters where the
programmer has an expectation that the unsafe pointer is not copied when being
passed as an argument. Now, we safely get an exclusivity violation when creating
two mutable spans from the same pointer field:
@lifetime(&self)
mutating func getSpan() -> MutableSpan<T> {
let span1 = makeMutableSpan(&self.pointer)
let span2 = makeMutableSpan(&self.pointer) // ERROR: overlapping access
return span1
}
If we don't fix this now, it will likely be source breaking in the future.
Fixes rdar://153745332 (Swift allows constructing two MutableSpans to
the same underlying pointer)
(cherry picked from commit 7c5d4b8b6d)
--- CCC ---
Explanation: Fix MutableSpan exclusive access to unsafe pointers This
fix enables exclusive access to a MutableSpan created from an
UnsafeMutablePointer.
Scope: Affects users of MutableSpan when initializing them from an unsafe pointer.
Radar/SR Issue: rdar://153745332 (Swift allows constructing two
MutableSpans to the same underlying pointer)
main PR: https://github.com/swiftlang/swift/pull/82450
Risk: Low. This only affects users of an API that requires lifetime
dependence. Without using an experimental feature, this only applies
to the initializers of Mutable[Raw]Span.
Testing: Added source-level unit tests
Reviewer: TBD
Allow a dependence on Void to be considered immortal. This is the ultimate
override in cases where no other code pattern is supported yet.
(cherry picked from commit 36d2b5bee4)
Consider an empty tuple to be a value introducer rather than a forwarding
instruction.
Fixes rdar://153978086 ([nonescapable] compiler crash with dependency on an
expression)
(cherry picked from commit bcc4a78c42)
When extending a coroutine, handle the end_borrow instruction used to end a
coroutine lifetime at a dead-end block.
Fixes rdar://153479358 (Compiler crash when force-unwrapping optional ~Copyable type)
(cherry picked from commit 5b5f370ce1)
It used to also set it for functions which are referenced from a global with a const/section attribute - even if not performance attribute was present in the whole module. This is unnecessary and can lead to worse code generation.
rdar://152665294
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)
(cherry picked from commit 227f8028e8)
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)
(cherry picked from commit 1d09c06ab1)
When de-serializing a function and this function allocates a class, the methods of the de-serialized vtable must be handled, too.
Fixes an IRGen crash
rdar://152311945
The function convention for the first argument is not identified as indirect-out.
This lets alias analysis assume that the memory pointed to by argument 0 cannot be written by the called function.
The problem is that subscripting a LazyFilterCollection (with the base index, e.g. `Int`) does not work as expected, because it returns the nth element of the base collection!
The fix is to implement the subscript "manually".
Fixes a mis-compile.
rdar://152160748
This prevents simplification and SILCombine passes to remove (alive) `mark_dependence_addr`.
The instruction is conceptually equivalent to
```
%v = load %addr
%d = mark_dependence %v on %base
store %d to %addr
```
Therefore the address operand has to be defined as writing to the address.
If the block is passed to another function - either as closure argument or as closure capture - it's "converted" to a swift closure with the help of a thunk. The thunk just calls the block.
If this is done with a non-escaping partial_apply, the block does not escape.
rdar://149095630
As SourceKit explicitly disables WMO, silence the diagnostic in this case (but leave it enabled for explicit non-WMO builds otherwise).
rdar://150596807
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)
(cherry picked from commit 4512927d2b)
Fix ownership issues with sequences of partial_apply's in AutoDiff closure specialization pass (#80662)
Each partial_apply consumes its arguments, therefore we should never release intermediate ones in the sequence of closures.
Fixes#78847
(cherry picked from commit 87ca0f8680)
Correctly generate dependency tracking for functions that return a non-Escapable
existential, such as:
func getMutableSpanWithOpaqueReturn(_ array: inout [Int]) -> any PAny & ~Copyable & ~Escapable
Previously, dependency insertion assumed that @out storage always initialized an
alloc_stack. But existentials are always boxed.
First, add a diagnostic to catch any missing dependency insertions now that
we're past the bootstrapping phase.
Then, generalize handling of dependency insertion to handle any access base as
long as it has a recognizable address source.
Fixes rdar://150388126 (Missing mark_dependence for opaque lifetime dependent
value)
(cherry picked from commit 9d8e8d3f05)
Array/ArraySlice/ContiguousArray have support for mutableSpan property.
These types are "optimized COW" types, we use compiler builtins begin_cow_mutation/end_cow_mutation to
optimize uniqueness checks. Since mutableSpan is a property and not a coroutine there is
no way to schedule the end_cow_mutaton operation at the end of the access.
This can lead to miscompiles in rare cases where we can end up using a stale storage buffer after a cow.
This PR inserts end_cow_mutation_addr to avoid this issue.
Note: We can end up with unnecessary end_cow_mutation_addr. But it is just a barrier to prevent invalid optimizations
and has no impact.
When a coroutine is extended because of a dependent lifetime, extend all scopes
that enclose that coroutine even if the coroutine itself has no lifetime
dependencies.
Fixes rdar://150275147 (Invalid SIL after lifetime dependence fixup involving
coroutines)
(cherry picked from commit 4a65be8074)
Add a note explaining that dependence on closure captures is not
supported. Otherwise, the diagnostics are very confusing:
"it depends on a closure capture; this is not yet supported"
(cherry picked from commit 83b0ce1098)
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.
(cherry picked from commit ec512864eb)
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)
(cherry picked from commit c891d8ade4)
For example:
```
%0 = load %1
copy_addr %1 to %2
```
->
```
%0 = load %1
store %0 to %2
```
This is important for MandatoryRedundantLoadElimination to be able to create statically initialized globals in the mandatory pipeline.
For example:
```
public struct MyStruct {
public static let r: Range<Int> = 1 ..< 3
}
```
gets a statically initialized global, even at Onone, with this improvement.
rdar://149356742
Briefly (April 2025), RawSpan._extracting, Span._extracting, and UTF8Span.span
returned a borrowed value that depended on a copied argument. Continue to
support those interfaces. The implementations were correct but needed an
explicit _overrideLifetime.
(cherry picked from commit 8a48cd979b)
Diagnose a scoped dependence on an argument that inherits its lifetime as an
error:
@lifetime(borrow arg)
func reborrowSpan<T>(_ arg: Span<T>) -> Span<T> { arg }
@lifetime(copy span)
public func testBorrowInheritedArg<T>(_ span: Span<T>) -> Span<T> {
reborrowSpan(span) // expected-error {{lifetime-dependent value escapes its scope}}
}
Fixes: rdar://146319009 ([nonescapable] enforce borrow constraint narrowing of inherited lifetime)
(cherry picked from commit 4f470a1d34)
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)
(cherry picked from commit 5831777407)
This adds support to handle unsafe addressors, which generate mark_dependence
instructions with an address base. This case does not arise with lifetime
dependencies. Nonetheless, the lifetime dependence diagnostics kick in to
attempt to promote the unsafe addressor's mark_dependence to noescape, so we
need to handle it.
rdar://149784450 (Compiler crash with non-escapable deinit dereferencing)
(cherry picked from commit 3b08592ed2)
Allow a dependency on a local [read] access scope to be transfered to the
caller's [modify] access.
Fixes rdar://149560133 (Invalid lifetime dependence error when
trying to return Span from an inout argument)
(cherry picked from commit 33fbe11bf8)