Ruby Bug #22023 ワークアラウンドのエンコーディング修正
LANG 環境変数が未設定または C に設定された環境で、Rubyソースファイルのパースが失敗する問題を修正しました。File.read のデフォルトエンコーディングに依存していた箇所を、明示的に UTF-8 を指定する形に変更しています。
背景
この修正は、バージョン 1.24.2 で導入された Ruby Bug #22023 ワークアラウンドの不具合に対処するものです。#541 で報告されたように、特定の環境下でワークアラウンド自体が新たな問題を引き起こしていました。
File.read はエンコーディングを明示しない場合、Encoding.default_external を使用します。この値は LANG 環境変数の影響を受けるため、LANG が未設定または C に設定されている環境では ASCII となります。Rubyのソースファイルには日本語などの非ASCII文字が含まれることがあるため、ASCII エンコーディングでパースするとエラーが発生します。
CI環境やコンテナ環境では LANG が設定されていないケースが多く、問題が再現しやすい状況にあります。
技術的な変更
lib/bootsnap/compile_cache/iseq.rb 内の compile_file_prism メソッドで、File.read の呼び出しに encoding: Encoding::UTF_8 を明示的に指定するよう変更されました。
変更前:
def compile_file_prism(path, options = nil)
compile_prism(::File.read(path), path, path, nil, options)
end
変更後:
def compile_file_prism(path, options = nil)
compile_prism(::File.read(path, encoding: Encoding::UTF_8), path, path, nil, options)
end
変更はこの1行のみです。Encoding::UTF_8 定数を直接指定することで、実行環境の LANG 設定やロケールに関わらず、常に UTF-8 としてソースファイルを読み込みます。
設計判断
Encoding::UTF_8 を呼び出し側で明示指定する方式 が採用されました。
Rubyのソースファイルはデフォルトで UTF-8 として扱われる(# encoding: コメントで上書き可能)という言語仕様に照らすと、パース前の読み込み時も UTF-8 を前提とするのが自然です。Encoding.default_external はあくまでユーザー向けI/Oのデフォルトであり、ソースコードのパースには適していません。
環境依存の暗黙的なデフォルト値に頼らず、意図を明示する定数を使うことで、異なるロケール設定を持つ環境間での動作の一貫性が保たれます。
まとめ
この修正は1行の変更ながら、「環境依存のデフォルト値ではなく、言語仕様に沿った明示的な指定を使う」という原則を体現しています。ロケール設定が統一されていないCI環境やコンテナ環境において、1.24.2 のワークアラウンドが安定して機能するようになります。