Skip to content
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

Style/RedundantInterpolation auto-correct should not be marked safe or should be implemented differently #10656

Closed
jimryan opened this issue May 20, 2022 · 0 comments · Fixed by #10663
Labels

Comments

@jimryan
Copy link

jimryan commented May 20, 2022

The Style/RedundantInterpolation cop's auto-correct should not be marked safe because it cannot guarantee that subsequent code wasn't relying on the "redundant" interpolation essentially dup'ing the string.

I've put together a brief demo of two scenarios where replacing the interpolation with to_s fails to produce equivalent code: https://github.com/jimryan/rubocop-redundant-interpolation-unsafe-autocorrect-demo

An alternative solution to not marking as safe would be to replace redundant string interpolations with .to_s.dup which is more precisely what the redundant interpolation was doing. E.g. "#{foo}" becomes foo.to_s.dup. I believe that would be safe.


Expected behavior

Autocorrection should not be marked "safe" for this cop. I would not expect the potential for an error or change in behavior of any kind after running a safe auto-correction.

Alternative behavior could be to replace redundant string interpolations with to_s.dup.

Actual behavior

It is marked safe, yet safe autocorrection can break/change code in some scenarios.

Steps to reproduce the problem

Steps are in the README of the demo repo, but in general:

  1. Write code that interpolates a string and stores it in a new variable
  2. Mutate that string
  3. Style/RedundantInterpolation will replace that interpolation with .to_s on the original string, which just returns the same String object. Now the mutation is mutating the original string (the one that was interpolated), and not a copy of it. When a string is the subject of the redundant interpolation, the interpolation is equivalent to dup, not to_s.

RuboCop version

$ [bundle exec] rubocop -V
1.29.1 (using Parser 3.1.2.0, rubocop-ast 1.18.0, running on ruby 2.7.6 arm64-darwin21)
@jimryan jimryan changed the title Style/RedundantInterpolation auto-correct should not be marked safe or should be implemented differently Style/RedundantInterpolation auto-correct should not be marked safe or should be implemented differently May 20, 2022
@koic koic added the bug label May 23, 2022
koic added a commit to koic/rubocop that referenced this issue May 23, 2022
…ocorrection

Fixes rubocop#10656.

This PR marks `Style/RedundantInterpolation` as unsafe autocorrection
because when calling a destructive method to string, the resulting
string may have different behavior or raise `FrozenError`.

```ruby
x = 'a'
y = "#{x}"
y << 'b'   # return 'ab'
x          # return 'a'
y = x.to_s
y << 'b'   # return 'ab'
x          # return 'ab'

x = 'a'.freeze
y = "#{x}"
y << 'b'   # return 'ab'.
y = x.to_s
y << 'b'   # raise `FrozenError`.
```

Updating the auto-corrected code from `'a'.to_s` to `'a'.to_s.dup` will get safe, but it
will make `dup` redundant when unneeded. And This would go against the cop's name "redundant".
That means replacing it with a different redundancy that cannot be removed by static analysis.
So I decided to mark it as unsafe.
bbatsov pushed a commit that referenced this issue May 23, 2022
…tion

Fixes #10656.

This PR marks `Style/RedundantInterpolation` as unsafe autocorrection
because when calling a destructive method to string, the resulting
string may have different behavior or raise `FrozenError`.

```ruby
x = 'a'
y = "#{x}"
y << 'b'   # return 'ab'
x          # return 'a'
y = x.to_s
y << 'b'   # return 'ab'
x          # return 'ab'

x = 'a'.freeze
y = "#{x}"
y << 'b'   # return 'ab'.
y = x.to_s
y << 'b'   # raise `FrozenError`.
```

Updating the auto-corrected code from `'a'.to_s` to `'a'.to_s.dup` will get safe, but it
will make `dup` redundant when unneeded. And This would go against the cop's name "redundant".
That means replacing it with a different redundancy that cannot be removed by static analysis.
So I decided to mark it as unsafe.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants