Lots of "warning: method redefined; discarding old" printed during testing
sarna opened this issue · comments
Basic Info
- Faraday Version: 2.7.5
- Ruby Version: ruby 3.2.2 (2023-03-30 revision e51014f9c0) [arm64-darwin22]
Issue description
With warnings enabled (eg during testing), there are several lines printed with "warning: method redefined; discarding old" warnings.
Steps to reproduce
$ cat Gemfile
# frozen_string_literal: true
source "https://rubygems.org"
gem "faraday"
$ bundle install
Using bundler 2.4.7
Using faraday-net_http 3.0.2
Using ruby2_keywords 0.0.5
Using faraday 2.7.5
Bundle complete! 1 Gemfile dependency, 4 gems now installed.
Bundled gems are installed into `./vendor/bundle`
$ bundle exec irb -W
irb(main):001:0> require "faraday"
/Users/sarna/Developer/ruby/test-faraday/vendor/bundle/ruby/3.2.0/gems/faraday-2.7.5/lib/faraday/options.rb:177: warning: method redefined; discarding old user
/Users/sarna/Developer/ruby/test-faraday/vendor/bundle/ruby/3.2.0/gems/faraday-2.7.5/lib/faraday/options.rb:177: warning: method redefined; discarding old password
/Users/sarna/Developer/ruby/test-faraday/vendor/bundle/ruby/3.2.0/gems/faraday-2.7.5/lib/faraday/options.rb:177: warning: method redefined; discarding old request
/Users/sarna/Developer/ruby/test-faraday/vendor/bundle/ruby/3.2.0/gems/faraday-2.7.5/lib/faraday/options.rb:177: warning: method redefined; discarding old ssl
/Users/sarna/Developer/ruby/test-faraday/vendor/bundle/ruby/3.2.0/gems/faraday-2.7.5/lib/faraday/options.rb:177: warning: method redefined; discarding old builder_class
/Users/sarna/Developer/ruby/test-faraday/vendor/bundle/ruby/3.2.0/gems/faraday-2.7.5/lib/faraday/request.rb:48: warning: method redefined; discarding old params=
/Users/sarna/Developer/ruby/test-faraday/vendor/bundle/ruby/3.2.0/gems/faraday-2.7.5/lib/faraday/request.rb:59: warning: method redefined; discarding old headers=
/Users/sarna/Developer/ruby/test-faraday/vendor/bundle/ruby/3.2.0/gems/faraday-2.7.5/lib/faraday/request/instrumentation.rb:10: warning: method redefined; discarding old name
/Users/sarna/Developer/ruby/test-faraday/vendor/bundle/ruby/3.2.0/gems/faraday-2.7.5/lib/faraday/request/instrumentation.rb:15: warning: method redefined; discarding old instrumenter
=> true
I'm also seeing this in Faraday 2.7.5 and not in 2.7.4.
This is caused by defining methods with the same name as Struct
members.
❯ cat test.rb
X = Struct.new(:a, :b) do
def a
:other
end
end
X.new(1, 2).a # => :other
❯ ruby -W test.rb
test.rb:2: warning: method redefined; discarding old a
Before #1489, the above X
was defined by inheriting from Struct.new(:a, :b)
. I'm not sure about Ruby's internal implementation, but I guess the difference between them is the timing of the method definition. Previously, a redefined method was declared as a method of the subclass, which is just a normal overriding.
# This case just overrides the method defined by the parent class.
class X < Struct.new(:a, :b)
def a
end
end
# NOTE: The above code is the same as the below.
TMP = Struct.new(:a, :b)
class X < TMP
def a
end
end
In the latest code, redefinition occurs during the setup of Struct
. This means that defining methods from Struct
members as well as custom methods within a block of .new
is happening at the same time.
X = Struct.new(:a, :b) do
def a
end
end
# Defining the method within the block seems to be the same as the below.
class X
def a
end
def a
end
end
If possible, it might be the best to avoid defining the same name as Struct
members (e.g., user
should be renamed). However, such methods might be used by other plugins or applications, so another approach would be required.
I've proposed a fix in #1506 if you all want to take a look.
Thank you @yykamei for the eye-opening explanation and @mattbrictson for providing a fix 🙇
Thank you all ❤️