-
-
Notifications
You must be signed in to change notification settings - Fork 386
Add frozen_string_literal magic comments #858
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
Add frozen_string_literal magic comments #858
Conversation
Codecov ReportAll modified lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #858 +/- ##
=======================================
Coverage 98.19% 98.19%
=======================================
Files 14 14
Lines 555 555
=======================================
Hits 545 545
Misses 10 10
☔ View full report in Codecov by Sentry. |
lib/inherited_resources/version.rb
Outdated
module InheritedResources | ||
VERSION = '1.13.1'.freeze | ||
VERSION = '1.13.1' |
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.
This should remain as is because frozen_string_literal
is opt-in even with Ruby 3.0 where it was no longer decided to make it the default.
VERSION = '1.13.1' | |
VERSION = '1.13.1'.freeze |
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.
Hi, can I have a clarification?
Does it mean that even if the # frozen_string_literal: true
magic comment is present in this file, there are chances that VERSION
is not frozen?
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.
Sure. Yes because you have to run Ruby with the option for enabling frozen string literals, otherwise the comment does nothing. It's opt-in. Originally, it was planned to make the option enabled by default in Ruby 3.0 but that was retracted. I don't know if they still intend to enable it by default in future major versions.
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.
So let's say that I have
test-frozen.rb
# frozen_string_literal: true
puts 'hello'.frozen?
How I can run this file to get false
?
I can see that there as option to opt-in and to allow a file without the magic comment to automatically freeze the strings, but I cannot see a "disable" option to override the magic comment
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.
To clarify a bit, frozen_string_literal
has been around for awhile (initial googling suggests 2.3). It was proposed to turn that on by default for 3.0, as in, that is the behavior you get without the magic comment. But that didn't end up happening.
I haven't found a way that you can disable using frozen_string_literal
for turning ON frozen strings, just enabling/disabling using frozen string literals globally without needing to use the magic comment.
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.
@javierjulio I still do not get why is that needed. It also triggers a RuboCop offense:
$ cat version.rb
# frozen_string_literal: true
module InheritedResources
VERSION = '1.13.1'.freeze
end
$ rubocop version.rb
Inspecting 1 file
C
Offenses:
version.rb:4:13: C: [Correctable] Style/RedundantFreeze: Do not freeze immutable objects, as freezing them has no effect.
VERSION = '1.13.1'.freeze
^^^^^^^^^^^^^^^
1 file inspected, 1 offense detected, 1 offense autocorrectable
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'm more interested in landing the rest of this PR than the specifics of this one file 😅 I made the change to use .freeze, but I agree with @tagliala .
I'm happy to do any other changes to get this accepted, but wanted to "Allow edits by maintianers" is checked if that is easier.
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.
Then why not disable it in the file and leave the .freeze
call in place? This would satisfy both sides. The point I was trying to make is that the change here assumes its only for those the are enabling the feature with the --enable=frozen-string-literal
flag but if you are not, then this would be unfrozen now. Why not just disable the global setting in this single file using the magic comment and leave the .freeze
call here? Am I missing something?
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.
Sure, that works for me. I pushed up that change.
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.
Hello,
sorry for the silence here
The point I was trying to make is that the change here assumes its only for those the are enabling the feature with the --enable=frozen-string-literal flag but if you are not, then this would be unfrozen now
My interpretation for the above sentence is: "instead of adding a magic comment to each file, it is possible to frozen string literals with --enable=frozen-string-literal
command line option".
At that point, the magic comment can work in the opposite way, also mentioned in the linked answer, by specifying # frozen_string_literal: false
So, I would say that if # frozen_string_literal: true
is present, all literals present in the file are frozen, without the possibility for the developer to unfreeze them (*)
Moreover, there isn't a command line option --disable=frozen-string-literal
, which would invalidate the magic comment, but even in those cases, if a user is deliberately adding that command line option, that should be honored so an unfrozen string would not be a problem
Case 1: no freeze
, no magic comment
ELSA = 'Elsa'
puts ELSA.frozen?
$ ruby elsa.rb
false
$ ruby --enable=frozen-string-literal elsa.rb
true
Case 2: no freeze
, magic comment with true
# frozen_string_literal: true
ELSA = 'Elsa'
puts ELSA.frozen?
$ ruby elsa_fsl_true.rb
true
$ ruby --enable=frozen-string-literal elsa_fsl_true.rb
true
Case 3: no freeze
, magic comment with false
# frozen_string_literal: false
ELSA = 'Elsa'
puts ELSA.frozen?
$ ruby elsa_fsl_false.rb
false
$ ruby --enable=frozen-string-literal elsa_fsl_false.rb
false
Case 4: freeze
, no magic comment
ELSA = 'Elsa'.freeze
puts ELSA.frozen?
$ ruby elsa_freeze.rb
true
$ ruby --enable=frozen-string-literal elsa_freeze.rb
true
Case 5: freeze
, magic comment true
Skipping example because it's trivial (all true)
Case 6: freeze
, magic comment false
# frozen_string_literal: false
ELSA = 'Elsa'.freeze
puts ELSA.frozen?
$ ruby elsa_freeze_fsl_false.rb
true
$ ruby --enable=frozen-string-literal elsa_freeze_fsl_false.rb
true
Since we are in Case 2 (no freeze
, magic comment true
) it should be guaranteed that the string is frozen.
This should be the reason why RuboCop triggers an auto-correctable safe offense when developers try to add freeze
on Case 2 scenarios
$ cat elsa_fsl_true_freeze.rb
# frozen_string_literal: true
ELSA = 'Elsa'.freeze
puts ELSA.frozen?
$ rubocop elsa_fsl_true_freeze.rb
Inspecting 1 file
C
Offenses:
elsa_fsl_true_freeze.rb:3:8: C: [Correctable] Style/RedundantFreeze: Do not freeze immutable objects, as freezing them has no effect.
ELSA = 'Elsa'.freeze
^^^^^^^^^^^^^
1 file inspected, 1 offense detected, 1 offense autocorrectable
$ rubocop -a elsa_fsl_true_freeze.rb
Inspecting 1 file
C
Offenses:
elsa_fsl_true_freeze.rb:3:8: C: [Corrected] Style/RedundantFreeze: Do not freeze immutable objects, as freezing them has no effect.
ELSA = 'Elsa'.freeze
^^^^^^^^^^^^^
1 file inspected, 1 offense detected, 1 offense corrected
$ cat elsa_fsl_true_freeze.rb
# frozen_string_literal: true
ELSA = 'Elsa'
puts ELSA.frozen?
(*) The only possibility for the developer to unfreeze would be to edit the file and remove the magic comment. If we fear such a possibility, then we should also freeze
all other literals in all other files
caf9e47
to
01f48d6
Compare
I spotted this while profiling my app with memory_profiler. InheritedResouces::UrlHelpers#define_params_helper showed up, where it allocated some 12320 blank strings (`''`). It isn't much relatively by itself, but it adds up. Update lib/inherited_resources/url_helpers.rb Co-authored-by: Javier Julio <[email protected]>
78d3ec3
to
708ed61
Compare
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.
Thanks!
I spotted this while profiling my app with memory_profiler. InheritedResouces::UrlHelpers#define_params_helper showed up, where it allocated some 12320 blank strings (
''
).It isn't much relatively by itself, but it adds up.