Ruby 2.2.0 now warns against a circular argument reference. It is pretty simple to demonstrate and pretty difficult to explain so I’ll just present some code snippets.
The first example shadows a function (which I have encountered in one of the open-source projects I’m involved with):
def foo 42 end def bar(foo = foo) foo end puts bar.inspect
On ruby 2.1 it just prints
42. On ruby 2.2 though:
-e:5: warning: circular argument reference - foo nil
The warning refers to the
def bar(foo = foo) definition. If you remember
a = a with
a being an uninitialized variable, initializes
a with the value of
nil. Ruby 2.1’s function definitions though was not fully following this logic and that disparity was utilized by some developers as a feature. Now in ruby 2.2 this has been fixed and recognized properly.
On the other hand when shadowing a variable instead of a function:
foo = 42 def bar(foo = foo) foo end puts bar.inspect
On ruby 2.1 it fails with:
-e:3:in `bar': undefined local variable or method `foo' for main:Object (NameError) from -e:1:in `<main>'
But on ruby 2.2, it recognizes the circular reference:
-e:3: warning: circular argument reference - foo nil
To figure out if one’s code exploits this feature/bug, one can simply run the following regexp:
ag 'def +[A-Za-z._!?]+(\(| +)([^)]+, *)?([a-z_]+) *[=:] *\3[^a-z_!?.]'
I’m assuming using The Silver Searcher and not filtering any files based on extension. Otherwise, just replace
git grep and you are good to go.
- 8th October 2015 – Update regexp to account for keyword arguments and methods ending in “!”, “?” – thanks to Alan & Andreas