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.
When the BitwiseCopyable experimental feature is enabled, infer types to
conform to `_BitwiseCopyable`. The `_BitwiseCopyable` inference broadly
follows the approach taken to infer `Sendable`.
(1) Special types are conformed:
- function types if trivial
- metatypes
- builtin types if trivial
(2) TheTupleType is conditionally conformed.
(3) Nominal types are conformed if:
- non-public or public+fixed-layout
- enum or struct (non-class)
- every field conforms to _BitwiseCopyable
Additionally, check that nominal types which are explicitly conformed to
`_BitwiseCopyable` satisfy the latter two conditions of (3).
For a public, non-fixed-layout type to conform to `_BitwiseCopyable`,
the user must conform the type explicitly.
Finally, verify that conformances correspond to TypeLowering's notion of
triviality to the appropriate extent:
- if a type isn't trivial, it doesn't conform to `_BitwiseCopyable`
unless it's an archetype
- if a type is trivial, it conforms to `_BitwiseCopyable` unless some
field in its layout doesn't conform to `_BitwiseCopyable`, which is
only permitted under certain circumstances (the type has generic
parameters, the type is public non-fixed-layout, the type is a
reference but has ReferenceStorage::Unmanaged, the type is a
ModuleType, etc.)
Optionally, the dependency to the initialization of the global can be specified with a dependency token `depends_on <token>`.
This is usually a `builtin "once"` which calls the initializer for the global variable.
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.
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.
Add the thrown type into the AST representation of function types,
mapping from function type representations and declarations into the
appropriate thrown type. Add tests for serialization, printing, and
basic equivalence of function types that have thrown errors.
Parse typed throw specifiers as `throws(X)` in every place where there
are effects specified, and record the resulting thrown error type in
the AST except the type system. This includes:
* `FunctionTypeRepr`, for the parsed representation of types
* `AbstractFunctionDecl`, for various function-like declarations
* `ClosureExpr`, for closures
* `ArrowExpr`, for parsing of types within expression context
This also introduces some serialization logic for the thrown error
type of function-like declarations, along with an API to extract the
thrown interface type from one of those declarations, although right
now it will either be `Error` or empty.
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.
LLVM upstream removed the PtrToElt and AnyPtrToElt intrinsics in commit
4136e08f14ae9043b46bbe0a101e8609164d1be5.
LLVM upstream removed the PtrToArgument intrinsic in commit
253a52988fe37887ba1f7741271d602083fe7dd7.
Clang and LLVM added some new builtins.
LLVM added IITDescriptor::AArch64Svcount, which I set to not be
decodable since Swift can't represent those at the moment.
Also added handling for the WASM reference type builtins in the Clang
type converter.
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.
* [Executors][Distributed] custom executors for distributed actor
* harden ordering guarantees of synthesised fields
* the issue was that a non-default actor must implement the is remote check differently
* NonDefaultDistributedActor to complete support and remote flag handling
* invoke nonDefaultDistributedActorInitialize when necessary in SILGen
* refactor inline assertion into method
* cleanup
* [Executors][Distributed] Update module version for NonDefaultDistributedActor
* Minor docs cleanup
* we solved those fixme's
* add mangling test for non-def-dist-actor
`__shared` and `__owned` would always get mangled, even when they don't have any effect
on ABI, making it unnecessarily ABI-breaking to apply them to existing API to make
calling conventions explicit. Avoid this issue by only mangling them in cases where they
change the ABI from the default.
The variants are produced by SILGen when opaque values are enabled.
They are necessary because otherwise SILGen would produce
address_to_pointer of values.
They will be lowered by AddressLowering.
This is the start of the removal of the C++ implementation of libSyntax
in favor of the new Swift Parser and Swift Syntax libraries. Now that
the Swift Parser has switched the SwiftSyntaxParser library over to
being a thin wrapper around the Swift Parser, there is no longer any
reason we need to retain any libSyntax infrastructure in the swift
compiler.
As a first step, delete the infrastructure that builds
lib_InternalSwiftSyntaxParser and convert any scripts that mention
it to instead mention the static mirror libraries. The --swiftsyntax
build-script flag has been retained and will now just execute the
SwiftSyntax and Swift Parser builds with the just-built tools.
This is a dedicated instruction for incrementing a
profiler counter, which lowers to the
`llvm.instrprof.increment` intrinsic. This
replaces the builtin instruction that was
previously used, and ensures that its arguments
are statically known. This ensures that SIL
optimization passes do not invalidate the
instruction, fixing some code coverage cases in
`-O`.
rdar://39146527
By using the keyword instead of the function, we actually get a much simpler
implementation since we avoid all of the machinery of SILGenApply. Given that we
are going down that path, I am removing the old builtin implementation since it
is dead code.
The reason why I am removing this now is that in a subsequent commit, I want to
move all of the ownership checking passes to run /before/ mandatory inlining. I
originally placed the passes after mandatory inlining since the function version
of the move keyword was transparent and needing to be inlined before we could
process it. Since we use the keyword now, that is no longer an issue.
The new intrinsic, exposed via static functions on Task<T, Never> and
Task<T, Error> (rethrowing), begins an asynchronous context within a
synchronous caller's context. This is only available for use under the
task-to-thread concurrency model, and even then only under SPI.