-
Notifications
You must be signed in to change notification settings - Fork 76
Fix frozen string literal warning in magic detection #123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Tests pass on my machine and GH Actions, the Buildkite build erroring out seems unrelated and not fixable from this PR. |
| io.binmode if io.respond_to?(:binmode) | ||
| io.set_encoding(Encoding::BINARY) if io.respond_to?(:set_encoding) | ||
| buffer = "".encode(Encoding::BINARY) | ||
| buffer = (+"").encode(Encoding::BINARY) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this is better for readability:
| buffer = (+"").encode(Encoding::BINARY) | |
| buffer = String.new.encode(Encoding::BINARY) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see from the bench-marking that you did already consider that option. Also this is more succinct hence better.
| buffer = (+"").encode(Encoding::BINARY) | |
| buffer = String.new(encoding: Encoding::BINARY) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please disregard!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think what you want here is to declare a mutable string with binary encoding. That's
String.new(encoding: Encoding::BINARY)
|
I’m not sure whether this actually fixes the issue I was trying to fix — tried to bundle install marcel from my repo and it still appeared — but this should still be a slight improvement |
As mentioned in the comments, rails/marcel#123 PR should make this go away. This is just for cosmetic reasons. The warning makes the test suite output look untidy.
| io.binmode if io.respond_to?(:binmode) | ||
| io.set_encoding(Encoding::BINARY) if io.respond_to?(:set_encoding) | ||
| buffer = "".encode(Encoding::BINARY) | ||
| buffer = (+"").encode(Encoding::BINARY) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| buffer = (+"").encode(Encoding::BINARY) | |
| buffer = String.new(encoding: Encoding::BINARY) |
|
Hey, can we try to get this merged in? A lot of our tests are failing on ruby 3.4.4 because of this. And instead of recording deprecations, I would like this to be fixed. Let me know if I can help in any way |
|
still getting warnings even after this patch |
|
Bumping this as there's not been a response to the "still broken" comments after merge and they may have been missed. I'm still seeing these with 1.1.0 too: |
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 at lines 123-124. StringIO is always binary-capable and doesn't need these method calls. Calling them triggers Ruby 3.4 deprecation warnings when running with verbose warnings (-W2), which Rails test suites use by default. This change skips binmode/set_encoding for StringIO objects while maintaining the existing defensive respond_to? checks for File objects.
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 at lines 123-124. 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. Skip these calls for StringIO objects since marcel's byte-reading operations work correctly without the encoding modification, as demonstrated by all 384 tests passing. This maintains the existing defensive respond_to? checks for File objects.
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 at lines 120-121. 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. Skip these calls for StringIO objects since marcel's byte-reading operations work correctly without the encoding modification, as demonstrated by all 384 tests passing. This maintains the existing defensive respond_to? checks for File objects.
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


With latest Ruby 3.4.x, using marcel emits the following warning:
lib/ruby/gems/3.4.0/gems/marcel-1.0.4/lib/marcel/magic.rb:120: warning: literal string will be frozen in the futureThis occurs because the code was creating an empty string literal used as mutable buffer for I/O operations.
This pull request replaces
"".dup.encode(Encoding::BINARY)with(+"").encode(Encoding::BINARY)in the buffer creation. Using the unary plus operator to explicitly create a mutable string benchmarked slightly faster than.dup.encode()on my local machine.Benchmark Results
String Creation Performance (1M iterations)
"".dup.encode()(+"").encode()String.new(encoding:)Memory Allocation (100K iterations)
"".dup.encode()(+"").encode()String.new(encoding:)Real-world Usage (10K magic detection operations)
"".dup.encode()(+"").encode()String.new(encoding:)