コンパイラ診断ディレクティブ
Compiler Diagnostic Directives
このダイジェストはClaude Opus 4.7 / 4.8によって生成されたものです(License)。原文はこちら↗。
01 何が問題だったのか
開発中のコードベースには、未完成の部分や後で見直すべき箇所を示すために TODO や FIXME といったコメントを残すことがよくあります。多くのエディタはこれらのコメントをコードナビゲータに表示してくれますが、コマンドラインでのビルドや継続的インテグレーション (CI) では表示されないため、チームや自分自身に確実に気付かせる手段がありませんでした。
また、二つのビルド構成が排他的な関係にあり「この組み合わせでビルドしてはいけない」ことをコンパイル時に検出したい場合もあります。Swift にはそのためのしくみがなく、条件付きコンパイルで不整合を検出して確実にビルドを失敗させる手段が不足していました。
これらは性質の異なる課題ですが、いずれも「コンパイル時に開発者へ確実にメッセージを伝える」ための仕組みが欠けているという共通点があります。
02 どのように解決されるのか
コンパイラディレクティブとして #warning(_:) と #error(_:) を導入します。いずれも引数に静的な文字列リテラルを取り、パース時点でその内容を警告またはエラーとして出力します。
#warning の使い方
#warning はコンパイルを止めずに警告を出します。コードテンプレートで「ここを埋めてください」と指示したいときや、あとで見直したい箇所に印を付けたいときに便利です。
enum APICredentials {
#warning("fill in your API key below")
static let key = ""
#warning("fill in your API secret below")
static let secret = ""
}
func configPath() -> String {
#warning("this should be made more safe")
return Bundle.main.path(forResource: "Config", ofType: "plist")!
}
#error の使い方
#error はコンパイルをエラーで失敗させます。ビルド構成の組み合わせが不正であることをコンパイル時に検出したい場合などに使います。
#if MYLIB_VERSION < 3 && os(macOS)
#error("MyLib versions < 3 are not supported on macOS")
#endif
#if との組み合わせ
#warning や #error が #if の通らない分岐の中にある場合は、診断は出力されません。これにより、特定のビルド構成のときだけ警告やエラーを出すことができます。
#if false
#warning("this will not trigger a warning")
#error("this will not trigger an error")
#endif
#if true
#warning("this will trigger a warning")
#error("this will trigger an error")
#endif
動作の詳細
- 引数は静的な文字列リテラル(
static-string-literal)に限られます。実行時に組み立てた文字列は渡せません。 - 診断の位置は、文字列リテラルの先頭を指します。
#errorが出現してもコンパイラはディレクティブ自体を無視してそのまま処理を続けます(そのためエラーは出るものの、以降の解析は行われます)。
03 今後の見通し
本提案では #warning と #error は行ディレクティブとしてのみ提供され、式の中で値を包みつつ警告を出すような使い方はできません。レビューの過程では、こうした式形式の #warning や、警告扱いにしない純粋な情報メッセージ用の #message / #info といった拡張も議論されました。
これらはいずれも本提案の機能を壊さずに後から追加できる加法的な拡張であり、将来別のproposalで取り上げる余地が残されています。あくまで方向性として示されているもので、実現を約束するものではありません。