Project

General

Profile

Actions

Bug #8297

closed

extend & inherited class variable issue

Added by dunric (David Unric) over 11 years ago. Updated over 5 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
2.0.0p0
Backport:
[ruby-core:54463]

Description

=begin
By the current documentation, (({Object#extend})) method has to (only) add instance methods of a module given as a parameter.
In the following example, the class ((|C|)) is extended with module ((|M|)).
By (({class_variables})) method sent to singleton class of C also did inherit class variable ((|@@xyz|)).
However when inherited ((|@@xyz|)) is accessed, (({NameError})) exception is raised as it is was not initialized.

module M
@@xyz = 123
end
M.class_variables # [:@@xyz]
M.class_variable_get :@@xyz # 123 , so far so good

class C
extend M
end
p C.singleton_class.class_variables # [:@@xyz]
p C.singleton_class.class_variable_get :@@xyz # NameError exception

Either (({class_variables})) returns invalid array - ie. ((|@@xyz|)) was not inherited at all or (({class_variable_get})) ignores class variables inherited from module (when sent to a singleton).
=end
Prior Ruby versions like 1.9.3p392 does not suffer this issue as return with Module#class_variables returns an empty array.


Files

Updated by dunric (David Unric) over 11 years ago

=begin
By the current documentation, Object#extend method has to (only) add instance methods of a module given as a parameter.
In the following example, the class ((C)) is extended with module ((M)).
By ((class_variables)) method sent to singleton class of C also did inherit class variable ((@@xyz)).
However when inherited ((@@xyz)) is accessed, ((NameError)) exception is raised as it is was not initialized:

module M
@@xyz = 123
end

M.class_variables # [:@@xyz]
M.class_variable_get :@@xyz # 123 , so far so good

class C
extend M
end
p C.singleton_class.class_variables # [:@@xyz]
p C.singleton_class.class_variable_get :@@xyz # NameError exception

Either ((class_variables)) returns invalid array - ie. ((@@xyz)) was not inherited at all or ((class_variable_get)) ignores class variables inherited from module (when sent to a singleton).

Prior Ruby versions like 1.9.3p392 does not suffer this issue as Module#class_variables returns an empty array.
=end

Updated by nobu (Nobuyoshi Nakada) over 11 years ago

  • Description updated (diff)

Updated by jsc (Justin Collins) almost 6 years ago

This appears to still be an issue with Ruby 2.6.0 (ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-linux]):

Example:

module M
  @@xyz = 123
end

puts "M.class_variables: #{M.class_variables.inspect}"
puts "M.class_variable_get :@@xyz: #{M.class_variable_get :@@xyz}"

class C
  extend M
end

puts "C.class_variables: #{C.class_variables.inspect}"
puts "C.class_variable_get :@@xyz: #{C.class_variable_get :@@xyz}"

Output:

M.class_variables: [:@@xyz]
M.class_variable_get :@@xyz: 123
C.class_variables: []
Traceback (most recent call last):
	1: from 8297.rb:13:in `<main>'
8297.rb:13:in `class_variable_get': uninitialized class variable @@xyz in C (NameError)

Updated by jeremyevans0 (Jeremy Evans) over 5 years ago

This bug is still present in the master branch. I think the best way to fix it is to modify Module#class_variables for singleton classes of classes/modules to use the same lookup order as Module#class_variable_get:

  • Singleton Class
  • Class
  • All Ancestors of Class

Note that this does not include modules included in the singleton class.

Attached is a patch that implements this behavior.

Actions #5

Updated by jeremyevans (Jeremy Evans) over 5 years ago

  • Status changed from Open to Closed

Applied in changeset git|7470f965650bf17875632f0c5f9e5a4d9de9fc3f.


Fix Module#class_variables for singleton classes of classes/modules

Module#class_variables should reflect class variable lookup. For
singleton classes of classes/modules, this means the lookup should
be:

  • Singleton Class
  • Class
  • All Ancestors of Class

Note that this doesn't include modules included in the singleton
class, because class variable lookup doesn't include those.

Singleton classes of other objects do not have this behavior and
always just search all ancestors of the singleton class, so do not
change the behavior for them.

Fixes [Bug #8297]

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0