The reason why I am fixing this is that otherwise, we get a warning when one
creates an actor isolated closure and pass it into a task, e.x.:
```swift
@MainActor func test() {
// We would get a warning on the closure below saying that we are sending
// a closure that is MainActor isolated.
Task {
...
}
}
```
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)
Stored `let` properties of a struct, class, or actor permit
'inout' modification within the constructor body after they have been
initialized. Tentatively remove this rule, only allowing such `let`
properties to be initialized (assigned to) and not treated as `inout`.
Fixes rdar://127258363.
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
We do this by pushing the conversion down to the emission of the
closure expression, then teaching closure emission to apply the isolation
to the closure. Ideally, we combine the isolation along with the rest of
the conversion peephole, but if necessary, we make sure we emit the
isolation.
a closure expression, then don't actually do it. The long term plan is
to actually do this, which should just be a matter of taking some of the
code out of reabstraction thunk emission and using it in prolog/epilog/return
emission. In the short term, the goal is just to get the conversion
information down to the closure emitter so that we can see that we're
erasing into an `@isolated(any)` type and then actually erase the
closure's isolation properly instead of relying on type-based erasure,
which can't handle parameter/capture isolation correctly.
The main piece that's still missing here is support for closures;
they actually mostly work, but they infer the wrong isolation for
actor-isolated closures (it's not expressed in the type, so obviously
they're non-isolated), so it's not really functional. We also have
a significant problem where reabstraction thunks collide incorrectly
because we don't mangle (or represent!) formal isolation into
SILFunctionType; that's another follow-up. Otherwise, I think SILGen
is working.
This generates significantly better code directly out of SILGen, at
the cost of having to reimplement a little bit of the argument-emission
logic to handle default arguments. But it also neatly sidesteps the
problems we have with splitting tuple RValues when the tuple contains
a pack expansion, which will require some significant surgery to RValue
to fix. That, in turn, fixes rdar://121489308.
The thunk is a reabstraction thunk with a custom prolog that
has a runtime precondition check that makes sure that concurrent
environment where the thunk is run matches that of a global
actor associated with the thunked type.
Allow the use of typed throws for the main functions of `@main` types,
and thread the thrown error through to a new entry point in the library,
`_errorInMainTyped`, which is generic in the thrown error type.
Fixes rdar://121603043.
For `@preconcurrency` conformance witness thunks replace hop to
executor with a precondition to make sure that the thunk is always
called in the expected context.
Introduce SILGen support for reabstractions thunks that change the
error, between indirect and direct errors as well as conversions
amongst error types (e.g., from concrete to `any Error`).
Lower the thrown error type into the SIL function type. This requires
very little code because the thrown error type was already modeled as
a SILResultInfo, which carries type information. Note that this
lowering does not yet account for error types that need to passed
indirectly, but we will need to do so for (e.g.) using resilient error
types.
Teach a few places in SIL generation not to assume that thrown types
are always the existential error type, which primarily comes down to
ensuring that rethrow epilogues have the thrown type of the
corresponding function or closure.
Teach throw emission to implicitly box concrete thrown errors in the
error existential when needed to satisfy the throw destination. This
is a temporary solution that helps translate typed throws into untyped
throws, but it should be replaced by a better modeling within the AST
of the points at which thrown errors are converted.
The result-reabstraction code doesn't need to handle cleanups properly
during the planning phase because of course we don't have any values
yet. That is not true of argument reabstraction, so we need to make
sure that the recursive emitters can produce values with cleanups
so that we can collect and forward those cleanups correctly when
emitting the call.
As part of this, I've changed the code so that it should forward
outer addresses to inner address more consistently; it wouldn't
have done this before if we were breaking apart or assembling
a pack. I'm not sure I can directly test this without figuring
out a way to get SILGen to reabstract both sides of a function,
though.
I'm not sure this is really doing borrowed vs owned arguments
correctly, if e.g. we need to rebstract one component of a tuple
that's otherwise borrowed.