`getValue` -> `value`
`getValueOr` -> `value_or`
`hasValue` -> `has_value`
`map` -> `transform`
The old API will be deprecated in the rebranch.
To avoid merge conflicts, use the new API already in the main branch.
rdar://102362022
The reason why we are doing this is that we want move only addresses to be
checked by the move only address checker and not the move operator address
checker.
rdar://102056097
When property has attached property wrappers and is managed
by a type wrapper at the same time it has to be initialized in
a special way - instead of using backing property directly
(which is not actually a stored property in this scheme)
`assign_by_wrapper` instruction has to use a field of a
local `_storage` variable which represents underlying storage
before `$storage` property could be initialized.
Properties that are managed by a type wrapper have to be initialized
through a temporary `_storage` variable and only DI can tell us
when `_storage` is fully initialized, so we need to emit a
`assign_by_wrapper` instruction (with originator - type wrapper)
for every assignment to keep that and inject `$_storage.init`
as soon as all the managed properties are initialized.
Also renaming it to be UncheckedConversionComponent since it's a better name.
As a physical component, we'd run into problems in assignment statements.
The problem was that if we had something like:
```
SomeOtherComponent // first component
GetterSetterComponent
ABISafeConversionComponent // last component
```
When emitting the assignment, we always drill down through all but
the last component by calling `project()` on each one. Then on the last
component, we'd do the actual setting operation. But GetterSetterComponent
cannot be projected when the access is for writing.
So, to work around this I decided to model it as a TranslationComponent, because
those are specifically designed to be handled during an assignment by popping those
off the end of the component sequence, untranslating the value we're about to assign
as we go, until we hit the GetterSetterComponent.
By "untranslating" we're effectively putting Sendable back onto the set's argument
prior to calling set, because the underlying property's type still has `@Sendable`
on it (e.g., it's accessors still have that on its argument type). When
"translating" we're effectively taking Sendable off after reading it.
I think actually works really well and makes much more sense now.
resolves rdar://99619834
We needed a way to describe an ABI-safe cast of an address
representing an LValue to implement `@preconcurrency` and
its injection of casts during accesses of members.
This new AST node, `ABISafeConversionExpr` models what is
essentially an `unchecked_addr_cast` in SIL when accessing
the LVAlue.
As of now I simply implemented it and the verification of
the node for the concurrency needs to ensure that it's not
misused by accident. If it finds use outside of that,
feel free to update the verifier.
The generalized ActorIsolation is enough to represent everything that
ImplicitActorHopTarget can do, and we were mapping between the two way
too often, so collapse them.
I also updated the move function tests to show that this is working. As a nice
bonus, I was able to enable all of the tests also in a non-optimized stdlib.
When emitting a call to the getter for storage, emit the actor hop (and
hop back) as part of the call itself, rather than around the whole
initialization. This address a bug involving initialization with an
optional binding in an `if let`, where the hop-back would only be
performed on the non-nil branch.
Fixes rdar://96487805 / FB10562197
It used to be an accessor but that is not required because
SILDeclRef controls mangling which is the most imprortant
and could be used to emit the right reference.
This strategy is used to dispatch accesses to 'distributed' computed
property to distributed thunk accessor instead of a regular getter
when access happen outside actor isolation context.
This involved doing the following:
1. Update the move only checker to look for new patterns.
2. Teach emitSemanticStore to use a moveonlywrapper_to_copyable to store moveonly
values into memory. The various checkers will validate that this code is
correct.
3. When emitting an apply, always unwrap move only variables. In the
future, I am going to avoid this if a parameter is explicitly marked as also
being moveonly (e.x.: @moveOnly parameter or @noEscape argument).
4. Convert from moveOnly -> copyable on return inst automatically in SILGen.
5. Fix SILGenLValue emission so we emit an error diagnostic later rather than
crash. This is needed to keep SILGen emitting move only addresses (that is no
implicit copy address only lets) in a form that the move only checker then
will error upon. Without this change, SILGen crashes instead of emitting an
error diagnostic in the following test:
.//test/SILOptimizer/move_only_checker_addressonly_fail.swift
The resignID call within the initializer moved into DI, because an assignment to
the actorSystem, and thus initialization of the id, is no longer guaranteed to happen.
Thus, while we previously could model the resignation as a clean-up emitted on all
unwind paths in an initializer, now it's conditional, based on whether the id was
initialized. This is exactly what DI is designed to do, so we inject the resignation
call just before we call the identity's deinit.
The `@exclusivity(unchecked)` attribute can be used on variables to selectively disable exclusivity checking.
For completeness, also the `@exclusivity(checked)` variant is supported: it turns on exclusivity checking for specific variables if exclusivity enforcement is disabled by the command line option.
This new attribute is a missing implementation part of SE-0176 (https://github.com/apple/swift-evolution/blob/main/proposals/0176-enforce-exclusive-access-to-memory.md).
rdar://31121356
Don't crash when we're SILGen'ing accesses to globals in top-level code.
The address is found in the top-level main function because we generate
the initialization code directly. In the case when we're generating the
body of the implicit main function, the presence of the address does not
indicate that the variable is local.
Some globals, like static stored properties, are lazily initialized.
For situations where we do a direct access to that property,
we will first call a function that tries to initialize the var if needed,
before returning the address of the global to perform the direct access.
In this specific case, we were not on the right actor when invoking
that function.
fixes rdar://83411416
When trying to access a let-bound property of an actor across
a moudule boundary, the operation should be treated as async.
But, upon reaching SILGen, the compiler would crash when trying
to emit the needed hop, because the base of the element reference
was missing. This commit fixes that and adds regression coverage.
resolves rdar://81812013
Just for convenicence.
* Replace `llvm::isa_and_nonnull` with imported `isa_and_nonnull`
* Repalce some `EXPR && isa<T>(EXPR)` with `isa_and_nonnull<T>(EXPR)`
Change the code generation patterns for `async let` bindings to use an ABI based on the following
functions:
- `swift_asyncLet_begin`, which starts an `async let` child task, but which additionally
now associates the `async let` with a caller-owned buffer to receive the result of the task.
This is intended to allow the task to emplace its result in caller-owned memory, allowing the
child task to be deallocated after completion without invalidating the result buffer.
- `swift_asyncLet_get[_throwing]`, which replaces `swift_asyncLet_wait[_throwing]`. Instead of
returning a copy of the value, this entry point concerns itself with populating the local buffer.
If the buffer hasn't been populated, then it awaits completion of the task and emplaces the
result in the buffer; otherwise, it simply returns. The caller can then read the result out of
its owned memory. These entry points are intended to be used before every read from the
`async let` binding, after which point the local buffer is guaranteed to contain an initialized
value.
- `swift_asyncLet_finish`, which replaces `swift_asyncLet_end`. Unlike `_end`, this variant
is async and will suspend the parent task after cancelling the child to ensure it finishes
before cleaning up. The local buffer will also be deinitialized if necessary. This is intended
to be used on exit from an `async let` scope, to handle cleaning up the local buffer if necessary
as well as cancelling, awaiting, and deallocating the child task.
- `swift_asyncLet_consume[_throwing]`, which combines `get` and `finish`. This will await completion
of the task, leaving the result value in the result buffer (or propagating the error, if it
throws), while destroying and deallocating the child task. This is intended as an optimization
for reading `async let` variables that are read exactly once by their parent task.
To avoid an epoch break with existing swiftinterfaces and ABI clients, the old builtins and entry
points are kept intact for now, but SILGen now only generates code using the new interface.
This new interface fixes several issues with the old async let codegen, including use-after-free
crashes if the `async let` was never awaited, and the inability to read from an `async let` variable
more than once.
rdar://77855176
The fix is to implement part of SILGen that I asserted could not
happen because I couldn't formulate a situation where an access
to instance-isolated state would happen at the point in the code.
But, if a property wrapper's wrapped-value is global-actor
isolated, and is wrapping an actor instance, then it does happen.
Implementation details:
If the address is isolated to an actor instance, then we need the
base in order to perform a hop prior to starting the access,
so I just pass the base value through SILGen to the point it is
needed, since the base is available from all of the callers.
When accessing a static property isolated to a
global-actor, such as MainActor, a `hop_to_executor`
was not being emitted. This was caught by an assertion
I had left to catch such cases, but of course in release
builds this will lead to incorrect SIL, etc.
This issue revealed some other problems with how
the implementation was done for other kinds of
accesses starting from a static property, e.g.,
emitting a redundant hop for the same access.
This was fixed by modelling the actor-isolation
placed into a component as only being accessible
by consuming it from the component. This prevents
the emission of the hops more than once.
Thus, the regression test was updated to catch
unexpected hop_to_executor instructions.
Resolves rdar://78292384
Convenience initializers only contain assignments to self, but not initializations.
This case was not handled when deciding between a regular assignment and assign_by_wrapper.
https://bugs.swift.org/browse/SR-14675
rdar://78892507