現在のソース位置を取得するマクロ
Macro for getting the current source location
このダイジェストはClaude Opus 4.7 / 4.8によって生成されたものです(License)。原文はこちら↗。
01 何が問題だったのか
Swift 標準ライブラリには、コンパイル時に呼び出し位置のファイル ID・ファイルパス・行・列を取得する #fileID / #filePath / #line / #column といったマクロがあります。これらを関数のデフォルト引数に使うと、呼び出し元のソース上の位置を自動的に捕捉できます。たとえば fatalError() は file と line を受け取り、呼び出された際にそれらを標準エラー出力へ表示します。
Swift Testing はこの 4 つの値すべてを捕捉する必要があります。しかし 4 つを個別に扱うのは冗長で煩雑なため、これらをまとめた SourceLocation 型を用意し、各 API はその 1 引数として受け取ります。SourceLocation を捕捉するために、Swift Testing は次のように展開される #_sourceLocation マクロを提供しています。
public func withKnownIssue(
_ comment: Comment? = nil,
isIntermittent: Bool = false,
sourceLocation: SourceLocation = #_sourceLocation,
_ body: () throws -> Void
)
ところがこの #_sourceLocation はアンダースコア付きで、正式にはサポートされておらず、Swift Testing のドキュメントにも載っていません。かといって SourceLocation.init() を使っても、デフォルト引数式の展開の仕組み(SE-0422)の都合で「誤った」位置が捕捉されてしまいます。そのため、テスト作者が SourceLocation を捕捉する正式な手段は、4 つの引数をすべて手で書き出して自分で SourceLocation を構築することしかありませんでした。
02 どのように解決されるのか
既存の(非サポートな)#_sourceLocation を置き換える、正式にサポートされた #sourceLocation マクロを Swift Testing に導入します。このマクロは、コンパイル時に、マクロ呼び出し自身の位置を指す SourceLocation のインスタンスへ展開されます。
/// 現在のソース位置を取得する。
@freestanding(expression) public macro sourceLocation() -> SourceLocation
ただし、Swift 言語には行制御のための #sourceLocation(file:line:) 文が組み込まれています。そのため、式としての #sourceLocation マクロと衝突しないよう、利用時には module selector でモジュール名を明示して #Testing::sourceLocation と書く必要があります。
let here = #Testing::sourceLocation
#fileID / #filePath / #line / #column と同様に、関数のデフォルト引数として使うのが基本的な使い方です。
func expectEdible(
_ food: some Food,
sourceLocation: SourceLocation = #Testing::sourceLocation
) {
#expect(food.isEdible, sourceLocation: sourceLocation)
}
既存の #_sourceLocation は deprecated となり、deprecation メッセージで #Testing::sourceLocation への移行を促します。ただし、より古い Swift リリースとのソース互換性のために、#_sourceLocation 自体は引き続き利用可能なまま残されます。
03 今後の見通し
将来的には、式の位置で使われた #sourceLocation と文の位置で使われた #sourceLocation をコンパイラが区別し、明らかに行制御文を指す場合にだけ組み込みの文として扱うように調整したい、という構想があります。これが実現すれば、式としての #sourceLocation を module selector なしで曖昧さなく使えるようになります。この変更は、すでに #Testing::sourceLocation と書かれている既存のコードともソース互換であるとされています。あくまで将来の方向性であり、実現を約束するものではありません。