Unavailable Sendable conformance (UnavailableSendableConformance)
Overview
An unavailable sendable conformance is an explicit prohibition on conforming to Sendable. It is declared by marking the conformance unavailable with the available attribute. Like other conformances, unavailable conformances are inherited by subclasses. Providing an unavailable conformance to the Sendable protocol states that a type and its subclasses must not conform to Sendable:
class ImageLoader {}
@available(*, unavailable)
extension ImageLoader: Sendable {}Suppose you subclass a type with an unavailable Sendable conformance:
final class ThumbnailLoader: ImageLoader, @unchecked Sendable {}This results in a warning like:
| final class ThumbnailLoader: ImageLoader, @unchecked Sendable {}
| | `- warning: 'ThumbnailLoader' inherits an unavailable 'Sendable' conformance; conforming here risks data races
| `- note: 'ThumbnailLoader' inherits unavailable conformance to protocol 'Sendable' from superclass hereAn unavailable Sendable conformance means the type does not meet the criteria for Sendable, so it would not be safe to treat it or any subclass as Sendable. Suppose ImageLoader comes from a library with mutable implementation details like an unsynchronized cache, which makes it unsafe to send, so the library author used an unavailable conformance to ensure it’s never treated as Sendable. Sharing an ImageLoader between concurrency domains would be a data race. Your ThumbnailLoader subclass inherits these implementation details, so it must not be marked Sendable either.
These rules also apply to extensions of types; you shouldn’t extend a type to conform to Sendable when it was defined with an unavailable Sendable conformance. Treating a non-Sendable type as Sendable will prevent enforcing race safety.
Suppressed conformances
By writing ~Sendable, a type can suppress inferred Sendable conformance without preventing subclasses from adding protections for state and conforming to Sendable. A superclass can also use ~Sendable to let subclasses choose whether to be Sendable.
class ImageLoader: ~Sendable {
// Not thread safe.
}
final class ThreadSafeImageLoader: ImageLoader, @unchecked Sendable {
// Protects state from ImageLoader in some way that makes it safe to access i.e. via a lock.
}Sendable wrapper
To resolve this warning, instead of trying to make a non-Sendable type conform to Sendable, create a Sendable wrapper that ensures exclusive access, or wrap the type in a Mutex, which is Sendable.
actor SendableImageLoader {
let loader: ImageLoader
// ...
}See Also
Related Documentation
Sendable TypesImplicit Conformance to a ProtocolSE-0518: ~Sendable for explicitly marking non-Sendable typesSE-0337: Incremental migration to concurrency checkingSE-0364: Warning for Retroactive Conformances of External Types
@dynamicCallable implementation requirements (DynamicCallable)Add @preconcurrency import (AddPreconcurrencyImport)Always enabled availability domains (AlwaysAvailableDomain)Argument matching for trailing closures (TrailingClosureMatching)Calling a mutating async actor-isolated method (ActorIsolatedMutatingAsync)Calling an actor-isolated method from a synchronous nonisolated context (ActorIsolatedCall)Captures in a `@Sendable` closure (SendableClosureCaptures)Compilation caching (CompilationCaching)Conforming to `StringInterpolationProtocol` (StringInterpolationConformance)Conversion from `@isolated(any)` function type to synchronous function type (ConversionFromIsolatedAnyToSynchronous)Cross-isolation data race (RegionIsolationCrossIsolationDataRace)Deprecated declaration warnings (DeprecatedDeclaration)Deprecated implementation-only imports (ImplementationOnlyDeprecated)Dynamic exclusivity (DynamicExclusivity)Embedded Swift language restrictions (EmbeddedRestrictions)