Project

General

Profile

Actions

Bug #21280

open

StringIO#set_encoding warns when backed by chilled string literal

Added by jeremyevans0 (Jeremy Evans) 5 days ago. Updated about 3 hours ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:121702]

Description

StringIO#set_encoding changes the underlying string encoding if the string is not frozen, but does not change the underlying string encoding if the string is frozen. In Ruby 3.4, this results in a warning for chilled literal strings:

$ ruby34 -w -r stringio -e "StringIO.new('').set_encoding('binary')"
-e:1: warning: literal string will be frozen in the future (run with --debug-frozen-string-literal for more information)

I believe Ruby should emit this warning only for cases that will break when string literals are frozen. This is not one of those cases, so Ruby should not emit the warning. To avoid emitting the warning, I think StringIO#set_encoding should not set the encoding on the underlying string for chilled literal strings. I submitted a pull request to avoid changing the encoding of the underlying string: https://github.com/ruby/stringio/pull/128

However, @rhenium (Kazuki Yamaguchi) said that he thought the encoding of the underlying string should still be changed, and the warning should be emitted (https://github.com/ruby/stringio/pull/128#issuecomment-2818362875).

For some history, before Ruby 2.3, StringIO#set_encoding used to always set the encoding of the underlying string. This was changed in #11827, when the encoding was not set on the underlying string if the string was frozen (3e1c01ae463a8c9d8bbe9050251a2538ddb0292f).

In https://bugs.ruby-lang.org/issues/11827#note-3, @nurse wrote:

Away from the case and thinking ideal behavior, StringIO should be a view of given source string and set_encoding shouldn't change source encoding.
But I'm not sure that it is worth breaking the compatibility.

I think this means that ideally, absent backwards compatibility issues, StringIO#set_encoding should never change the underlying string encoding.

In https://bugs.ruby-lang.org/issues/11827#note-4, @shugo (Shugo Maeda) gave an example from @nobu (Nobuyoshi Nakada) that open-uri depends on the current behavior:

      enc = Encoding::ASCII_8BIT unless enc
      if self.respond_to? :force_encoding
        self.force_encoding(enc)
      elsif self.respond_to? :string
        self.string.force_encoding(enc)
      else # Tempfile
        self.set_encoding enc
      end
    end

However, as StringIO#string is defined, this will call self.string.force_encoding(enc) and not self.set_encoding enc, so I'm not sure why a change to String#set_encoding would affect the behavior of this example.

@rhenium (Kazuki Yamaguchi) pointed out that this issue affects StringIO#binmode and StringIO#set_encoding_by_bom as well as StringIO#encoding.

How do we want to handle this case? Should this result in a warning (current behavior), or is it safe to avoid changing the encoding of the underlying string for chilled strings (as is done for frozen strings)?

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0