Bug #11827
closed
StringIO with set_encoding broken with enabled frozen string literal
Added by deepj (deepj #) about 9 years ago.
Updated about 9 years ago.
ruby -v:
ruby 2.3.0preview2 (2015-12-11 trunk 53028) [x86_64-darwin15]
[ruby-core:72189]
Description
I'm not sure if this the following problem is an expected behavior. But I guess, it is a bug when I run the code below. It throws `set_encoding': can't modify frozen String (RuntimeError).
# frozen_string_literal: true
io = StringIO.new('')
io.set_encoding(Encoding::BINARY)
I wouldn't expect this kind of behavior.
- Status changed from Open to Feedback
deepj # wrote:
I'm not sure if this the following problem is an expected behavior. But I guess, it is a bug when I run the code below. It throws `set_encoding': can't modify frozen String (RuntimeError).
# frozen_string_literal: true
io = StringIO.new('')
io.set_encoding(Encoding::BINARY)
I wouldn't expect this kind of behavior.
What behavior do you expect?
StringIO is a wrapper to provide IO-like interface for String, so the argument of StringIO.new
should not be copied.
s = "foo"
io = StringIO.new(s)
io.putc(?b)
p s #=> "boo"
If you specify writable mode explicitly, you can get an exception earlier:
# frozen_string_literal: true
io = StringIO.new("", "w") #=> Errno::EACCESS
Shugo Maeda wrote:
What behavior do you expect?
Not throw the exception in this case. I guess this is a better example https://github.com/rack/rack/blob/master/lib/rack/mock.rb#L139
Here is set an encoding for IO classes included StringIO. When the frozen string literal is enabled it causes a problem obviously. And there is no way (at least I haven't figured out it) how to change an encoding for a StringIO with frozen string. For me it wouldn't be any difference with I have a StringIO with a frozen string, or a File. It's just a interface with same expected behaviour of IO-like classes. In this case a change of encoding. So a string would be mutable in StringIO when it was immutable previously. I might be wrong here.
deepj # wrote:
Shugo Maeda wrote:
What behavior do you expect?
Not throw the exception in this case. I guess this is a better example https://github.com/rack/rack/blob/master/lib/rack/mock.rb#L139
Here is set an encoding for IO classes included StringIO. When the frozen string literal is enabled it causes a problem obviously. And there is no way (at least I haven't figured out it) how to change an encoding for a StringIO with frozen string. For me it wouldn't be any difference with I have a StringIO with a frozen string, or a File. It's just a interface with same expected behavior of IO-like classes. In this case a change of encoding. So a string would be mutable in StringIO when it was immutable previously. I might be wrong here.
In this case ''.force_encoding(Encoding::ASCII_8BIT)
should be String.new.force_encoding(Encoding::ASCII_8BIT)
(or String.new(encoding: Encoding::ASCII_8BIT) for Ruby 2.3)
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.
Yui NARUSE 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.
FYI, nobu figured out 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
- Status changed from Feedback to Closed
Applied in changeset r53188.
stringio.c: separate encoding from buffer
- ext/stringio/stringio.c (strio_set_encoding): add StringIO's own
encoding and separate it from the buffer string to override the
encoding of string when reading. [ruby-core:72189] [Bug #11827]
note that setting the encoding of its buffer string may cause
unpredictable behavior.
Also available in: Atom
PDF
Like0
Like0Like0Like0Like0Like0