Incompatible Concurrency Annotation
Declaration should be @preconcurrency to maintain compatibility with Swift 5
- Identifier:
incompatible_concurrency_annotation - Enabled by default: No
- Supports autocorrection: Yes
- Kind: lint
- Analyzer rule: No
- Minimum Swift compiler version: 6.0.0
- Default configuration:
Key Value severity warning global_actors [“MainActor”]
Rationale
Declarations that use concurrency features such as @Sendable closures, Sendable generic type
arguments or @MainActor (or other global actors) should be annotated with @preconcurrency
to ensure compatibility with Swift 5.
This rule detects public declarations that require @preconcurrency and can automatically add
the annotation.
Non Triggering Examples
public struct S: Sendable {}
public class C: Sendable {}
public actor A {}
private @MainActor struct S { }
@MainActor struct S { }
internal @MainActor func globalActor()
private @MainActor init() {}
internal subscript(index: Int) -> String where String: Sendable { get }
@preconcurrency @MainActor public struct S {}
@preconcurrency @MainActor public class C {}
@preconcurrency @MainActor public enum E { case a }
@preconcurrency @MainActor public protocol P {}
@preconcurrency @MainActor public func globalActor()
@preconcurrency public func sendableClosure(_ block: @Sendable () -> Void)
@preconcurrency public func globalActorClosure(_ block: @MainActor () -> Void)
@preconcurrency public init(_ block: @Sendable () -> Void)
@preconcurrency public subscript(index: Int) -> String where String: Sendable { get }
@preconcurrency public func sendableReturningClosure() -> @Sendable () -> Void
@preconcurrency public func globalActorReturningClosure() -> @MainActor () -> Void
@preconcurrency public func sendingParameter(_ value: sending MyClass)
@preconcurrency public func tupleParameterClosures(
_ handlers: (@Sendable () -> Void, @MainActor () -> Void)
)
@preconcurrency public func tupleReturningClosures() -> (
@Sendable () -> Void,
@MainActor () -> Void
)
@preconcurrency public func closureWithSendingArgument(
_ handler: (_ value: sending MyClass) -> Void
)
public func nonSendableClosure(_ block: () -> Void)
public func generic<T>() where T: Equatable
public func generic<T: Hashable>()
public init<T: Hashable>()
public @MyActor enum E { case a }
public func customActor(_ block: @MyActor () -> Void)
Triggering Examples
@MainActor public ↓struct S {}
@MainActor public ↓class C {}
@MainActor public ↓enum E { case a }
@MainActor public ↓protocol GlobalActor {}
@MainActor public ↓func globalActor()
class C {
@MainActor public ↓init() {}
}
@MainActor public ↓init<T>()
struct S {
@MainActor public ↓subscript(index: Int) -> String { get }
}
public ↓subscript<T>(index: T) -> Int where T: ExpressibleByIntegerLiteral & Sendable { get }
public ↓func sendableClosure(_ block: @Sendable () -> Void)
public ↓func globalActorClosure(_ block: @MainActor () -> Void)
public struct S { public ↓func sendableClosure(_ block: @Sendable () -> Void) }
public ↓init(_ block: @Sendable () -> Void)
public ↓init(param: @MainActor () -> Void)
public ↓func tupleParameter(
_ handlers: (@Sendable () -> Void, @MainActor () -> Void)
)
public ↓func tupleWithSending(
_ handlers: ((_ value: sending MyClass) -> Void, @MainActor () -> Void)
)
public ↓func generic<T>() where T: Sendable {}
public ↓struct S<T> where T: Sendable {}
public ↓class C<T> where T: Sendable {}
public ↓enum E<T> where T: Sendable { case a }
public ↓init<T>() where T: Sendable {}
public ↓func returnsSendableClosure() -> @Sendable () -> Void
public ↓func returnsActorClosure() -> @MainActor () -> Void
public ↓func returnsClosureTuple() -> (@Sendable () -> Void, @MainActor () -> Void)
//
// global_actors: ["MainActor", "MyActor"]
//
@MyActor public ↓struct S {}
//
// global_actors: ["MainActor", "MyActor"]
//
public ↓func globalActorClosure(_ block: @MyActor () -> Void)
//
// global_actors: ["MainActor", "MyActor"]
//
@MyActor public ↓func customGlobalActor()
//
// global_actors: ["MainActor", "MyActor"]
//
@MyActor public ↓init()
View on GitHub
Install in Dash