🚨

Swift のビルド時の「警告」をすべて「エラー」にして ⚠️ の数をゼロにすることを目指す(Warning Control)

に公開

普段のあなたの Swift 製プロジェクトには、どれくらいの「警告(warning)」が残っていますか?

この黄色の警告表示、たくさん表示されると「うっ……」となり、またコンパイル・ビルドのログがものすごく長くなってしまって見辛くなりますよね。ただ、警告を解消せずともコンパイル・ビルドは成功してしまうため、ついつい放置しがち… という方もいらっしゃるのではないでしょうか。

それならば、警告は全部エラーにして、解消しなければビルドが失敗する ようにすれば良いのでは……?

この記事は Swift Advent Calendar 2025 の23日目の記事です。

すべての「警告」を「エラー」として取り扱う

Swift の初期から、すべての警告をエラーとして取り扱うようにするコンパイラフラグ「-warnings-as-errors」がありました。たとえば、Xcode プロジェクトのビルド設定でこれをセットするには「Treat Warnings as Errors(SWIFT_TREAT_WARNINGS_AS_ERRORS)」を「Yes」にします。

また、Swift 6.2 からは Swift Package Manager からもこの設定を行えるようになり、SwiftSetting の treatAllWarnings(as:_:) で WarningLevel を error にすることで、コンパイラフラグ「-warnings-as-errors」を設定したのと同義になります。

Package.swift
  // swift-tools-version: 6.2
  
  import PackageDescription
  
  let package = Package(
      name: "Playground",
      targets: [
          .target(
              name: "Playground",
              swiftSettings: [
+                 .treatAllWarnings(as: .error),
              ]
          )
      ]
  )

このいずれかの方法で、すべての警告をエラーとして取り扱うようにしてビルドしてみましょう。

真っ黄色だった画面の表示が赤に染まり、これらをすべて解決しなければビルドが失敗するようになりました。

すべての警告をエラーにしつつ、一部は警告のまま残す

意気揚々とすべての警告をエラーにしましたが、プロジェクトの状態によってはエラーの数が多すぎてどうにもならない… といったことも考えられるでしょう。そこで、一部のカテゴリについてはエラーとして取り扱わず、警告のままにしておくことができます。

たとえば、以下のスクリーンショットのように、すでに非推奨(depreacted)となっている宣言について、これを使っている箇所には警告が付きますが、すべての警告をエラーとして取り扱うようにしたことでビルドが通らなくなりました。

これへの対応がなんらかの理由によって困難で、一時的にエラーではなく警告に戻したいという場面を想定します。この「非推奨なっている宣言」は「診断グループ(diagnostic groups)」の「DeprecatedDeclaration」に該当するため、これに限ってはエラーではなく警告のまま取り扱うように指定します。「診断グループ」については後述します。

Swift Package Manager から設定するには、SwiftSetting の treatWarning(_:as:_:) を使います。[1]

Package.swift
  // swift-tools-version: 6.2
  
  import PackageDescription
  
  let package = Package(
      name: "Playground",
      targets: [
          .target(
              name: "Playground",
              swiftSettings: [
                  .treatAllWarnings(as: .error),
+                 .treatWarning("DeprecatedDeclaration", as: .warning),
              ]
          )
      ]
  )

このようにすることで、基本的にはすべての警告をエラーとして取り扱いつつ、一部の診断グループについては警告のままにすることができました。

一部の警告のみをエラーとして取り扱う

先ほどの例とは逆に、一部の警告だけをエラーとして取り扱うようにすることもできます。SwiftSetting の treatAllWarnings(as:_:) の記述を削除し、treatWarning(_:as:_:) で WarningLevel を error にします。

Package.swift
  // swift-tools-version: 6.2
  
  import PackageDescription
  
  let package = Package(
      name: "Playground",
      targets: [
          .target(
              name: "Playground",
              swiftSettings: [
-                 .treatAllWarnings(as: .error),
-                 .treatWarning("DeprecatedDeclaration", as: .warning),
+                 .treatWarning("DeprecatedDeclaration", as: .error),
              ]
          )
      ]
  )

しかし、この場合「診断グループ」に属さない警告をエラーにすることができなくなります。

たとえば、未使用変数についての警告はどの診断グループにも属していないため、これをエラーにしたい場合には必ず treatAllWarnings(as:_:) で WarningLevel を error にする必要があります。

診断グループ(diagnostic groups)

さて、Swift 6.1 で導入された 「SE-0443 Precise Control Flags over Compiler Warnings」において、「診断グループ(diagnostic groups)」という概念が登場しています。

もともとコンパイラには警告やエラーのそれぞれに「診断識別子(diagnostic identifiers)」がありますが、それを抽象化したのがこの「診断グループ」です。警告やエラーの切り替えには「診断グループ」の方を用います。

特定の警告・エラーがどの診断グループによるものなのかを調べるには、コンパイラオプション「-print-diagnostic-groups」を付けてビルドし、ログを確認します。

% swift build -Xswiftc -warnings-as-errors -Xswiftc -print-diagnostic-groups

[1/1] Planning build
Building for debugging...
error: emit-module command failed with exit code 1 (use -v to see invocation)
/Users/treastrain/Developer/Playground/Swift Package/Sources/Playground/main.swift:16:19: error: 'Q' is deprecated [#DeprecatedDeclaration]
14 | 
15 | struct MyData: P {}
16 | extension MyData: Q {}
   |                   `- error: 'Q' is deprecated [#DeprecatedDeclaration]
17 | 
18 | 

[#DeprecatedDeclaration]: <https://docs.swift.org/compiler/documentation/diagnostics/deprecated-declaration>

診断グループの一覧を取得する swift コマンドは現時点では存在しません。トグルの中に一覧表を用意しましたのでよろしければご覧ください。

Swift 6.2 で利用可能な診断グループの一覧
名称 ドキュメント
ActorIsolatedCall Calling an actor-isolated method from a synchronous nonisolated context
AvailabilityUnrecognizedName Unrecognized availability platforms
ClangDeclarationImport Imported Clang declaration warnings
ConformanceIsolation Protocol conformances crossing into actor-isolated code
DeprecatedDeclaration Deprecated declaration warnings
DynamicCallable @dynamicCallable implementation requirements
ErrorInFutureSwiftVersion Language mode and tools version
ExistentialAny Existential any
ExistentialMemberAccess Using protocol members with references to `Self` or `Self`-rooted associated types
ImplementationOnlyDeprecated Deprecated implementation-only imports
IsolatedConformances Isolated conformances
MemberImportVisibility Member import visibility
MissingModuleOnKnownPaths Missing module on known path from a dependency
MultipleInheritance Multiple inheritance
MutableGlobalVariable Unsafe mutable global and static variables
NominalTypes Nominal types
NonisolatedNonsendingByDefault nonisolated(nonsending) by Default
OpaqueTypeInference Underlying type inference for opaque result types
PreconcurrencyImport Extraneous @preconcurrency imports
PropertyWrappers Property wrapper implementation requirements
ProtocolTypeNonConformance Protocol types cannot conform to protocols
ResultBuilderMethods Result builder methods
SendableClosureCaptures Captures in a `@Sendable` closure
SendableMetatypes Sendable metatypes
SendingRisksDataRace Sending value risks causing data races
StrictLanguageFeatures Strict language feature enablement
StrictMemorySafety Strict memory safety
StringInterpolationConformance Conforming to `StringInterpolationProtocol`
TemporaryPointers Temporary pointers
TrailingClosureMatching Argument matching for trailing closures
UnknownWarningGroup Unknown warning group
Swift 6.3 から利用可能な診断グループの一覧

(swift-6.3-DEVELOPMENT-SNAPSHOT-2025-12-18-a 時点での情報です)

名称 ドキュメント
AlwaysAvailableDomain Always enabled availability domains
CompilationCaching Compilation caching
ForeignReferenceType Foreign reference types
DynamicExclusivity Dynamic Exclusivity
EmbeddedRestrictions Embedded Swift language restrictions
ExclusivityViolation Overlapping accesses, but operation requires exclusive access
ExistentialType (なし)
ModuleNotTestable Module not testable
ModuleVersionMissing Missing module version
PerformanceHints Performance hints
RegionIsolation (なし)
ReturnTypeImplicitCopy (なし)
SemanticCopies Semantic Copies
SendingClosureRisksDataRace Sending closure risks causing data races
UnrecognizedStrictLanguageFeatures (なし)
WeakMutability (なし)
ExplicitSendable Explicit Sendable annotations on public type declarations
脚注
  1. コンパイラフラグで指定する場合は「-Wwarning <診断グループの名称>」を追加します。 ↩︎

Discussion