Through various means, it is possible for a synchronous actor-isolated
function to escape to another concurrency domain and be called from
outside the actor. The problem existed previously, but has become far
easier to trigger now that `@escaping` closures and local functions
can be actor-isolated.
Introduce runtime detection of such data races, where a synchronous
actor-isolated function ends up being called from the wrong executor.
Do this by emitting an executor check in actor-isolated synchronous
functions, where we query the executor in thread-local storage and
ensure that it is what we expect. If it isn't, the runtime complains.
The runtime's complaints can be controlled with the environment
variable `SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL`:
0 - disable checking
1 - warn when a data race is detected
2 - error and abort when a data race is detected
At an implementation level, this introduces a new concurrency runtime
entry point `_checkExpectedExecutor` that checks the given executor
(on which the function should always have been called) against the
executor on which is called (which is in thread-local storage). There
is a special carve-out here for `@MainActor` code, where we check
against the OS's notion of "main thread" as well, so that `@MainActor`
code can be called via (e.g.) the Dispatch library's
`DispatchQueue.main.async`.
The new SIL instruction `extract_executor` performs the lowering of an
actor down to its executor, which is implicit in the `hop_to_executor`
instruction. Extend the LowerHopToExecutor pass to perform said
lowering.
Plumb generic signatures through the codegen for invoking foreign APIs as async, so that we
correctly handle APIs declared on ObjC lightweight generic classes. rdar://74361267
- `Mangle::ASTMangler::mangleAutoDiffDerivativeFunction()` and `Mangle::ASTMangler::mangleAutoDiffLinearMap()` accept original function declarations and return a mangled name for a derivative function or linear map. This is called during SILGen and TBDGen.
- `Mangle::DifferentiationMangler` handles differentiation function mangling in the differentiation transform. This part is necessary because we need to perform demangling on the original function and remangle it as part of a differentiation function mangling tree in order to get the correct substitutions in the mangled derivative generic signature.
A mangled differentiation function name includes:
- The original function.
- The differentiation function kind.
- The parameter indices for differentiation.
- The result indices for differentiation.
- The derivative generic signature.
Bridging an async Swift method back to an ObjC completion-handler-based API requires
that the ObjC thunk spawn a task on which to execute the Swift async API and pass
its results back on to the completion handler.
An asyncHandler function is split into two functions:
1. The asyncHandler body function: it contains the body of the function, but is emitted as an async function.
2. The original function: it just contains
_runAsyncHandler(operation: asyncHandlerBodyFunction)
rdar://problem/71247879
Implement SIL generation for "async let" constructs, which involves:
1. Creating a child task future at the point of declaration of the "async let",
which runs the initializer in an async closure.
2. Entering a cleanup to destroy the child task.
3. Entering a cleanup to cancel the child task.
4. Waiting for the child task when any of the variables is reference.
5. Decomposing the result of the child task to write the results into the
appropriate variables.
Implements rdar://71123479.
Immediately before invoking the ObjC API, get the current continuation, capture it into a block to
pass as the completion handler, and then await the continuation, whose resume/error successors
serve as the semantic return/throw result of the call. This should complete the caller-side part
of SILGen; the completion handler block implementation is however still only a stub.
This attribute allows to define a pre-specialized entry point of a
generic function in a library.
The following definition provides a pre-specialized entry point for
`genericFunc(_:)` for the parameter type `Int` that clients of the
library can call.
```
@_specialize(exported: true, where T == Int)
public func genericFunc<T>(_ t: T) { ... }
```
Pre-specializations of internal `@inlinable` functions are allowed.
```
@usableFromInline
internal struct GenericThing<T> {
@_specialize(exported: true, where T == Int)
@inlinable
internal func genericMethod(_ t: T) {
}
}
```
There is syntax to pre-specialize a method from a different module.
```
import ModuleDefiningGenericFunc
@_specialize(exported: true, target: genericFunc(_:), where T == Double)
func prespecialize_genericFunc(_ t: T) { fatalError("dont call") }
```
Specially marked extensions allow for pre-specialization of internal
methods accross module boundries (respecting `@inlinable` and
`@usableFromInline`).
```
import ModuleDefiningGenericThing
public struct Something {}
@_specializeExtension
extension GenericThing {
@_specialize(exported: true, target: genericMethod(_:), where T == Something)
func prespecialize_genericMethod(_ t: T) { fatalError("dont call") }
}
```
rdar://64993425
Fill in the missing SILDeclRef cases in
`emitDelayedFunction`, and rename it to
`emitFunctionDefinition`. This will allow SIL to
be emitted only for a specific set of symbols.
Enum element constructors are used when an enum element satisfies
a protocol requirement. Instead of emitting them as part of
emitGlobalFunctionRef(), let's sink it down to getFunction() where
we do all other on-demand function body emission.
`@differentiable` attribute on protocol requirements and non-final class
members now produces derivative function entries in witness tables and vtables.
This enables `witness_method` and `class_method` differentiation.
Existing type-checking rules:
- Witness declarations of `@differentiable` protocol requirements must have a
`@differentiable` attribute with the same configuration (or a configuration
with superset parameter indices).
- Witness table derivative function entries are SILGen'd for `@differentiable`
witness declarations.
- Class vtable derivative function entries are SILGen'd for non-final
`@differentiable` class members.
- These derivative entries can be overridden or inherited, just like other
vtable entries.
Resolves TF-1212.
Generate SIL differentiability witnesses from `@differentiable` and
`@derivative` declaration attributes.
Add SILGen utilities for:
- Emiting differentiability witnesses.
- Creating derivative function thunks, which are used as entries in
differentiability witnesses.
When users register a custom derivative function, it is necessary to create a
thunk with the expected derivative type computed from the original function's
type. This is important for consistent typing and consistent differentiability
witness entry mangling.
See `SILGenModule::getOrCreateCustomDerivativeThunk` documentation for details.
Resolves TF-1138.
Now that CSApply transforms partial applications into closures,
we never see AST with partially-applied method calls. So all the
machinery for emitting curry thunks is now gone.
emitKeyPathComponentForDecl was only checking if the setter was
accessible from the current module, not the current function.
This failed when accessing an internal setter from a module
imported for testing.
emitKeyPathComponentForDecl was only checking if the setter was
accessible from the current module, not the current function.
This failed when accessing an internal setter from a module
imported for testing.
ProtocolConformanceRef already has an invalid state. Drop all of the
uses of Optional<ProtocolConformanceRef> and just use
ProtocolConformanceRef::forInvalid() to represent it. Mechanically
translate all of the callers and callsites to use this new
representation.
Teach SILGen to emit a separate SIL function to capture the
initialization of the backing storage type for a wrapped property
based on the wrapped value. This eliminates manual code expansion at
every use site.
This removes an intricate set of invariants that must be kept consistent
between Parse and SILGen. It will also make it easier to implement local
variables with 'lazy' and property wrappers in the future.
Assign separate SILProfiler instances to stored property initializers
and constructors.
Starting with rdar://39460313, coverage reporting for these constructs
was bundled up into a single SILProfiler uniqued by the NominalTypeDecl.
There are two problems with doing this.
First, the shared SILProfiler is given a fake name that can't be
demangled. That breaks Xcode's reports. Second, the relationship
between SILProfiler and SILFunction is supposed to be 1:1. Having a
shared SILProfiler muddies things a bit and requires extra bookkeeping.
rdar://47467864
Just as with conformances, we can detect that a delayed function
needs to be added to the queue from 'first principles' rather than
walking the ExternalDefinitions list.
This completely eliminates the ExternalDefinitions walk from SILGen,
which has several advantages:
- It fixes a source of quadratic behavior. In batch mode, type checking
produces a list of external definitions shared across all primary
files. Then, SILGen runs once per primary file, building a delayed
emission map every time.
- It allows SILGen to emit external definitions which only come into
existence as a result of lazy conformance checking. Previously,
anything that was added after SILGen performed its walk over the
external definitions list would not be emitted.
Instead of visiting all types in the ExternalDefinitions list and
queuing up their conformances, just emit conformances as needed
when they are first referenced.
- Don't forget to walk the top-level 'main' function
- Force _ObjectiveCBridgeable and _BridgedStoredNSError conformances
for types mentioned in apply instructions, existential erasure and
casts
- Only walk each unique CanType once, and skip non-ClangImporter
synthesized conformances completely
- Add a few missing cases
SILGen has the ability to lazily emit ClangImporter-synthesized
conformances. Sema builds a per-SourceFile list of "used" conformances,
which are forced to be emitted by SILGen. All other conformances can be
emitted lazily.
Some of these "used" conformances are in fact not referenced by SILGen
at all, but must exist for emission by IRGen so that they can be
referenced from type metadata accessors, as well as available at
runtime for the dynamic cast machinery.
To handle these cases, add an AST walk to SILGen which emits the types
of stored properties, the superclass of a class, and a few other
things that might not be referenced directly from SIL.
For now, this is all redundant because Sema forces the right
conformances anyway, but that's going to change soon.
This allows the conversion of the Windows `BOOL` type to be converted to
`Bool` implicitly. The implicit bridging allows for a more ergonomic
use of the native Windows APIs in Swift.
Due to the ambiguity between the Objective C `BOOL` and the Windows
`BOOL`, we must manually map the `BOOL` type to the appropriate type.
This required lifting the mapping entry for `ObjCBool` from the mapped
types XMACRO definition into the inline definition in the importer.
Take the opportunity to simplify the mapping code.
Adjust the standard library usage of the `BOOL` type which is now
eclipsed by the new `WindowsBool` type, preferring to use `Bool`
whenever possible.
Thanks to Jordan Rose for the suggestion to do this and a couple of
hints along the way.
To represent the abstracted interface of an opaque type, we need a generic signature that refines
the outer context generic signature with an additional generic parameter representing the underlying
type and its exposed constraints. Opaque types also need to be keyed by their originating decl, so
that we can treat values of the same opaque type as the same. When we check a FuncDecl with an
opaque type specified as its return type, create an OpaqueTypeDecl and associate it with the
originating decl. (A representation for *types* derived from the opaque decl will come next.)
This was partially implemented but the check looked at the lowered
types and not the AST types, and DynamicSelfType is erased at the
top level of a lowered type.
Also use the new mangling for reabstraction thunks with self, to
ensure we don't emit the same symbol with two different lowered
types.
Fixes <https://bugs.swift.org/browse/SR-10309>, <rdar://problem/49703441>.
Each call site will soon have to think about passing in the right expansion
instead of just assuming the default will be OK. But there are now only a
few call sites left, because most have been refactored to use convenience
APIs that pass in the right resilience expansion already.