Bug #19711
closedNoMethodError "private method `new' called for class" since bebd05fb51ea65bc57344b67100748200f8311eb
Description
Rails CI against ruby3.3.0dev has been failing https://buildkite.com/rails/rails/builds/96929#0188841c-cf1f-46d6-b48b-f510a5675262/1069-1078
According to git bisect, this change has been triggered via bebd05fb51ea65bc57344b67100748200f8311eb
Steps to reproduce (that may not be minimum though)¶
$ gem install activesupport
$irb
require 'active_support/deprecation'
klass = Class.new(ActiveSupport::Deprecation)
deprecator = klass.new
Expected behavior¶
It should successfully work as the previous commit does.
$ ruby -v
ruby 3.3.0dev (2023-06-02T21:16:52Z master 4e26ae3cb9) [x86_64-linux]
$ gem install activesupport
Successfully installed activesupport-7.0.5
Parsing documentation for activesupport-7.0.5
Done installing documentation for activesupport after 1 seconds
1 gem installed
$ irb
irb(main):001:0> require 'active_support/deprecation'
=> true
irb(main):002:0> klass = Class.new(ActiveSupport::Deprecation)
=> #<Class:0x00007f683e01a5b0>
irb(main):003:0> deprecator = klass.new
=>
#<#<Class:0x00007f683e01a5b0>:0x00007f683e2207b0
...
irb(main):004:0>
Actual behavior¶
It gets "(irb):5:in <main>': private method
new' called for class #Class:0x00007fbd57dd9b10 (NoMethodError)"
$ ruby -v
ruby 3.3.0dev (2023-06-03T00:35:18Z master bebd05fb51) [x86_64-linux]
$ gem install activesupport
Successfully installed activesupport-7.0.5
Parsing documentation for activesupport-7.0.5
Done installing documentation for activesupport after 1 seconds
1 gem installed
$ irb
irb(main):001:0> require 'active_support/deprecation'
=> true
irb(main):002:0> klass = Class.new(ActiveSupport::Deprecation)
irb(main):003:0> deprecator = klass.new
(irb):3:in `<main>': private method `new' called for class #<Class:0x00007f7e13282bc8> (NoMethodError)
from <internal:kernel>:187:in `loop'
from /home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/irb-1.7.0/exe/irb:9:in `<top (required)>'
from /home/yahonda/.rbenv/versions/trunk/bin/irb:25:in `load'
from /home/yahonda/.rbenv/versions/trunk/bin/irb:25:in `<main>'
irb(main):004:0>
irb(main):003:0> require 'active_support/deprecation'
=> true
irb(main):004:0> klass = Class.new(ActiveSupport::Deprecation)
=> #<Class:0x00007fbd57dd9b10>
irb(main):005:0> deprecator = klass.new
(irb):5:in `<main>': private method `new' called for class #<Class:0x00007fbd57dd9b10> (NoMethodError)
from <internal:kernel>:187:in `loop'
from /home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/irb-1.7.0/exe/irb:9:in `<top (required)>'
from /home/yahonda/.rbenv/versions/trunk/bin/irb:25:in `load'
from /home/yahonda/.rbenv/versions/trunk/bin/irb:25:in `<main>'
irb(main):006:0>
Updated by hsbt (Hiroshi SHIBATA) over 1 year ago
Updated by ioquatix (Samuel Williams) over 1 year ago
module ActiveSupport
class Deprecation
include Singleton
Why is Rails trying to call new
on a singleton class?
What is the expected behaviour of calling new on a subclass of a Singleton?
Updated by dpepper (Daniel Pepper) over 1 year ago
Looks like https://github.com/rails/rails/blob/main/activesupport/test/deprecation_test.rb calls .new
on the Deprecation Singleton a bunch of places. This behavior should not be possible on a singleton, however .new
is explicitly marked as public in InstanceDelegator.
module ActiveSupport
class Deprecation
include Singleton
include InstanceDelegator # <==
module ActiveSupport
class Deprecation
module InstanceDelegator # :nodoc:
def self.included(base)
...
base.public_class_method :new # <== makes otherwise private method public again
end
Essentially, this is what's happening:
klass = Class.new do
include Singleton
public_class_method :new
end
Class.new(klass).new # <== used to work but explodes after the change
The Singleton PR inadvertently changed .new
to be marked private in both included and inherited (priorly just the when included), hence .new
was made private, public, then unexpectedly private again. I agree with ioquatix in wondering why .new
is called on a singleton, but happy to scope down the Singleton change to avoid changing behavior until we want to do that explicitly.
Updated by ioquatix (Samuel Williams) over 1 year ago
@yahonda (Yasuo Honda) do you have any opinion on Rails' usage as outlined above?
Updated by byroot (Jean Boussier) over 1 year ago
do you have any opinion on Rails' usage as outlined above?
Before even looking at the issue, we'll fix it if necessary, but we need advance notice first, otherwise this will cause a mess for people upgrading to 3.3.
Updated by yahonda (Yasuo Honda) over 1 year ago
This code was added almost 10 years ago via https://github.com/rails/rails/commit/71993c6f9770b1350aa41fe8c68f1dd2c7800403 and I have not found the reason why yet.
My opinion is I also want some deprecation cycle before dropping this behavior.
Updated by jeremyevans0 (Jeremy Evans) over 1 year ago
- Status changed from Open to Closed