Issue #6810 has been updated by alexeymuranov (Alexey Muranov).


fxn (Xavier Noria) wrote:
> Yes, this is expected.
> 
> The resolution algorithm first checks the modules in the nesting (in their very constants table, it ignores their ancestors), then the ancestors of the module the constants appears in (the first one in the nesting, or Object if the nesting is empty), and if the former is a module, then Object is checked by hand (and it still tries const_missing if all fails).
> 
> The key to understand those examples, in addition to the algorithm, is to be aware of the respective nestings:
> 
>     module A
>       module B
>         Module.nesting # => [A::B, A]
>       end
>     end
> 
> whereas
> 
>     module A::B
>       Module.nesting # => [A::B]
>     end
> 
> In the second case A is not checked, since it is not in the nesting, it is not an ancestor of A::B, and it is not Object.
> 
> The nesting is only modified by the class and module keywords, and by opening a singleton class with class << object (and some other obscure cases related to string eval'ing). In particular, the nesting inside and outside class methods defined with def self... is the same.

Xavier, thanks for the explanation, i see now why it works this way, so this is not a bug.  However, can anybody please explain to me why this is a desired behavior, i mean the way the nesting is calculated?  Wouldn't it be easier if

  module A; end
  module A::B;
    # do something
  end

was equivalent to

  module A
    module B
      # do something
    end
  end

?
----------------------------------------
Bug #6810: `module A::B; end` is not equivalent to `module A; module B; end; end` with respect to constant lookup (scope)
https://bugs.ruby-lang.org/issues/6810#change-28513

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee: 
Category: core
Target version: 
ruby -v: ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin10.8.0]


=begin
Is this the expected behavior?  To me it is rather surprising:

 N = 0

 module A
   module B
     def self.f; N; end
   end
   N = 1
 end

 A::B.f # => 1

but

 N = 0

 module A; end

 module A::B
   def self.f; N; end
 end

 module A
   N = 1
 end

 A::B.f # => 0

Even more striking:

 module A
   module B
     def self.f; N; end
   end
 end

 N = 0

 A::B.f # => 0

 A::N = 1

 puts A::B.f # => 1

 A::B::N = 2

 A::B.f # => 2

but

 module A; end

 module A::B
   def self.f; N; end
 end

 N = 0

 A::B.f # => 0

 A::N = 1

 A::B.f # => 0

 A::B::N = 2

 A::B.f # => 2


=end


-- 
http://bugs.ruby-lang.org/