Source-level warning control
The @diagnose attribute
@diagnose refines compiler warning behavior inside a specific declaration. It lets a focused region of source code be stricter or more permissive than the rest of its module.
At a glance
@diagnose(
StrictMemorySafety,
as: error,
reason: "Security-sensitive boundary"
)
func decodeHeader(_ pointer: UnsafePointer<UInt8>) {
// StrictMemorySafety warnings are errors throughout
// this declaration's signature and lexical scope.
}
Parameters
| Parameter | Type | Purpose | Possible values |
|---|---|---|---|
| Diagnostic group ID | Identifier | Selects the warning group whose behavior changes in this declaration. | See Documented diagnostic groups. |
as: |
Behavior specifier | Defines how warnings from the selected group are emitted. | error, warning, or ignored. |
reason: |
Optional static string literal | Documents why the warning behavior differs in this declaration. | Any string literal without interpolation. |
Behavior effects
The value passed to as: determines the selected group’s behavior throughout the declaration:
| Behavior | Effect inside the declaration |
|---|---|
error |
Promotes warnings in the selected group to errors. |
warning |
Emits the selected group as warnings, even when an enclosing or module-wide policy promoted them to errors. |
ignored |
Suppresses warnings in the selected group within the declaration. |
How scope works
The policy covers both the annotated declaration’s signature and its lexical scope. It can be applied to functions, types, extensions, protocols, initializers, subscripts, computed properties, accessors, observers, enum cases, type aliases, associated types, imports, and declarations produced by freestanding declaration macros.
@diagnose(StrictMemorySafety, as: warning)
struct LegacyDecoder {
func decode(_ pointer: UnsafePointer<UInt8>) {
// StrictMemorySafety diagnostics are warnings here.
}
@diagnose(
StrictMemorySafety,
as: ignored,
reason: "Input is validated by the caller"
)
func decodeTrusted(_ pointer: UnsafePointer<UInt8>) {
// The nested declaration overrides its enclosing policy.
}
}
Nested declarations can refine an enclosing policy. The innermost policy wins. Multiple attributes on the same declaration are order-sensitive, and the lexically last applicable attribute wins.
Relationship with build settings
Module-wide flags such as -warnings-as-errors, -Werror <GroupID>, and -Wwarning <GroupID> establish global behavior. @diagnose overrides that behavior for its declaration only.
// The module uses: -warnings-as-errors
@diagnose(
ErrorInFutureSwiftVersion,
as: warning,
reason: "Migration is tracked for this compatibility layer"
)
func compatibilityLayer() {
// Future-version diagnostics remain visible without failing this build.
}
Important limits:
@diagnosecontrols warning diagnostics only. It cannot suppress or change compiler errors.-suppress-warningsremains module-wide and overrides every@diagnosebehavior, includingas: error.- The attribute does not affect source compatibility, ABI, or deployment targets.
- Attached peer declarations are outside the annotated declaration’s lexical scope.
Use cases
Allow a temporary deprecated API exception
A project can enforce deprecation warnings as errors globally while allowing one compatibility boundary to keep building. The reason: records why the exception exists and when it should be revisited.
@diagnose(
DeprecatedDeclaration,
as: warning,
reason: "Maintain compatibility until the next release"
)
func bridgeToLegacySystem() {
oldAPI() // Remains a warning here instead of an error.
}
Prepare a declaration for a future Swift language mode
Promote warnings that will become errors in a future Swift language mode today. This helps teams migrate sensitive or actively maintained code before changing the entire module’s language mode.
@diagnose(
ErrorInFutureSwiftVersion,
as: error,
reason: "Keep this parser ready for the next Swift language mode"
)
func parseConfiguration() {
// Future-version errors already fail this declaration's build.
}
Keep generated or compatibility code free of unused values
Treat unused values as errors inside declarations where every computed result should be consumed, without imposing that policy throughout the project.
@diagnose(NoUsage, as: error)
func generateBindings() {
buildMetadata() // Fails the build if this result is unused.
}
These are only a few possible policies. Explore all available identifiers in Documented diagnostic groups.
Documented diagnostic groups
The table covers every Group ID with a corresponding document in Swift’s diagnostic documentation at commit aacc248. Each ID links to its source document.
The snippets demonstrate how to apply each identifier. Whether a snippet produces a diagnostic depends on the code inside the declaration, compiler version, language mode, enabled features, and build settings. @diagnose only affects diagnostics emitted as warnings; it cannot modify compiler errors.
| Group ID | Description | Swift usage |
|---|---|---|
ActorIsolatedCall | Calling actor-isolated methods from synchronous nonisolated contexts | |
ActorIsolatedMutatingAsync | Calling mutating async actor-isolated methods | |
AddPreconcurrencyImport | Add @preconcurrency imports | |
AlwaysAvailableDomain | Always-enabled availability domains | |
AvailabilityUnrecognizedName | Unrecognized availability platforms | |
CanImportMissingModule | Missing modules referenced by canImport | |
ClangDeclarationImport | Imported Clang declaration warnings | |
CompilationCaching | Compilation caching diagnostics | |
ConformanceIsolation | Protocol conformances crossing into actor-isolated code | |
ConversionFromIsolatedAnyToSynchronous | Conversions from @isolated(any) to synchronous functions | |
DeprecatedDeclaration | Uses of deprecated declarations | |
DynamicCallable | @dynamicCallable implementation requirements | |
DynamicExclusivity | Dynamic exclusivity checks | |
EmbeddedRestrictions | Embedded Swift language restrictions | |
ErrorInFutureSwiftVersion | Warnings that become errors in a future Swift mode | |
ExclusivityViolation | Overlapping access violations | |
ExistentialAny | Explicit any for existential types | |
ExistentialMemberAccess | Existential member access limitations | |
ExistentialType | Existential type performance hints | |
ExplicitSendable | Explicit Sendable annotations on public types | |
ForeignReferenceType | Foreign reference types | |
ImplementationOnlyDeprecated | Deprecated implementation-only imports | |
ImplicitStrongCapture | Implicit strong captures of weak items | |
InconsistentImportAccess | Inconsistent import access levels | |
IsolatedConformances | Isolated conformances | |
MemberImportVisibility | Member import visibility | |
MissingModuleOnKnownPaths | Missing modules on known dependency paths | |
ModuleNotTestable | Modules unavailable for testing | |
ModuleSelfImport | A module importing itself | |
ModuleVersionMissing | Missing module versions | |
MultipleInheritance | Unsupported multiple inheritance | |
MutableGlobalVariable | Unsafe mutable global and static variables | |
NoUsage | Unused values | |
NoUseUnstructuredThrowingTask | Unused throwing unstructured tasks | |
NominalTypes | Nominal type diagnostics | |
NonisolatedNonsendingByDefault | nonisolated(nonsending) default behavior | |
OldSuppressedAssociatedTypes | Migration from suppressed associated types | |
OpaqueTypeInference | Opaque result type inference | |
OptionObsoletedByModuleSelectors | Options obsoleted by module selectors | |
OSLog | OSLog module diagnostics | |
PerformanceHints | Performance-related hints | |
PreconcurrencyImport | Extraneous @preconcurrency imports | |
PropertyWrappers | Property wrapper implementation requirements | |
ProtocolTypeNonConformance | Protocol types that cannot conform to protocols | |
PublicImportOfProjectInternalModule | Public imports of project-internal modules | |
RegionIsolationCrossIsolationDataRace | Cross-isolation data races | |
RegionIsolationUnknownPattern | Unknown region-isolation patterns | |
ResultBuilderMethods | Result builder method requirements | |
ReturnTypeImplicitCopy | Implicit copies on return | |
SemanticCopies | Semantic copy diagnostics | |
SendableClosureCaptures | Captures in @Sendable closures | |
SendableMetatypes | Sendable metatypes | |
SendingClosureRisksDataRace | Sending closures that risk data races | |
SendingRisksDataRace | Sending values that risk data races | |
SPIImportIgnored | Ignored SPI imports | |
StrictLanguageFeatures | Strict language feature enablement | |
StrictMemorySafety | Strict memory-safety checks | |
StringInterpolationConformance | StringInterpolationProtocol conformances | |
TemporaryPointers | Temporary pointer lifetime issues | |
TrailingClosureMatching | Trailing-closure argument matching | |
UnavailableSendableConformance | Unavailable Sendable conformances | |
UnknownWarningGroup | Unknown warning groups | |
UnnecessaryEffectMarker | Unnecessary effect markers | |
UnnecessaryUnsafe | Unnecessary unsafe markers | |
UnrecognizedStrictLanguageFeatures | Unrecognized strict language features | |
UnsupportedScopedImport | Unsupported scoped imports | |
UntypedThrows | Untyped throws | |
UnusedImportAccess | Unused import access levels | |
UseAnyAppleOSAvailability | Use of anyAppleOS availability | |
UselessAvailabilityCheck | Availability checks with no effect | |
UselessConditionalStatement | Conditional statements with no effect | |