The hack added here doesn't quite work right, so let's throw another on top.
ResultPlanner::expandInnerTupleOuterIndirect's narrow whole-tuple-into-opaque guard
to redirect to planSingleIntoIndirect checked only AllInnerResults.size() == 1,
so when the dispatcher reached the function recursively from expandParallelTuples
for an empty-tuple element, it mis-claimed the lone residual inner slot, which
actually belonged to a sibling tuple element, and the real later element then
tripped claimNext on an empty list.
If we just ensure the types are the same, we can avoid that.
resolves rdar://178736957
When passing a `(T) throws(E) -> R` closure to a parameter of type `(T)
throws -> U` where `U` is a generic type variable substituted to `R`
(which is a tuple — possibly `Void`), SILGen builds a reabstraction
thunk whose inner result is `@out R` and whose outer result is `@out T`
(opaque archetype that happens to substitute to `R`).
`ResultPlanner::expandInnerTupleOuterIndirect` dispatches between
"single-slot injection" (optional/existential) and "parallel tuple walk"
based on whether `outerSubstType` is a tuple — but that's the wrong
dimension. The abstraction pattern determines how the value is *passed*,
not the substituted type. When `outerOrigType` is opaque the outer is a
single `@out` slot regardless of the substituted type.
Routing to the parallel tuple walk caused:
- Empty-tuple case: the walk iterates 0 times, leaves the inner `@out`
slot unclaimed, and trips `assert(AllInnerResults.empty())` in
`ResultPlanner::plan`. (Previously crashed in IRGen's
`SyncCallEmission::setArgs` as `SmallVector grow_pod` before the
IR-level symptom was fixed.)
- Non-empty-tuple case: the walk tries to claim per-element slots that
don't exist and trips the `claimNext` assertion.
Detect the "inner has a single whole-tuple indirect slot, outer is
opaque" case in `expandInnerTupleOuterIndirect` and dispatch to
`planSingleIntoIndirect`. Gate on `AllInnerResults.size() == 1` so the
fix does not fire when the inner has per-element slots (where the
parallel walk's per-element claims remain correct).
A more principled fix dispatches the whole function on
`outerOrigType.isTuple()` and handles 1-to-N result-slot mappings — left
as a FIXME for a separate change.
Fixes https://github.com/swiftlang/swift/issues/77880. Fixes
https://github.com/swiftlang/swift/issues/88027.
Prevents situations when actor isolation ends up not being set
un-intentionally i.e. when cloning, specializating, or creating
thunks.
The thunks get `unspecified` isolation at the moment.
The `@export(interface)` and `@export(implementation)` attributes
SE-0497 are queried directly on AST nodes in several places within the
SIL pipeline. However, they don't persist when SIL functions are
serialized, meaning that clients of the original module might make
different assumptions about the availability of a given function's
definition.
Represent these attributes in a SIL function (as an optional
CodeGenerationModel), (de-)serialize them into the module, and add a
textual representation as SIL function attributes `[export_interface]`
and `[export_implementation]`.
This was already half done by adding the parameter to the arguments
but the flag to skip it while matching was missing.
Resolves: https://github.com/swiftlang/swift/issues/87537
Resolves: rdar://171274515
The TypeExpansionContext of a function that emits a reabstraction thunk
might differ from the TypeExpansionContext of the thunk itself.
This seems to cause a problem in one case at least, when emitting a
function conversion from () -> some P to () -> any P where we can see the
underlying type of the some P, we end up with a mismatch where the SIL type
of the value was unwrapped, but the lowering of the formal type in the context
of the thunk remains an opaque archetype.
One of the examples in the test was uncovered by binding inference changes
producing a different but equivalent constraint system solution, but the
remaining cases were already broken prior.
My change here is just a horrible workaround for this mismatch; the
representational problem needs to be addressed properly elsewhere.
Fixes rdar://172130660.
We were creating the JumpDests too early, so lowering a 'break' or 'continue'
statement would perform cleanups that were recorded while evaluating the
pack expansion expression, which would cause SIL verifier errors and
runtime crashes.
- Fixes https://github.com/swiftlang/swift/issues/78598
- Fixes rdar://131847933
NOTE: We are not performing any bitmasking at all now. This is so that we can
transition the code base/tests to expect Builtin.ImplicitActor instead
of Optional<any Actor>.
NOTE: The actual test changes are in the next commit. I did this to make it
easier to review the changes.
This should not have any user visible changes.
The intent for `@inline(always)` is to act as an optimization control.
The user can rely on inlining to happen or the compiler will emit an error
message.
Because function values can be dynamic (closures, protocol/class lookup)
this guarantee can only be upheld for direct function references.
In cases where the optimizer can resolve dynamic function values the
attribute shall be respected.
rdar://148608854
ResultConvention::Guaranteed will be used by borrow accessors when the storage type can be returned by value.
ResultConvention::GuaranteedAddress will be used by mutate accessors and borrow accessors when the storage type
cannot be returned by value.
- Calls to variadic-generic protocol requirements weren't applying
substitutions properly, so expansion-sensitive types in the callee
signature weren't pairing properly with their expansions in the
caller.
- emitPackTransform had an over-destroy if the transformation function
actually emitted into the temporary element directly.
- There were some MV ownership assertions that were wrong, which
revealed that the corresponding code really didn't handle consuming/
borrowing mismatches properly at all.
- We were completely mishandled consuming packs.
Fixes#81002, #80995, and #81600.
Specifically:
1. When we convert a function to nonisolated(nonsending), we need to
make sure that in the thunk we hop upon return since nonisolated(nonsending)
functions are assumed to preserve the caller's isolation.
2. When we convert a function from nonisolated(nonsending), we need to
make sure that in the thunk we hop onto the actor that we are passing in as the
isolated parameter of the nonisolated(nonsending) function. This ensures that
the nonisolated(nonsending) function can assume that it is already on its
isolated parameter's actor at function entry.
rdar://155905383
Also, I discovered that we don't apply nonisolated(nonsending) to
function types in the new mode. That's one for a different patch.
Fixes rdar://154401813 and rdar://154137740
The new macro aliasing uncovered a latent issue where we would attempt
to perform an optional-to-optional conversion on a type that is
non-optional though may be aliased to an optional. `CVaList` is
sometimes an optional pointer and would be interpreted as an optional
type which would fail the assertion in the optional-to-optional
conversion.
Consider an `@_alwaysEmitIntoClient` function and a custom derivative
defined
for it. Previously, such a combination resulted different errors under
different
circumstances.
Sometimes, there were linker errors due to missing derivative function
symbol -
these occurred when we tried to find the derivative in a module, while
it
should have been emitted into client's code (and it did not happen).
Sometimes, there were SIL verification failures like this:
```
SIL verification failed: internal/private function cannot be serialized or serializable: !F->isAnySerialized() || embedded
```
Linkage and serialization options for the derivative were not handled
properly,
and, instead of PublicNonABI linkage, we had Private one which is
unsupported
for serialization - but we need to serialize `@_alwaysEmitIntoClient`
functions
so the client's code is able to see them.
This patch resolves the issue and adds proper handling of custom
derivatives
of `@_alwaysEmitIntoClient` functions. Note that either both the
function and
its custom derivative or none of them should have
`@_alwaysEmitIntoClient`
attribute, mismatch in this attribute is not supported.
The following cases are handled (assume that in each case client's code
uses
the derivative).
1. Both the function and its derivative are defined in a single file in
one module.
2. Both the function and its derivative are defined in different files
which
are compiled to a single module.
3. The function is defined in one module, its derivative is defined in
another
module.
4. The function and the derivative are defined as members of a protocol
extension in two separate modules - one for the function and one for the
derivative. A struct conforming the protocol is defined in the third
module.
5. The function and the derivative are defined as members of a struct
extension in two separate modules - one for the function and one for the
derivative.
The changes allow to define derivatives for methods of `SIMD`.
Fixes#54445
<!--
If this pull request is targeting a release branch, please fill out the
following form:
https://github.com/swiftlang/.github/blob/main/PULL_REQUEST_TEMPLATE/release.md?plain=1
Otherwise, replace this comment with a description of your changes and
rationale. Provide links to external references/discussions if
appropriate.
If this pull request resolves any GitHub issues, link them like so:
Resolves <link to issue>, resolves <link to another issue>.
For more information about linking a pull request to an issue, see:
https://docs.github.com/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue
-->
<!--
Before merging this pull request, you must run the Swift continuous
integration tests.
For information about triggering CI builds via @swift-ci, see:
https://github.com/apple/swift/blob/main/docs/ContinuousIntegration.md#swift-ci
Thank you for your contribution to Swift!
-->
This ensures that when we generate the vtable thunk for a
nonisolated(nonsending) override (or vis-a-versa), we get the ABI correct. I
also added tests for all of the relevant cases for vtables that we check for
protocols.
rdar://151394209
Now that coroutine kind (and consequently ABI) for the accessors is
keyed off a SIL option, it's no longer possible to read whether a given
SILFunction arose from a read/modify coroutine just by checking its
coroutine kind. Regardless of ABI, read/modify coroutines may only
unwind (i.e. are only permitted not to "run to completion") if the
relevant experimental (soon to be deleted) feature is enabled.
This involved cleaning up and generalizing the work from
f245389bb3. I followed the same approach: hide the
implicit parameter while we run things through translateArgument and friends and
then put it back in manually.
As an additional benefit, I think I found a good place to put FunctionIsolation
onto lowered AnyFunctionTypes that will not cause cycles in the evaluator since
it is done in TypeLowering.
rdar://148785846
Specifically:
1. I made it so that thunks from caller -> concurrent properly ignore the
isolated parameter of the thunk when calling the concurrent function.
rdar://148112362
2. I made it so that thunks from concurrent -> caller properly create a
Optional<any Actor>.none and pass that into the caller function.
rdar://148112384
3. I made it so that in cases where we are assigning an @Sendable caller to a
non-sendable caller variable, we allow for the conversion as long as the
parameters/results are sendable as well.
rdar://148112532
4. I made it so that when we generate a thunk from @execution(caller) ->
@GlobalActor, we mangle in @GlobalActor into the thunk.
rdar://148112569
5. I discovered that due to the way we handle function conversion expr/decl ref
expr, we were emitted two thunks when we assigned a global @caller function to a
local @caller variable. The result is that we would first cast from @caller ->
@concurrent and then back to @caller. The result of this would be that the
@caller function would always be called on the global queue.
rdar://148112646
I also added a bunch of basic tests as well that showed that this behavior was
broken.
This just ensures that all thunks are verified right when they are created. This
is necessary since some thunks do not go through function post processing.
This would make sure that async function types marked as `@execution(caller)`
have correct isolation.
Also defines all of the possible conversions to and from `caller`
isolated function types.