🎉

[Feature #20205] frozen_string_literal をデフォルトで有効にするチケット

2024/02/23に公開

[Feature #20205] Enable frozen_string_literal by default

  • frozen_string_literal をデフォルトで有効にするチケット
  • いくつかポイントがあるんですがこの機能自体がかなり強い非互換になるので以下のような移行パスを提案している
    • Release R0: 非推奨警告を導入(非推奨警告が有効な場合のみ)
    • Release R1: 設定に関係なく非推奨警告を表示する
    • Release R2: frozen_string_literal をデフォルトで有効にする
    • NOTE: これらの移行パスは具体的にどういうバージョンで適用されるのかはまた別の話
  • また既に非推奨警告の実装は Shopify 側で実装しているらしい
    • https://github.com/Shopify/ruby/pull/549
    • かいつまむと以下のような対応らしい
      • #frozen_string_literal: true または #frozen_string_literal: false が定義されているファイルにはなにも影響がない
      • #frozen_string_literal がないファイルではコンパイル時に putstring の変わりに putchilledstring が使用される
      • putchilledstring では文字列をマークしておき、文字列が変更されたら警告を出すようにいなっている
  • 互換性に関する話としては以下のようなオプションを指定する事で互換性を保つことができる、とも書いてある
    • RUBYOPT="--disable=frozen_string_literal"
    • ちなみに既存で --enable=frozen_string_literal を指定する事ができる
  • frozen_string_literal を有効にする利点としてパフォーマンスと意図しない変更を防ぐ目的がある
  • パフォーマンスに関しては https://bugs.ruby-lang.org/issues/20205#note-4 にいくつかのライブラリのベンチマークが載っている
  • 意図しない変更、は例えば以下のようなコードとかですね
HEADER = "<html><body>"

def generate
  output = HEADER # no `.dup`
  output << "<p>test</p>" # HEADER の値が変わってしまう
  # ...
end
  • 他の論点としては --enable-frozen-string-literal を使ったほうがいいのではないか、みたいな議論もされている
  • 最終的にはこの対応自体は matz が同意しているので次の Ruby のバージョンから何かしらの対応が入りそう
  • いつになるかは置いといてまた Ruby 3.0 のキーワード引数と同じぐらいの対応が必要になってきそうですねー
GitHubで編集を提案

Discussion