Skip to content

Commit 14f652d

Browse files
Merge pull request #4425 from swiftwasm/main
[pull] swiftwasm from main
2 parents a597c61 + de0e227 commit 14f652d

File tree

27 files changed

+488
-153
lines changed

27 files changed

+488
-153
lines changed

CHANGELOG.md

Lines changed: 52 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -71,54 +71,54 @@ _**Note:** This is in reverse chronological order, so newer entries are added to
7171

7272
* [SE-0343][]:
7373

74-
Top-level scripts support asynchronous calls.
74+
Top-level scripts support asynchronous calls.
7575

76-
Using an `await` by calling an asynchronous function or accessing an isolated
77-
variable transitions the top-level to an asynchronous context. As an
78-
asynchronous context, top-level variables are `@MainActor`-isolated and the
79-
top-level is run on the `@MainActor`.
76+
Using an `await` by calling an asynchronous function or accessing an isolated
77+
variable transitions the top-level to an asynchronous context. As an
78+
asynchronous context, top-level variables are `@MainActor`-isolated and the
79+
top-level is run on the `@MainActor`.
8080

81-
Note that the transition affects function overload resolution and starts an
82-
implicit run loop to drive the concurrency machinery.
81+
Note that the transition affects function overload resolution and starts an
82+
implicit run loop to drive the concurrency machinery.
8383

84-
Unmodified scripts are not affected by this change unless `-warn-concurrency` is
85-
passed to the compiler invocation. With `-warn-concurrency`, variables in the
86-
top-level are isolated to the main actor and the top-level context is isolated
87-
to the main actor, but is not an asynchronous context.
84+
Unmodified scripts are not affected by this change unless `-warn-concurrency` is
85+
passed to the compiler invocation. With `-warn-concurrency`, variables in the
86+
top-level are isolated to the main actor and the top-level context is isolated
87+
to the main actor, but is not an asynchronous context.
8888

8989
* [SE-0336][]:
9090

91-
It is now possible to declare `distributed actor` and `distributed func`s inside of them.
91+
It is now possible to declare `distributed actor` and `distributed func`s inside of them.
9292

93-
Distributed actors provide stronger isolation guarantees than "local" actors, and enable additional checks to be made on return types and parameters of distributed methods, e.g. checking if they conform to `Codable`. Distributed methods can be called on "remote" references of distributed actors, turning those invocations into remote procedure calls, by means of pluggable and user extensible distributed actor system implementations.
94-
95-
Swift does not provide any specific distributed actor system by itself, however, packages in the ecosystem fulfil the role of providing those implementations.
96-
97-
```swift
98-
distributed actor Greeter {
99-
var greetingsSent = 0
93+
Distributed actors provide stronger isolation guarantees than "local" actors, and enable additional checks to be made on return types and parameters of distributed methods, e.g. checking if they conform to `Codable`. Distributed methods can be called on "remote" references of distributed actors, turning those invocations into remote procedure calls, by means of pluggable and user extensible distributed actor system implementations.
94+
95+
Swift does not provide any specific distributed actor system by itself, however, packages in the ecosystem fulfil the role of providing those implementations.
10096

101-
distributed func greet(name: String) -> String {
102-
greetingsSent += 1
103-
return "Hello, \(name)!"
97+
```swift
98+
distributed actor Greeter {
99+
var greetingsSent = 0
100+
101+
distributed func greet(name: String) -> String {
102+
greetingsSent += 1
103+
return "Hello, \(name)!"
104+
}
104105
}
105-
}
106-
107-
func talkTo(greeter: Greeter) async throws {
108-
// isolation of distributed actors is stronger, it is impossible to refer to
109-
// any stored properties of distributed actors from outside of them:
110-
greeter.greetingsSent // distributed actor-isolated property 'name' can not be accessed from a non-isolated context
111106

112-
// remote calls are implicitly throwing and async,
113-
// to account for the potential networking involved:
114-
let greeting = try await greeter.greet(name: "Alice")
115-
print(greeting) // Hello, Alice!
116-
}
117-
```
107+
func talkTo(greeter: Greeter) async throws {
108+
// isolation of distributed actors is stronger, it is impossible to refer to
109+
// any stored properties of distributed actors from outside of them:
110+
greeter.greetingsSent // distributed actor-isolated property 'name' can not be accessed from a non-isolated context
111+
112+
// remote calls are implicitly throwing and async,
113+
// to account for the potential networking involved:
114+
let greeting = try await greeter.greet(name: "Alice")
115+
print(greeting) // Hello, Alice!
116+
}
117+
```
118118

119119
* The compiler now emits a warning when a non-final class conforms to a protocol that imposes a same-type requirement between `Self` and an associated type. This is because such a requirement makes the conformance unsound for subclasses.
120120

121-
For example, Swift 5.6 would allow the following code, which at runtime would construct an instance of `C` and not `SubC` as expected:
121+
For example, Swift 5.6 would allow the following code, which at runtime would construct an instance of `C` and not `SubC` as expected:
122122

123123
```swift
124124
protocol P {
@@ -226,24 +226,24 @@ Swift 5.6
226226

227227
* [SE-0327][]:
228228

229-
In Swift 5 mode, a warning is now emitted if the default-value expression of an
230-
instance-member property requires global-actor isolation. For example:
231-
232-
```swift
233-
@MainActor
234-
func partyGenerator() -> [PartyMember] { fatalError("todo") }
229+
In Swift 5 mode, a warning is now emitted if the default-value expression of an
230+
instance-member property requires global-actor isolation. For example:
235231

236-
class Party {
237-
@MainActor var members: [PartyMember] = partyGenerator()
238-
// ^~~~~~~~~~~~~~~~
239-
// warning: expression requiring global actor 'MainActor' cannot
240-
// appear in default-value expression of property 'members'
241-
}
242-
```
243-
244-
Previously, the isolation granted by the type checker matched the isolation of
245-
the property itself, but at runtime that is not guaranteed. In Swift 6,
246-
such default-value expressions will become an error if they require isolation.
232+
```swift
233+
@MainActor
234+
func partyGenerator() -> [PartyMember] { fatalError("todo") }
235+
236+
class Party {
237+
@MainActor var members: [PartyMember] = partyGenerator()
238+
// ^~~~~~~~~~~~~~~~
239+
// warning: expression requiring global actor 'MainActor' cannot
240+
// appear in default-value expression of property 'members'
241+
}
242+
```
243+
244+
Previously, the isolation granted by the type checker matched the isolation of
245+
the property itself, but at runtime that is not guaranteed. In Swift 6,
246+
such default-value expressions will become an error if they require isolation.
247247

248248
* Actor isolation checking now understands that `defer` bodies share the isolation of their enclosing function.
249249

SwiftCompilerSources/Sources/Optimizer/Analysis/CalleeAnalysis.swift

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,32 @@ import SIL
1616
public struct CalleeAnalysis {
1717
let bridged: BridgedCalleeAnalysis
1818

19-
public func getCallees(callee: Value) -> FunctionArray {
19+
public func getCallees(callee: Value) -> FunctionArray? {
20+
let bridgedFuncs = CalleeAnalysis_getCallees(bridged, callee.bridged)
21+
if bridgedFuncs.incomplete != 0 {
22+
return nil
23+
}
24+
return FunctionArray(bridged: bridgedFuncs)
25+
}
26+
27+
public func getIncompleteCallees(callee: Value) -> FunctionArray {
2028
return FunctionArray(bridged: CalleeAnalysis_getCallees(bridged, callee.bridged))
2129
}
2230

23-
public func getDestructors(destroyInst: Instruction) -> FunctionArray {
24-
return FunctionArray(bridged:
25-
CalleeAnalysis_getInstCallees(bridged, destroyInst.bridged))
31+
public func getDestructor(ofExactType type: Type) -> Function? {
32+
let destructors = FunctionArray(bridged: CalleeAnalysis_getDestructors(bridged, type.bridged, /*isExactType*/ 1))
33+
if destructors.count == 1 {
34+
return destructors[0]
35+
}
36+
return nil
37+
}
38+
39+
public func getDestructors(of type: Type) -> FunctionArray? {
40+
let bridgedDtors = CalleeAnalysis_getDestructors(bridged, type.bridged, /*isExactType*/ 0)
41+
if bridgedDtors.incomplete != 0 {
42+
return nil
43+
}
44+
return FunctionArray(bridged: bridgedDtors)
2645
}
2746
}
2847

@@ -35,6 +54,4 @@ public struct FunctionArray : RandomAccessCollection, FormattedLikeArray {
3554
public subscript(_ index: Int) -> Function {
3655
return BridgedFunctionArray_get(bridged, index).function
3756
}
38-
39-
public var allCalleesKnown: Bool { bridged.incomplete == 0 }
4057
}

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ReleaseDevirtualizer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ private func tryDevirtualizeReleaseOfObject(
8282

8383
let type = allocRefInstruction.type
8484

85-
guard let dealloc = context.getDestructor(ofClass: type) else {
85+
guard let dealloc = context.calleeAnalysis.getDestructor(ofExactType: type) else {
8686
return
8787
}
8888

SwiftCompilerSources/Sources/Optimizer/InstructionPasses/SimplifyGlobalValue.swift

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,20 @@ let simplifyGlobalValuePass = InstructionPass<GlobalValueInst>(
3737
private func checkUsers(of val: Value, users: inout Stack<Instruction>) -> Bool {
3838
for use in val.uses {
3939
let user = use.instruction
40-
if user is RefCountingInst || user is DebugValueInst {
41-
users.push(user)
42-
continue
43-
}
44-
if let upCast = user as? UpcastInst {
45-
if !checkUsers(of: upCast, users: &users) {
40+
switch user {
41+
case is RefCountingInst, is DebugValueInst, is FixLifetimeInst:
42+
users.push(user)
43+
case let upCast as UpcastInst:
44+
if !checkUsers(of: upCast, users: &users) {
45+
return false
46+
}
47+
case is RefElementAddrInst, is RefTailAddrInst:
48+
// Projection instructions don't access the object header, so they don't
49+
// prevent deleting reference counting instructions.
50+
break
51+
default:
4652
return false
47-
}
48-
continue
49-
}
50-
// Projection instructions don't access the object header, so they don't
51-
// prevent deleting reference counting instructions.
52-
if user is RefElementAddrInst || user is RefTailAddrInst {
53-
continue
5453
}
55-
return false
5654
}
5755
return true
5856
}

SwiftCompilerSources/Sources/Optimizer/PassManager/PassUtils.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,6 @@ struct PassContext {
112112
PassContext_fixStackNesting(_bridged, function.bridged)
113113
}
114114

115-
func getDestructor(ofClass type: Type) -> Function? {
116-
PassContext_getDestructor(_bridged, type.bridged).function
117-
}
118-
119115
func getContextSubstitutionMap(for type: Type) -> SubstitutionMap {
120116
SubstitutionMap(PassContext_getContextSubstitutionMap(_bridged, type.bridged))
121117
}

include/swift/AST/SILOptions.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ enum class CopyPropagationOption : uint8_t {
5858
On
5959
};
6060

61+
enum class DestroyHoistingOption : uint8_t {
62+
// Do not run SSADestroyHoisting.
63+
Off = 0,
64+
65+
// Run SSADestroyHoisting pass after AllocBoxToStack in the function passes.
66+
On = 1
67+
};
68+
6169
class SILModule;
6270

6371
class SILOptions {
@@ -84,6 +92,11 @@ class SILOptions {
8492
/// When this is 'On' the pipeline has default behavior.
8593
CopyPropagationOption CopyPropagation = CopyPropagationOption::On;
8694

95+
/// Whether to run the SSADestroyHoisting pass.
96+
///
97+
/// When this 'On' the pipeline has the default behavior.
98+
DestroyHoistingOption DestroyHoisting = DestroyHoistingOption::On;
99+
87100
/// Controls whether the SIL ARC optimizations are run.
88101
bool EnableARCOptimizations = true;
89102

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,10 @@ let Flags = [FrontendOption, NoDriverOption, HelpHidden, ModuleInterfaceOptionIg
248248
def enable_lexical_lifetimes_noArg :
249249
Flag<["-"], "enable-lexical-lifetimes">,
250250
HelpText<"Enable lexical lifetimes">;
251+
def enable_destroy_hoisting :
252+
Joined<["-"], "enable-destroy-hoisting=">,
253+
HelpText<"Whether to enable destroy hoisting">,
254+
MetaVarName<"true|false">;
251255
}
252256

253257
// Flags that are saved into module interfaces

include/swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ class CalleeCache {
147147

148148
/// Return the list of callees that can potentially be called at the
149149
/// given instruction. E.g. it could be destructors.
150-
CalleeList getCalleeList(SILInstruction *I) const;
150+
CalleeList getDestructors(SILType type, bool isExactType) const;
151151

152152
CalleeList getCalleeList(SILDeclRef Decl) const;
153153

@@ -224,9 +224,9 @@ class BasicCalleeAnalysis : public SILAnalysis {
224224
return Cache->getCalleeListOfValue(callee);
225225
}
226226

227-
CalleeList getCalleeList(SILInstruction *I) {
227+
CalleeList getDestructors(SILType type, bool isExactType) {
228228
updateCache();
229-
return Cache->getCalleeList(I);
229+
return Cache->getDestructors(type, isExactType);
230230
}
231231
};
232232

include/swift/SILOptimizer/OptimizerBridging.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,9 @@ BridgedCalleeAnalysis PassContext_getCalleeAnalysis(BridgedPassContext context);
9696

9797
BridgedCalleeList CalleeAnalysis_getCallees(BridgedCalleeAnalysis calleeAnalysis,
9898
BridgedValue callee);
99-
BridgedCalleeList CalleeAnalysis_getInstCallees(BridgedCalleeAnalysis calleeAnalysis,
100-
BridgedInstruction inst);
99+
BridgedCalleeList CalleeAnalysis_getDestructors(BridgedCalleeAnalysis calleeAnalysis,
100+
BridgedType type,
101+
SwiftInt isExactType);
101102
SwiftInt BridgedFunctionArray_size(BridgedCalleeList callees);
102103
BridgedFunction BridgedFunctionArray_get(BridgedCalleeList callees,
103104
SwiftInt index);
@@ -140,9 +141,6 @@ BridgedFunction BasicBlockSet_getFunction(BridgedBasicBlockSet set);
140141

141142
void AllocRefInstBase_setIsStackAllocatable(BridgedInstruction arb);
142143

143-
OptionalBridgedFunction PassContext_getDestructor(BridgedPassContext context,
144-
BridgedType type);
145-
146144
BridgedSubstitutionMap
147145
PassContext_getContextSubstitutionMap(BridgedPassContext context,
148146
BridgedType bridgedType);

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,14 @@ void swift::rewriting::realizeInheritedRequirements(
649649
Type());
650650
if (!inheritedType) continue;
651651

652+
// Ignore trivially circular protocol refinement (protocol P : P)
653+
// since we diagnose that elsewhere. Adding a rule here would emit
654+
// a useless redundancy warning.
655+
if (auto *protoDecl = dyn_cast<ProtocolDecl>(decl)) {
656+
if (inheritedType->isEqual(protoDecl->getDeclaredInterfaceType()))
657+
continue;
658+
}
659+
652660
auto *typeRepr = inheritedTypes[index].getTypeRepr();
653661
SourceLoc loc = (typeRepr ? typeRepr->getStartLoc() : SourceLoc());
654662
if (shouldInferRequirements) {

0 commit comments

Comments
 (0)