-
Notifications
You must be signed in to change notification settings - Fork 10.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Concurrency] Introduce "ConcurrentValue" protocol and checking. #35264
[Concurrency] Introduce "ConcurrentValue" protocol and checking. #35264
Conversation
The ConcurrentValue protocol indicates when a particular type is safe to share in a concurrent context, e.g., that a copy of a given value can be safely used concurrently with the value.
By making ConcurrentValue a marker protocol, it no longer has any ABI impact whatsoever. Sink it down into the Standard Library so it's easier to use, even from code that isn't building with concurrency enabled.
db7a73d
to
913467d
Compare
When referring to an actor-isolated declaration from outside of the actor, ensure that the types involved conform to the `ConcurrentValue` protocol. Otherwise, produce a diagnostic stating that it is unsafe to pass such types across actors. Apply the same rule to local captures within concurrent code.
913467d
to
9b166c1
Compare
Introduce checking of ConcurrentValue conformances: - For structs, check that each stored property conforms to ConcurrentValue - For enums, check that each associated value conforms to ConcurrentValue - For classes, check that each stored property is immutable and conforms to ConcurrentValue Because all of the stored properties / associated values need to be visible for this check to work, limit ConcurrentValue conformances to be in the same source file as the type definition. This checking can be disabled by conforming to a new marker protocol, UnsafeConcurrentValue, that refines ConcurrentValue. UnsafeConcurrentValue otherwise his no specific meaning. This allows both "I know what I'm doing" for types that manage concurrent access themselves as well as enabling retroactive conformance, both of which are fundamentally unsafe but also quite necessary. The bulk of this change ended up being to the standard library, because all conformances of standard library types to the ConcurrentValue protocol needed to be sunk down into the standard library so they would benefit from the checking above. There were numerous little mistakes in the initial pass through the stsandard library types that have now been corrected.
@swift-ci please test |
@swift-ci build toolchain |
Build failed |
Build failed |
@swift-ci please smoke test |
@swift-ci please build toolchain |
@swift-ci please smoke test |
@swift-ci please build toolchain |
@swift-ci please smoke test |
@swift-ci please smoke test |
@swift-ci please smoke test |
@swift-ci please build toolchain |
1 similar comment
@swift-ci please build toolchain |
Merging to start staging this in, since everything is behind a flag anyway. |
Linux Toolchain (Ubuntu 16.04) Install command |
macOS Toolchain Install command |
This extension (introduced in swiftlang#35264) was placed in a file location where it wasn’t correctly guarded against mentioning Float16 on macOS/x86_64, so the generated .swiftinterface file included a reference to an unavailable declaration. (The dummy stand-in Float16 type that we currently use on Intel macOS.) Moving the declaration out of the “AnyHashable” section and into a file region that’s more suitable for it (i.e., enclosed in `#if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64))`) resolves the issue. rdar://76025365
Any progress on |
This pull request introduces the
ConcurrentValue
protocol, whichdescribes types for which it is safe to use different copies of a value
concurrently. Value-semantic types, immutable types, and types that
have internal synchronization can all conform to
ConcurrentValue
.A value of a non-
ConcurrentValue
type cannot be transferredinto a separate isolation domain. For example, they cannot be used
in a call to an actor-isolated function on a different actor. Similarly,
a local variable of non-
ConcurrentValue
type cannot be capturedin a closure that executes concurrently with the function in which
the local variable was declared. The actor-isolation and capture
checking rules have been adjusted accordingly.
Structural types are treated as conforming to
ConcurrentValue
incertain cases, although we don't form proper conformances just yet:
ConcurrentValue
.@concurrent
function types conform toConcurrentValue
;their parameter and result types must also conform to
ConcurrentValue
ConcurrentValue
if all element types conform toConcurrentValue
.Nominal types can declare conformance to
ConcurrentValue
explicitly.That conformance is checked to ensure that none of the state of the
type lacks a conformance to
ConcurrentValue
:ConcurrentValue
ConcurrentValue
to
ConcurrentValue
Because all of the stored properties / associated values need to be
visible for this check to work, limit
ConcurrentValue
conformances tobe in the same source file as the type definition.
This checking can be disabled by conforming to a new marker protocol,
UnsafeConcurrentValue
, that inheritsConcurrentValue
.UnsafeConcurrentValue
otherwise his no specific meaning. This allowsboth "I know what I'm doing" for types that manage concurrent access
themselves as well as enabling retroactive conformance, both of which
are fundamentally unsafe but also quite necessary.
Roll out
ConcurrentValue
conformances throughout the standard library,which both makes a lot of code "just work" and also provides out the
effectiveness of the checking and the model.
The checking for
ConcurrentValue
conformances is always enabled, sincethere is no code using this protocol. However, all of the other diagnostics
related to
ConcurrentValue
checking are staged in as warnings behind aflag
-Xfrontend -enable-experimental-concurrent-value-checking
.