`zeroInitializer` is blocking optimizations, but it is not needed because the closure of `Builtin.emplace` will initialize the memory anyway.
We only need to tell mandatory passes that this memory should be treated as initialized.
When the called closure throws an error, it needs to clean up the buffer.
This means that the buffer is uninitialized at this point.
We need an `end_lifetime` so that the move-only checker doesn't insert a wrong `destroy_addr` because it thinks that the buffer is initialized.
Fixes a mis-compile.
rdar://151461109
Forward the owning cleanup for the temporary buffer (if needed) instead of
creating a new cleanup, to avoid a double-free when both the initialization
cleanup and the value cleanup execute. Fixes rdar://147961840.
This is a value operation that can work just fine on lowered types,
so there's no need to carry along a formal type. Make the value/address
duality clearer, and enforce it in the verifier.
`Builtin.FixedArray<let N: Int, T: ~Copyable & ~Escapable>` has the layout of `N` elements of type `T` laid out
sequentially in memory (with the tail padding of every element occupied by the array). This provides a primitive
on which the standard library `Vector` type can be built.
This requires two major changes.
The first is that we need to teach SILGen that the isolation of an initializer
is essentially dynamic (as far as SILGen is concerned) --- that it needs to emit
code in order to get the isolation reference. To make this work, I needed to
refactor how we store the expected executor of a function so that it's not
always a constant value; instead, we'll need to emit code that DI will lower
properly. Fortunately, I can largely build on top of the work that Doug previously
did to support #isolation in these functions. The SIL we emit here around delegating
initializer calls is not ideal --- the breadcrumb hop ends up jumping to the
generic executor, and then DI actually emits the hop to the actor. This is a little
silly, but it's hard to eliminate without special-casing the self-rebinding, which
honestly we should consider rather than the weirdly global handling of that in
SILGen today. The optimizer should eliminate this hop pretty reliably, at least.
The second is that we need to teach DI to handle the pattern of code we get in
delegating initializers, where the builtin actually has to be passed the self var
rather than a class reference. This is because we don't *have* a class reference
that's consistently correct in these cases. This ended up being a fairly
straightforward generalization.
I also taught the hop_to_executor optimizer to skip over the initialization of
the default-actor header; there are a lot of simple cases where we still do emit
the prologue generic-executor hop, but at least the most trivial case is handled.
To do this better, we'd need to teach this bit of the optimizer that the properties
of self can be stored to in an initializer prior to the object having escaped, and
we don't have that information easily at hand, I think.
Fixes rdar://87485045.
Some requirement machine work
Rename requirement to Value
Rename more things to Value
Fix integer checking for requirement
some docs and parser changes
Minor fixes
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
A vestigial remnant of it was left behind after
06921cfe84 in order to avoid a reverse
condfail when building old swiftinterfaces that define
```swift
func _copy<T>(_ value: T) -> T {
#if $BuiltinCopy
Builtin.copy(value)
#else
value
#endif
}
```
If the language feature is removed, though, such interfaces should again
be buildable because the branch where the language feature isn't defined
should be expanded.
rdar://127516085
The copy operator has been implemented and doesn't use it. Remove
`Builtin.copy` and `_copy` as much as currently possible.
Source compatibility requires that `_copy` remain in the stdlib. It is
deprecated here and just uses the copy operator.
Handling old swiftinterfaces requires that `Builtin.copy` be defined.
Redefine it here as a passthrough--SILGen machinery will produce the
necessary copy_addr.
rdar://127502242
We've been building up this exponential explosion of task-creation
builtins because it's not currently possible to overload builtins.
As long as all of the operands are scalar, though, it's pretty easy
to peephole optional injections in IRGen, which means we can at
least just use a single builtin in SIL and then break it apart in
IRGen to decide which options to set.
I also eliminated the metadata argument, which can easily be recreated
from the substitutions. I also added proper verification for the builtin,
which required (1) getting `@Sendable` right more consistently and (2)
updating a bunch of tests checking for things that are not actually
valid, like passing a function that returns an Int directly.
First, and I really should've checked this, but global actors do not
require `shared` to return `Self`; adjust the logic to propagate the
right formal type to the erasure logic.
Second, handle attempts to erase the isolation of something isolated to
a distributed actor using the magic Actor conformance that Doug added.
This only works when the actor is local, but it shouldn't be difficult to
enforce that we only attempt to erase isolation what that's true --- we
need to prevent partial application of distributed actors, and we need to
disallow explicit isolated captures of distributed actors when we're not
currently isolated to it. Otherwise, it's not possible to get an
@isolated(any) function value with an isolation that isn't the current
function's isolation, which means it always has to be local.
Fixed rdar://123734019
In preparation for inserting mark_dependence instructions for lifetime
dependencies early, immediately after SILGen. That will simplify the
implementation of borrowed arguments.
Marking them unresolved is needed to make OSSA verification
conservative until lifetime dependence diagnostics runs.
The distributed-actor-as-actor conformance is synthesized by the
frontend, so make sure that when we access the API that exposes it
(asLocalActor), we be sure to mark the conformance as "used".
This is a very specific workaround for general problem with
compiler-synthesized conformances. SIL deserialization can bring in a
reference to a conformance late in the SIL pipeline, after the point at
which SILGen can create the conformance. We should be able to address
this systemically to remove the hack.
When an actual instance of a distributed actor is on the local node, it is
has the capabilities of `Actor`. This isn't expressible directly in the type
system, because not all `DistributedActor`s are `Actor`s, nor is the
opposite true.
Instead, provide an API `DistributedActor.asLocalActor` that can only
be executed when the distributed actor is known to be local (because
this API is not itself `distributed`), and produces an existential
`any Actor` referencing that actor. The resulting existential value
carries with it a special witness table that adapts any type
conforming to the DistributedActor protocol into a type that conforms
to the Actor protocol. It is "as if" one had written something like this:
extension DistributedActor: Actor { }
which, of course, is not permitted in the language. Nonetheless, we
lovingly craft such a witness table:
* The "type" being extended is represented as an extension context,
rather than as a type context. This hasn't been done before, all Swift
runtimes support it uniformly.
* A special witness is provided in the Distributed library to implement
the `Actor.unownedExecutor` operation. This witness back-deploys to the
Swift version were distributed actors were introduced (5.7). On Swift
5.9 runtimes (and newer), it will use
`DistributedActor.unownedExecutor` to support custom executors.
* The conformance of `Self: DistributedActor` is represented as a
conditional requirement, which gets satisfied by the witness table
that makes the type a `DistributedActor`. This makes the special
witness work.
* The witness table is *not* visible via any of the normal runtime
lookup tables, because doing so would allow any
`DistributedActor`-conforming type to conform to `Actor`, which would
break the safety model.
* The witness table is emitted on demand in any client that needs it.
In back-deployment configurations, there may be several witness tables
for the same concrete distributed actor conforming to `Actor`.
However, this duplication can only be observed under fairly extreme
circumstances (where one is opening the returned existential and
instantiating generic types with the distributed actor type as an
`Actor`, then performing dynamic type equivalence checks), and will
not be present with a new Swift runtime.
All of these tricks together mean that we need no runtime changes, and
`asLocalActor` back-deploys as far as distributed actors, allowing it's
use in `#isolation` and the async for...in loop.
The SILGen emission for `Builtin.createAsyncTask` performs an
existential erasure and assumed that `any Any.Type` has no protocols in
its ExistentialLayout, but it's now possible to have some there with
NoncopyableGenerics.
Concurrency runtime expects discarding task operation entrypoint
function not to have result type, but the current SILGen
implementation generates reabstraction thunk to convert `() -> Void`
to `() -> T` for the operation function.
Since the `T` is always `Void` for DiscardingTG, the mismatch of result
type expectation does not cause any problem on most platforms, but the
signature mismatch causes a problem on WebAssembly.
This patch introduces new builtin operations for creating discarding
task, which always takes `() -> Void` as the operation function type.
The dependent 'value' may be marked 'nonescaping', which guarantees that the
lifetime dependence is statically enforceable. In this case, the compiler
must be able to follow all values forwarded from the dependent 'value', and
recognize all final (non-forwarded, non-escaping) use points. This implies
that `findPointerEscape` is false. A diagnostic pass checks that the
incoming SIL to verify that these use points are all initially within the
'base' lifetime. Regular 'mark_dependence' semantics ensure that
optimizations cannot violate the lifetime dependence after diagnostics.
Previously, inverses were only accounted-for in inheritance clauses.
This batch of changes handles inverses appearing in other places, like:
- Protocol compositions
- `some ~Copyable`
- where clauses
with proper attribution of default requirements in their absence.
When the differentiating a function containing loops, we allocate a linear map context object on the heap. This context object may store non-trivial objects, such as closures, that need to be released explicitly. Fix the autodiff linear map context allocation builtins to correctly release such objects and not just free the memory they occupy.