Skip to content

Conversation

@andynu
Copy link

@andynu andynu commented Oct 31, 2025

Fixes #139

Problem

PR #123 fixed frozen string warnings on line 127, but missed warnings triggered by calling binmode and set_encoding on StringIO objects. Rails applications running tests with verbose warnings (-W2) see this warning repeatedly:

/gems/marcel-1.1.0/lib/marcel/magic.rb:120: warning: literal string will be frozen in the future

Solution

Make StringIO readonly before encoding modifications to prevent the warning:

# Make StringIO readonly before encoding changes to prevent Ruby 3.4 frozen string warnings.
# Should be fixed in Ruby 3.5+: https://redmine.ruby-lang.org/issues/21280
io.close_write if io.respond_to?(:closed_write?) && !io.closed_write?

io.binmode if io.respond_to?(:binmode)
io.set_encoding(Encoding::BINARY) if io.respond_to?(:set_encoding)

How it works:

  • StringIO objects have a closed_write? method that File objects don't
  • Calling close_write makes the StringIO readonly, preventing internal string modifications
  • This prevents the frozen string warning when binmode/set_encoding are subsequently called
  • File objects don't have closed_write?, so they're unaffected

Why this approach:

  • Uses respond_to? pattern consistently with existing code
  • still calls binmode and set_encoding as originally intended
  • Proactively checks writability before calling (no rescue needed)
  • Only affects StringIO, which is the only IO type that triggers these warnings

Testing

Added a test that captures stderr and verifies no frozen string warnings when processing StringIO objects. All 384 existing tests pass. The test provides a runnable example that demonstrates the fix works correctly.

Future

This workaround should only be needed until Ruby 3.5, which will include an upstream fix that prevents false-positive warnings on StringIO encoding operations: https://redmine.ruby-lang.org/issues/21280

@andynu andynu force-pushed the fix-ruby34-frozen-string-warnings branch 2 times, most recently from 40b6a4c to 38b0819 Compare October 31, 2025 18:24
PR rails#123 fixed frozen string warnings on line 127 (buffer creation)
but missed the warnings triggered by calling binmode/set_encoding on
StringIO objects.

These methods modify StringIO's internal string encoding, which
triggers Ruby 3.4 deprecation warnings when running with verbose
warnings (-W2), which Rails test suites use by default.

Solution: Make StringIO readonly before encoding modifications by
calling close_write. This prevents the internal string modification
that triggers the warning, while still allowing binmode/set_encoding
to execute normally. Only affects StringIO objects (which have
closed_write? method) - File objects are unaffected.

This workaround should only be needed until Ruby 3.5, which will
include an upstream fix: https://redmine.ruby-lang.org/issues/21280
@andynu andynu force-pushed the fix-ruby34-frozen-string-warnings branch from 38b0819 to 25b6571 Compare October 31, 2025 20:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Marcel 1.1.0 emits Ruby 3.4 frozen string literal deprecation warnings

1 participant