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.
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.
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 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.
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.
There are a bunch of static `collectExistentialConformances` copied
around Sema and SILGen that are almost the same, save for whether they
want to permit missing conformances and/or check conditional
conformances.
This commit requestifies and combines all but one of these functions
into a `ModuleDecl::collectExistentialConformances`. The motivation for
this clean-up is another place that will need this procedure.
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.
patterns) in argument positions in reabstraction thunks.
Most of the difficulty in this work continues to center around
(1) trying to reuse as much code as possible between the parameter
and result paths and (2) propagating ownership information as
necessary throughout the code. I did my best to assert the preconditions
and postconditions here, but undoubtedly I'm missing cases. Some
simplicity here is still eluding me here.
This patch necessarily changes quite a bit of the code used in
non-variadic paths. I tried to avoid doing things that I knew would
be risky, like optimizing copies. I did fail in a few places: e.g.
we should now generate significantly better code when erasing to
Optional<Any>, just because the code was oddly poorly-factored before.
You can see the effect on the function_conversion test case.
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`).
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.
This was an annoying change, but mostly mechanical. The goal here is
to create parallel structure between the two paths so that it isn't
utterly confusing to share common CRTP paths between them. The renaming
of translate->process is just to make sure that all of the call sites
get correctly rewritten.
I'm trying to create more parallel structure between the param
and result reabstraction code so that, hopefully, some of the
basic explosion reasoning can be shared.
Moving the query implementation up to the AST library from SIL will allow
conveniences to be written on specific AST element classes. For instance, this
will allow `EnumDecl` to expose a convenience that enumerates element decls
that are available during lowering.
Also, improve naming and documentation for these queries.
Reformatting everything now that we have `llvm` namespaces. I've
separated this from the main commit to help manage merge-conflicts and
for making it a bit easier to read the mega-patch.
This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".
I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.