Right now it is basically a version of nonisolated beyond a few simple cases
like constructors/destructors where we are pretty sure we want to not support
this.
This is part of my bringup strategy for changing nonisolated/unspecified to be
caller isolation inheriting.
For a function to have complete lifetimes, the lifetime of every def in
the function which is backwards-reachable from a dead-end block must be
completed.
Previously, every def in every block which appears in the post-order of
the function's blocks is completed. This was not enough: defs in
"unreachable blocks" (i.e. those which aren't forwards-reachable from
the function entry) must be completed too, and such blocks do not appear
in the function's post-order.
Here, defs in unreachable blocks are be completed too. Such defs must
also be completed in relative post-order. To do this, roots for the
non-entry post-orders must be found.
rdar://141197164
Don't form a set of unreachable blocks, we only need to check whether
any given block is unreachable, which can be done via
`ReachableBlocks::isVisited`.
In preparation for only recording the defs once, replace the
GraphNodeWorklist of defs with a SetVector. Preserve the current
visitation order by creating a worklist of indices to be visited.
In terms of the test suite the only difference is that we allow for non-Sendable
types to be returned from nonisolated functions. This is safe due to the rules
of rbi. We do still error when we return non-Sendable functions across isolation
boundaries though.
The reason that I am doing this now is that I am implementing a prototype that
allows for nonisolated functions to inherit isolation from their caller. This
would have required me to implement support both in Sema for results and
arguments in SIL. Rather than implement results in Sema, I just finished the
work of transitioning the result checking out of Sema and into SIL. The actual
prototype will land in a subsequent change.
rdar://127477211
It replaces `DeclAttr::getUnavailable()` and `AvailableAttr::isUnavailable()`
as the designated way to query for the attribute that makes a decl unavailable.
Unfortunately, importing them as is results in ambiguous call sites.
E.g., std::vector::push_back has overloads for lvalue reference and
rvalue reference and we have no way to distinguish them at the call site
in Swift. To overcome this issue, functions with rvalue reference
parameters are imported with 'consuming:' argument labels.
Note that, in general, move only types and consuming is not properly
supported in Swift yet. We do not invoke the dtor for the moved-from
objects. This is a preexisting problem that can be observed with move
only types before this PR, so the fix will be done in a separate PR.
Fortunately, for most types, the moved-from objects do not require
additional cleanups.
rdar://125816354
When performance diagnostics were introduced, typed throws didn't exist
so it was not generally possible to have throws anywhere without
triggering performance diagnostics. As a short term hack, we disabled
checking of `throw` instructions and the basic blocks that terminate
in a `throw`.
Now that typed throws is available and can be used to eliminate
allocations with error handling, remove all of the hacks. We'll now
diagnose attempts to throw or catch existential values (e.g., the `any
Error` used for untyped throws), but typed throws are fine.
This just improves the ability to quickly triage bugs in SendNonSendable. It
used to be this way, but in the process of doing some refactoring, I moved the
logging too late by mistake.
I am doing this since I discovered that we are not printing certain errors as
early as we used to (due to the refactoring I did here), which makes it harder
to see the errors that we are emitting while processing individual instructions
and before we run the actual dataflow.
A nice side-effect of this is that it will make it easy to dump the error in the
debugger rather than having to wait until the point in the code where the normal
logging takes place.
A begin_apply token may be used by operands that do not end the coroutine:
mark_dependence.
We need an API that gives us only the coroutine-ending uses. This blocks
~Escapable accessors.
end_borrow is considered coroutine-ending even though it does not actually
terminate the coroutine.
We cannot simply ask isLifetimeEnding, because end_apply and abort_apply do not
end any lifetime.
during the MoveOnlyWrappedTypeEliminator pass.
Such instructions are only valid in RAW SIL. This pass generally removes marker
instructions that are only used for ownership diagnostics.
Fixes rdar://139450982 ([GH:#77451] Assert failure on
`extend_lifetime` verify with `onone-simplification` pass disabled)
The instruction only deallocates the box, it doesn't destroy its
contents. It's even less mutating than a `destroy_value`, which is
already regarded as non-mutating.
I am adding this instruction to express artificially that two non-Sendable
values should be part of the same region. It is meant to be used in cases where
due to unsafe code using Sendable, we stop propagating a non-Sendable dependency
that needs to be made in the same region of a use of said Sendable value. I
included an example in ./docs/SIL.rst of where this comes up with @out results
of continuations.
This problem comes up with the following example:
```swift
class A {
var description = ""
}
class B {
let a = A()
func b() {
let asdf = ""
Task { @MainActor in
a.description = asdf // Sending 'asdf' risks causing data races
}
}
}
```
The specific issue is that the closure we generate actually includes an
implicit(any) parameter at the SIL level which occurs after the callee operand
but before the captures. This caused the captured variable index from the AST
and the one we compute from the partial_apply to differ by 1. So we need to
subtract 1 in such a case. That is why we used to print 'asdf' instead of 'a'
above.
DISCUSSION: This shows an interesting difference between SIL applied arg indices
and AST indices. SIL applied arg indices would include the implicit(any)
parameter since it is a parameter in the SIL function type. In contrast, this
doesn't show up in the formal AST parameters or captures. To make it easier to
reason about this, I added a new API to ApplySite called
ApplySite::getASTAppliedArgIndex and added large comments to
getASTAppliedArgIndex and getAppliedArgIndex that explains the issue.
rdar://136593706
https://github.com/swiftlang/swift/issues/76648