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)
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)
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)
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"
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)
* rename `ScopedInstruction.endOperands` -> `scopeEndingOperands`
* let them behave the same way. For `load_borrow` there was a difference because `endOperands` didn't consider branches to re-borrow phis.
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.
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)
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)
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
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)
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)
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)
1. move embedded diagnostics out of the PerformanceDiagnostics pass. It was completely separated from the other logic in this pass, anyway.
2. rewrite it in swift
3. fix several bugs, that means: missed diagnostics, which led to IRGen crashes
* look at all methods in witness tables, including base protocols and associated conformances
* visit all functions in the call tree, including generic functions with class bound generic arguments
* handle all instructions, e.g. concurrency builtins
4. improve error messages by adding meaningful call-site information. For example:
* if the error is in a specialized function, report where the generic function is originally specialized with concrete types
* if the error is in a protocol witness method, report where the existential is created
For example:
```
protocol P: AnyObject {
func foo()
}
extension P {
func foo() {}
}
class C: P {}
let e: any P = C()
```
Such default methods are SILGen'd with a generic self argument. Therefore we need to specialize such witness methods, even if the conforming type is not generic.
rdar://145855851
If the method is a default witness methods (`selfType` != nil) it has generic self type.
In this case the generic self parameter is at depth 0 and the actual generic parameters of the substitution map are at depth + 1, e.g:
```
@convention(witness_method: P) <τ_0_0><τ_1_0 where τ_0_0 : GenClass<τ_1_0>.T>
^ ^
self params of substitution map at depth + 1
```
* move it from the SIL to the AST module (where it belongs)
* change the signature of `diagnose` from `diagnose(location, .some_error)` to `diagnose(.some_error, at: location)`
* add an overload to allow passing a `SIL.Location` directly to `diagnose`
* add a `Diagnostic : Error` utility struct which allows throwing a `Diagnostic`
Store specialize witness tables in a separate lookup table in the module. This allows that for a normal conformance there can exist the original _and_ a specialized witness table.
Also, add a boolean property `isSpecialized` to `WitnessTable` which indicates whether the witness table is specialized or not.