Skip to content

Commit cf0f0a1

Browse files
Examples for Protocol Conformance Mismatch errors (#38)
1 parent 98fd41e commit cf0f0a1

File tree

3 files changed

+185
-0
lines changed

3 files changed

+185
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import Library
2+
3+
// MARK: Under-Specified Protocol
4+
5+
#if swift(<6.0)
6+
/// A conforming type that has now adopted global isolation.
7+
@MainActor
8+
class WindowStyler: Styler {
9+
// Swift 5 Warning: main actor-isolated instance method 'applyStyle()' cannot be used to satisfy nonisolated protocol requirement
10+
// Swift 6 Error: main actor-isolated instance method 'applyStyle()' cannot be used to satisfy nonisolated protocol requirement
11+
func applyStyle() {
12+
}
13+
}
14+
#endif
15+
16+
// MARK: Globally-Isolated Protocol
17+
18+
/// A type conforming to the global actor annotated `GloballyIsolatedStyler` protocol,
19+
/// will infer the protocol's global actor isolation.
20+
class GloballyIsolatedWindowStyler: GloballyIsolatedStyler {
21+
func applyStyle() {
22+
}
23+
}
24+
25+
/// A type conforming to `PerRequirementIsolatedStyler` which has MainActor isolated protocol requirements,
26+
/// will infer the protocol's requirements isolation for methods witnessing those protocol requirements *only*
27+
/// for the satisfying methods.
28+
class PerRequirementIsolatedWindowStyler: PerRequirementIsolatedStyler {
29+
func applyStyle() {
30+
// only this is MainActor-isolated
31+
}
32+
33+
func checkStyle() {
34+
// this method is non-isolated; it is not witnessing any isolated protocol requirement
35+
}
36+
}
37+
38+
// MARK: Asynchronous Requirements
39+
40+
/// A conforming type that can have arbitrary isolation and
41+
/// still matches the async requirement.
42+
class AsyncWindowStyler: AsyncStyler {
43+
func applyStyle() {
44+
}
45+
}
46+
47+
// MARK: Using preconcurrency
48+
49+
/// A conforming type that will infer the protocol's global isolation *but*
50+
/// with downgraded diagnostics in Swift 6 mode and Swift 5 + complete checking
51+
class StagedGloballyIsolatedWindowStyler: StagedGloballyIsolatedStyler {
52+
func applyStyle() {
53+
}
54+
}
55+
56+
// MARK: Using Dynamic Isolation
57+
58+
/// A conforming type that uses a nonisolated function to match
59+
/// with dynamic isolation in the method body.
60+
@MainActor
61+
class DynamicallyIsolatedStyler: Styler {
62+
nonisolated func applyStyle() {
63+
#if compiler(<6.0)
64+
// temporarily disabled due to https://github.com/apple/swift/issues/74009
65+
MainActor.assumeIsolated {
66+
// MainActor state is available here
67+
}
68+
#endif
69+
}
70+
}
71+
72+
#if compiler(>=6.0)
73+
/// A conforming type that uses a preconcurency conformance, which
74+
/// is a safer and more ergonomic version of DynamicallyIsolatedStyler.
75+
@MainActor
76+
class PreconcurrencyConformanceStyler: @preconcurrency Styler {
77+
func applyStyle() {
78+
}
79+
}
80+
#endif
81+
82+
// MARK: Non-Isolated
83+
84+
/// A conforming type that uses nonisolated and non-Sendable types but
85+
/// still performs useful work.
86+
@MainActor
87+
class NonisolatedWindowStyler: StylerConfiguration {
88+
nonisolated var primaryColorComponents: ColorComponents {
89+
ColorComponents(red: 0.2, green: 0.3, blue: 0.4)
90+
}
91+
}
92+
93+
// MARK: Conformance by Proxy
94+
95+
/// An intermediary type that conforms to the protocol so it can be
96+
/// used by an actor
97+
struct CustomWindowStyle: Styler {
98+
func applyStyle() {
99+
}
100+
}
101+
102+
/// An actor that interacts with the Style protocol indirectly.
103+
actor ActorWindowStyler {
104+
private let internalStyle = CustomWindowStyle()
105+
106+
func applyStyle() {
107+
// forward the call through to the conforming type
108+
internalStyle.applyStyle()
109+
}
110+
}
111+
112+
func exerciseConformanceMismatchExamples() async {
113+
print("Protocol Conformance Isolation Mismatch Examples")
114+
115+
// Could also all be done with async calls, but this
116+
// makes the isolation, and the ability to invoke them
117+
// from a synchronous context explicit.
118+
await MainActor.run {
119+
#if swift(<6.0)
120+
print(" - using a mismatched conformance")
121+
WindowStyler().applyStyle()
122+
#endif
123+
124+
print(" - using a MainActor-isolated type")
125+
GloballyIsolatedWindowStyler().applyStyle()
126+
127+
print(" - using a per-requirement MainActor-isolated type")
128+
PerRequirementIsolatedWindowStyler().applyStyle()
129+
130+
print(" - using an async conformance")
131+
AsyncWindowStyler().applyStyle()
132+
133+
print(" - using staged isolation")
134+
StagedGloballyIsolatedWindowStyler().applyStyle()
135+
136+
print(" - using dynamic isolation")
137+
DynamicallyIsolatedStyler().applyStyle()
138+
139+
#if swift(>=6.0)
140+
print(" - using a preconcurrency conformance")
141+
PreconcurrencyConformanceStyler().applyStyle()
142+
#endif
143+
144+
let value = NonisolatedWindowStyler().primaryColorComponents
145+
print(" - accessing a non-isolated conformance: ", value)
146+
}
147+
148+
print(" - using an actor with a proxy conformance")
149+
await ActorWindowStyler().applyStyle()
150+
}

Sources/Examples/main.swift

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ let manualSerialQueue = DispatchQueue(label: "com.apple.SwiftMigrationGuide")
66
// Note: top-level code provides an asynchronous MainActor-isolated context
77
await exerciseGlobalExamples()
88
await exerciseBoundaryCrossingExamples()
9+
await exerciseConformanceMismatchExamples()

Sources/Library/Library.swift

+34
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,37 @@ public struct GlobalActorIsolatedColorComponents : Sendable {
3838

3939
public init() {}
4040
}
41+
42+
public protocol Styler {
43+
func applyStyle()
44+
}
45+
46+
@MainActor
47+
public protocol GloballyIsolatedStyler {
48+
func applyStyle()
49+
}
50+
51+
public protocol PerRequirementIsolatedStyler {
52+
@MainActor
53+
func applyStyle()
54+
}
55+
56+
@preconcurrency @MainActor
57+
public protocol StagedGloballyIsolatedStyler {
58+
func applyStyle()
59+
}
60+
61+
public protocol AsyncStyler {
62+
func applyStyle() async
63+
}
64+
65+
open class UIStyler {
66+
}
67+
68+
public protocol InheritingStyler: UIStyler {
69+
func applyStyle()
70+
}
71+
72+
public protocol StylerConfiguration {
73+
var primaryColorComponents: ColorComponents { get }
74+
}

0 commit comments

Comments
 (0)