Skip to content

Commit 774554a

Browse files
authored
Merge branch 'main' into wip-ktoso-changelog
2 parents cfa4199 + ab898c0 commit 774554a

File tree

112 files changed

+2514
-867
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+2514
-867
lines changed

CHANGELOG.md

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@
55
66
## Swift 6.0
77

8+
* Swift 6 comes with a new language mode that prevents the risk of data races
9+
at compile time. This guarantee is accomplished through _data isolation_; the
10+
compiler will validate that data passed over a boundary between concurrently
11+
executing code is either safe to reference concurrently, or mutually
12+
exclusive access to the value is enforced.
13+
14+
The data-race safety checks were previously available in Swift 5.10 through
15+
the `-strict-concurrency=complete` compiler flag. Complete concurrency
16+
checking in Swift 5.10 was overly restrictive, and Swift 6 removes many
17+
false-positive data-race warnings through better `Sendable` inference,
18+
new analysis that proves mutually exclusive access when passing values with
19+
non-`Sendable` type over isolation boundaries, and more.
20+
21+
You can enable the Swift 6 language mode using the `-swift-version 6`
22+
compiler flag.
23+
824
* [SE-0428][]:
925
Distributed actors now have the ability to support complete split server /
1026
client systems, thanks to the new `@Resolvable` macro and runtime changes.
@@ -50,7 +66,7 @@ And the module structure to support such applications looks like this:
5066
```
5167

5268
* [SE-0424][]:
53-
Serial executor gain a new customization point `checkIsolation()`, which can be
69+
Serial executor gains a new customization point `checkIsolation()`, which can be
5470
implemented by custom executor implementations in order to provide a last resort
5571
check before the isolation asserting APIs such as `Actor.assumeIsolated` or
5672
`assertIsolated` fail and crash.
@@ -59,6 +75,34 @@ And the module structure to support such applications looks like this:
5975
checking, and now even an actor which is "on a queue which is targeting
6076
another specific queue" can be properly detected using these APIs.
6177

78+
* [SE-0431][]:
79+
You can now require a function value to carry its actor isolation
80+
dynamically in a way that can be directly read by clients:
81+
82+
```swift
83+
func apply<R>(count: Int,
84+
operation: @isolated(any) async () -> R) async -> [R]
85+
where R: Sendable {
86+
// implementation
87+
}
88+
```
89+
90+
The isolation can read with the `.isolation` property, which has type
91+
`(any Actor)?`:
92+
93+
```swift
94+
let iso = operation.isolation
95+
```
96+
97+
This capability has been adopted by the task-creation APIs in the
98+
standard library. As a result, creating a task with an actor-isolated
99+
function will now synchronously enqueue the task on the actor, which
100+
can be used for transitive event-ordering guarantees if the actor
101+
guarantees that jobs will be run in the order they are enqueued, as
102+
`@MainActor` does. If the function is not explicitly isolated, Swift
103+
still retains the right to optimize enqueues for functions that actually
104+
start by doing work with different isolation from their formal isolation.
105+
62106
* [SE-0423][]:
63107
You can now use `@preconcurrency` attribute to replace static actor isolation
64108
checking with dynamic checks for witnesses of synchronous nonisolated protocol
@@ -99,6 +143,21 @@ And the module structure to support such applications looks like this:
99143
The dynamic actor isolation checks can be disabled using the flag
100144
`-disable-dynamic-actor-isolation`.
101145

146+
* [SE-0420][]:
147+
`async` functions can now explicitly inherit the isolation of their caller
148+
by declaring an `isolated` parameter with the default value of `#isolation`:
149+
150+
```swift
151+
func poll(isolation: isolated (any Actor)? = #isolation) async -> [Item] {
152+
// implementation
153+
}
154+
```
155+
156+
When the caller is actor-isolated, this allows it to pass isolated state
157+
to the function, which would otherwise have concurrency problems. The
158+
function may also be able to eliminate unwanted scheduling changes, such
159+
as when it can quickly return in a fast path without needing to suspend.
160+
102161
* [SE-0418][]:
103162

104163
The compiler would now automatically employ `Sendable` on functions
@@ -10496,19 +10555,23 @@ using the `.dynamicType` member to retrieve the type of an expression should mig
1049610555
[SE-0407]: https://github.com/apple/swift-evolution/blob/main/proposals/0407-member-macro-conformances.md
1049710556
[SE-0408]: https://github.com/apple/swift-evolution/blob/main/proposals/0408-pack-iteration.md
1049810557
[SE-0411]: https://github.com/apple/swift-evolution/blob/main/proposals/0411-isolated-default-values.md
10499-
[SE-0417]: https://github.com/apple/swift-evolution/blob/main/proposals/0417-task-executor-preference.md
1050010558
[SE-0412]: https://github.com/apple/swift-evolution/blob/main/proposals/0412-strict-concurrency-for-global-variables.md
1050110559
[SE-0413]: https://github.com/apple/swift-evolution/blob/main/proposals/0413-typed-throws.md
10560+
[SE-0414]: https://github.com/apple/swift-evolution/blob/main/proposals/0414-region-based-isolation.md
10561+
[SE-0417]: https://github.com/apple/swift-evolution/blob/main/proposals/0417-task-executor-preference.md
10562+
[SE-0418]: https://github.com/apple/swift-evolution/blob/main/proposals/0418-inferring-sendable-for-methods.md
10563+
[SE-0420]: https://github.com/apple/swift-evolution/blob/main/proposals/0420-inheritance-of-actor-isolation.md
1050210564
[SE-0422]: https://github.com/apple/swift-evolution/blob/main/proposals/0422-caller-side-default-argument-macro-expression.md
10565+
[SE-0423]: https://github.com/apple/swift-evolution/blob/main/proposals/0423-dynamic-actor-isolation.md
1050310566
[SE-0427]: https://github.com/apple/swift-evolution/blob/main/proposals/0427-noncopyable-generics.md
1050410567
[SE-0429]: https://github.com/apple/swift-evolution/blob/main/proposals/0429-partial-consumption.md
1050510568
[SE-0432]: https://github.com/apple/swift-evolution/blob/main/proposals/0432-noncopyable-switch.md
10506-
[SE-0414]: https://github.com/apple/swift-evolution/blob/main/proposals/0414-region-based-isolation.md
1050710569
[SE-0430]: https://github.com/apple/swift-evolution/blob/main/proposals/0430-transferring-parameters-and-results.md
1050810570
[SE-0418]: https://github.com/apple/swift-evolution/blob/main/proposals/0418-inferring-sendable-for-methods.md
1050910571
[SE-0423]: https://github.com/apple/swift-evolution/blob/main/proposals/0423-dynamic-actor-isolation.md
1051010572
[SE-0424]: https://github.com/apple/swift-evolution/blob/main/proposals/0424-custom-isolation-checking-for-serialexecutor.md
1051110573
[SE-0428]: https://github.com/apple/swift-evolution/blob/main/proposals/0428-resolve-distributed-actor-protocols.md
10574+
[SE-0431]: https://github.com/apple/swift-evolution/blob/main/proposals/0431-isolated-any-functions.md
1051210575
[#64927]: <https://github.com/apple/swift/issues/64927>
1051310576
[#42697]: <https://github.com/apple/swift/issues/42697>
1051410577
[#42728]: <https://github.com/apple/swift/issues/42728>

SwiftCompilerSources/Sources/Optimizer/PassManager/Context.swift

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,34 @@ extension Type {
433433
// Builder initialization
434434
//===----------------------------------------------------------------------===//
435435

436+
private extension Instruction {
437+
/// Returns self, unless self is a meta instruction, in which case the next
438+
/// non-meta instruction is returned. Returns nil if there are no non-meta
439+
/// instructions in the basic block.
440+
var nextNonMetaInstruction: Instruction? {
441+
for inst in InstructionList(first: self) where !(inst is MetaInstruction) {
442+
return inst
443+
}
444+
return nil
445+
}
446+
447+
/// Returns the next interesting location. As it is impossible to set a
448+
/// breakpoint on a meta instruction, those are skipped.
449+
/// However, we don't want to take a location with different inlining
450+
/// information than this instruction, so in that case, we will return the
451+
/// location of the meta instruction. If the meta instruction is the only
452+
/// instruction in the basic block, we also take its location.
453+
var locationOfNextNonMetaInstruction: Location {
454+
let location = self.location
455+
guard !location.isInlined,
456+
let nextLocation = nextNonMetaInstruction?.location,
457+
!nextLocation.isInlined else {
458+
return location
459+
}
460+
return nextLocation
461+
}
462+
}
463+
436464
extension Builder {
437465
/// Creates a builder which inserts _before_ `insPnt`, using a custom `location`.
438466
init(before insPnt: Instruction, location: Location, _ context: some MutatingContext) {
@@ -441,8 +469,23 @@ extension Builder {
441469
context.notifyInstructionChanged, context._bridged.asNotificationHandler())
442470
}
443471

444-
/// Creates a builder which inserts _before_ `insPnt`, using the location of `insPnt`.
472+
/// Creates a builder which inserts before `insPnt`, using `insPnt`'s next
473+
/// non-meta instruction's location.
474+
/// This function should be used when moving code to an unknown insert point,
475+
/// when we want to inherit the location of the closest non-meta instruction.
476+
/// For replacing an existing meta instruction with another, use
477+
/// ``Builder.init(replacing:_:)``.
445478
init(before insPnt: Instruction, _ context: some MutatingContext) {
479+
context.verifyIsTransforming(function: insPnt.parentFunction)
480+
self.init(insertAt: .before(insPnt),
481+
location: insPnt.locationOfNextNonMetaInstruction,
482+
context.notifyInstructionChanged, context._bridged.asNotificationHandler())
483+
}
484+
485+
/// Creates a builder which inserts _before_ `insPnt`, using the exact location of `insPnt`,
486+
/// for the purpose of replacing that meta instruction with an equivalent instruction.
487+
/// This function does not delete `insPnt`.
488+
init(replacing insPnt: MetaInstruction, _ context: some MutatingContext) {
446489
context.verifyIsTransforming(function: insPnt.parentFunction)
447490
self.init(insertAt: .before(insPnt), location: insPnt.location,
448491
context.notifyInstructionChanged, context._bridged.asNotificationHandler())
@@ -460,10 +503,10 @@ extension Builder {
460503
}
461504
}
462505

463-
/// Creates a builder which inserts _after_ `insPnt`, using the location of `insPnt`.
506+
/// Creates a builder which inserts _after_ `insPnt`, using `insPnt`'s next
507+
/// non-meta instruction's location.
464508
init(after insPnt: Instruction, _ context: some MutatingContext) {
465-
context.verifyIsTransforming(function: insPnt.parentFunction)
466-
self.init(after: insPnt, location: insPnt.location, context)
509+
self.init(after: insPnt, location: insPnt.locationOfNextNonMetaInstruction, context)
467510
}
468511

469512
/// Creates a builder which inserts at the end of `block`, using a custom `location`.
@@ -482,11 +525,12 @@ extension Builder {
482525
}
483526

484527
/// Creates a builder which inserts at the begin of `block`, using the location of the first
485-
/// instruction of `block`.
528+
/// non-meta instruction of `block`.
486529
init(atBeginOf block: BasicBlock, _ context: some MutatingContext) {
487530
context.verifyIsTransforming(function: block.parentFunction)
488531
let firstInst = block.instructions.first!
489-
self.init(insertAt: .before(firstInst), location: firstInst.location,
532+
self.init(insertAt: .before(firstInst),
533+
location: firstInst.locationOfNextNonMetaInstruction,
490534
context.notifyInstructionChanged, context._bridged.asNotificationHandler())
491535
}
492536

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,16 @@ public protocol DebugVariableInstruction : VarDeclInstruction {
418418
var debugVariable: DebugVariable { get }
419419
}
420420

421-
final public class DebugValueInst : Instruction, UnaryInstruction, DebugVariableInstruction {
421+
/// A meta instruction is an instruction whose location is not interesting as
422+
/// it is impossible to set a breakpoint on it.
423+
/// That could be because the instruction does not generate code (such as
424+
/// `debug_value`), or because the generated code would be in the prologue
425+
/// (`alloc_stack`).
426+
/// When we are moving code onto an unknown instruction (such as the start of a
427+
/// basic block), we want to ignore any meta instruction that might be there.
428+
public protocol MetaInstruction: Instruction {}
429+
430+
final public class DebugValueInst : Instruction, UnaryInstruction, DebugVariableInstruction, MetaInstruction {
422431
public var varDecl: VarDecl? {
423432
VarDecl(bridged: bridged.DebugValue_getDecl())
424433
}
@@ -1127,7 +1136,7 @@ final public class InitBlockStorageHeaderInst: SingleValueInstruction {}
11271136

11281137
public protocol Allocation : SingleValueInstruction { }
11291138

1130-
final public class AllocStackInst : SingleValueInstruction, Allocation, DebugVariableInstruction {
1139+
final public class AllocStackInst : SingleValueInstruction, Allocation, DebugVariableInstruction, MetaInstruction {
11311140
public var hasDynamicLifetime: Bool { bridged.AllocStackInst_hasDynamicLifetime() }
11321141

11331142
public var varDecl: VarDecl? {

SwiftCompilerSources/Sources/SIL/Location.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public struct Location: Equatable, CustomStringConvertible {
3030

3131
public var hasValidLineNumber: Bool { bridged.hasValidLineNumber() }
3232
public var isAutoGenerated: Bool { bridged.isAutoGenerated() }
33+
public var isInlined: Bool { bridged.isInlined() }
3334

3435
public var isDebugSteppable: Bool { hasValidLineNumber && !isAutoGenerated }
3536

cmake/modules/DarwinSDKs.cmake

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,5 @@
1-
option(SWIFT_ENABLE_IOS32
2-
"Build 32-bit variants of iOS"
3-
TRUE)
4-
5-
if(SWIFT_ENABLE_IOS32)
6-
set(SUPPORTED_IOS_ARCHS "arm64;arm64e")
7-
set(SUPPORTED_IOS_SIMULATOR_ARCHS "x86_64;arm64")
8-
else()
91
set(SUPPORTED_IOS_ARCHS "arm64;arm64e")
102
set(SUPPORTED_IOS_SIMULATOR_ARCHS "x86_64;arm64")
11-
endif()
12-
133
set(SUPPORTED_TVOS_ARCHS "arm64")
144
set(SUPPORTED_TVOS_SIMULATOR_ARCHS "x86_64;arm64")
155
set(SUPPORTED_WATCHOS_ARCHS "armv7k;arm64_32")

docs/ReferenceGuides/UnderscoredAttributes.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -955,12 +955,16 @@ the memory of the annotated type:
955955
threads, writes don't overlap with reads or writes coming from the same
956956
thread, and that the pointer is not used after the value is moved or
957957
consumed.
958-
- When the value is moved, a bitwise copy of its memory is performed to the new
959-
address of the value in its new owner. As currently implemented, raw storage
960-
types are not suitable for storing values which are not bitwise-movable, such
961-
as nontrivial C++ types, Objective-C weak references, and data structures
962-
such as `pthread_mutex_t` which are implemented in C as always requiring a
963-
fixed address.
958+
- By default, when the value is moved a bitwise copy of its memory is performed
959+
to the new address of the value in its new owner. This makes it unsuitable to
960+
store not bitwise-movable types such as nontrivial C++ types, Objective-C weak
961+
references, and data structures such as `pthread_mutex_t` which are
962+
implemented in C as always requiring a fixed address. However, you can provide
963+
`movesAsLike` to the `like:` version of this attribute to enforce that moving
964+
the value will defer its move semantics to the type it's like. This makes it
965+
suitable for storing such values that are not bitwise-movable. Note that the
966+
raw storage for this variant must always be properly initialized after
967+
initialization because foreign moves will assume an initialized state.
964968

965969
Using the `@_rawLayout` attribute will suppress the annotated type from
966970
being implicitly `Sendable`. If the type is safe to access across threads, it
@@ -987,6 +991,11 @@ forms are currently accepted:
987991
- `@_rawLayout(likeArrayOf: T, count: N)` specifies the type's size should be
988992
`MemoryLayout<T>.stride * N` and alignment should match `T`'s, like an
989993
array of N contiguous elements of `T` in memory.
994+
- `@_rawLayout(like: T, movesAsLike)` specifies the type's size and alignment
995+
should be equal to the type `T`'s. It also guarantees that moving a value of
996+
this raw layout type will have the same move semantics as the type it's like.
997+
This is important for things like ObjC weak references and non-trivial move
998+
constructors in C++.
990999

9911000
A notable difference between `@_rawLayout(like: T)` and
9921001
`@_rawLayout(likeArrayOf: T, count: 1)` is that the latter will pad out the

0 commit comments

Comments
 (0)