dowel

ADR-0009: FileId は正規化したパスのハッシュとする

状態: Accepted

文脈

ストアに値を格納するにあたり、FileId の扱いを決める必要があった (99-open-questions.md Q9)。

FileId は当初 SourceMap 内の添字であり、読み込んだ順に振られていた。 プロセス内では SourceMap::load が パスに対して同じ識別子を返すため安定していたが、プロセスを跨ぐと パッケージの走査順に依存する。

格納する値(Document / Value / Prov)はスパンを含み、スパンは FileId と対でのみ意味を持つ。番号がずれた状態で値を復元すると、 来歴と診断が別のファイルを指す。

選択肢は3つあった。

案 内容
A. パスのハッシュにする FileId を読み込み順から独立させる
B. 対応表をストアに持つ 復元時に現プロセスの番号へ振り直す
C. 値の中をパスにする 格納時に置き換え、復元時に引き直す

決定

案 A を採る。FileId を正規化したパスの 64bit ハッシュとする。

SourceMap の内部は Vec の添字から連想配列へ変わる。

根拠

案 B と案 C は、いずれも復元時(案 C は格納時も)に値の木を全走査して FileId を書き換える必要がある。これは 20-architecture.md 5.1 の「ノードの実体は必要に なるまで読まない」という性質と衝突する。復元のたびに全走査するなら、 値を遅延して読む意味がない。

案 A では格納した値をそのまま復元できる。走査は生じない。

案 C は加えて、同じパスが値の数だけ重複して保存される。

帰結

  • ハッシュの衝突時は別の識別子を割り当てて正しさを保つ。64bit では 実用上起きないが、衝突を検出せずに別のファイルを同一と扱うと、 診断と来歴が静かに誤る。衝突した1件はプロセスを跨いだ安定性を失う
  • FileId から SourceMap を引く操作が定数時間から対数時間になる。 診断の描画と来歴の表示で用いるが、いずれも件数が少ない
  • 未知の FileId を引いた場合は空の記述を返す。診断の描画中に落とすと 誤りの報告そのものが失われるためである
  • 正規化できないパス(存在しないファイルを指す合成のソース)は 与えられたパスをそのまま用いる。別の書き方で同じファイルを指すと 別の識別子になるが、正規化できない以上は同一性を判定できない