lostisland / faraday

Simple, but flexible HTTP client library, with support for multiple backends.
https://lostisland.github.io/faraday
MIT License
5.74k stars 976 forks source link

Lots of "warning: method redefined; discarding old" printed during testing #1505

Closed sarna closed 1 year ago

sarna commented 1 year ago

Basic Info

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
nholden commented 1 year ago

I'm also seeing this in Faraday 2.7.5 and not in 2.7.4.

iMacTia commented 1 year ago

This is probably a side-effect of #1489 and #1491 (cc @bdewater). The warnings don't hurt, but I'd prefer them to go away as well if possible.

I don't like that memoized stuff going on in there and I'm not sure I fully understand why we need it, I'll need some time to look into this 👀

yykamei commented 1 year ago

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
yykamei commented 1 year ago

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.

mattbrictson commented 1 year ago

I've proposed a fix in #1506 if you all want to take a look.

iMacTia commented 1 year ago

Thank you @yykamei for the eye-opening explanation and @mattbrictson for providing a fix 🙇

sarna commented 1 year ago

Thank you all ❤️