[Bug #21280] StringIO#set_encoding でチルド文字列の警告が出てしまうチケット

に公開

[Bug #21280] StringIO#set_encoding warns when backed by chilled string literal

  • StringIO#set_encoding では以下のような挙動になっています
    • 元の文字列が frozen でない場合はエンコーディングを変更する
    • 元の文字列が frozen されている場合はエンコーディングを変更しない
require "stringio"

str = "hoge"
pp str.encoding # => #<Encoding:UTF-8>

# これはエンコーディングが変更される
StringIO.new(str).set_encoding('binary')
pp str.encoding # => #<Encoding:BINARY (ASCII-8BIT)>

# これはエンコーディングが変更されない
StringIO.new(str.freeze).set_encoding('UTF-8')
pp str.encoding # => #<Encoding:BINARY (ASCII-8BIT)>
  • これを踏まえた上で Ruby 3.4 では StringIO#set_encoding 時にチルド文字列に対して警告が出力されます
Warning[:deprecated] = true

require "stringio"

# warning: literal string will be frozen in the future (run with --debug-frozen-string-literal for more information)
StringIO.new("hoge").set_encoding('binary')
  • このチケットではこの警告が出力されるのは適切でないのではないか、という内容です
  • 適切でない理由としては『件の警告が出力されるのは『文字列リテラルが frozen になった場合に壊れるケース』である』という話みたいですね
    • それが今回のケースでは適切でない、という話みたい
  • その上で『 StringIO#set_encoding では元の文字列のエンコーディングを変更しない』という対処をするのが最初の話だったみたいです
  • ただ、『 StringIO#set_encoding では元の文字列のエンコーディングを変更する必要がある』という話もあるみたいでそのあたりで議論しているみたいですね
  • 最終的には『 StringIO#set_encoding の挙動は変えずに警告のみ削除する』という対応になったみたいですね
Warning[:deprecated] = true

require "stringio"

StringIO.new("hoge").set_encoding('binary')
# Ruby 3.4 => warning: literal string will be frozen in the future (run with --debug-frozen-string-literal for more information)
# Ruby 3.5 => no warning
  • なんですが現時点だと Ruby 3.5 では StringIO#set_encoding で『元の文字列のエンコーディングを変更しない』ようになっているんですよねー
pp RUBY_DESCRIPTION
# => "ruby 3.5.0dev (2025-06-26T04:28:24Z master 5e9be99ef5) +PRISM [x86_64-linux]"

require "stringio"

str = "hoge"
StringIO.new(str).set_encoding('binary')

pp str.encoding
# Ruby 3.4 => #<Encoding:BINARY (ASCII-8BIT)>
# Ruby 3.5 => #<Encoding:UTF-8>
  • これが意図する変更なのかそうでないのかはよくわかってない
GitHubで編集を提案

Discussion