Project

General

Profile

Actions

Feature #20609

open

Nested module namespace misses fallback to top level

Added by abdullah.arif (Abdullah Arif) 11 days ago. Updated 11 days ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:118465]

Description

Currently, Ruby falls back to the top-level constants if it cannot find the Module in the local scope. This can cause it to behave unintuitively.

module A
  module B
    MY_CONST = 'defined in A::B'
  end
end

module X
end

module X::Y
  # Ruby treats A::B the same as ::A::B, because module X::Y::A is not defined. IMO this should raise a Name error or atleast a warning.
  module A::B
    # This was meant to be scoped to X::Y::A::B'
    MY_CONST = 'defined in X::Y::A::B'
  end
  puts(::A::B::MY_CONST) # => defined in X::Y::A::B
  puts(A::B::MY_CONST) # => defined in X::Y::A::B
end

puts(X::Y::A::B::MY_CONST) # uninitialized constant X::Y::A (NameError)

I think Ruby should raise an error or atleast a clear warning explaining the module it is using has different nesting than what the coder might expect.

Updated by jeremyevans0 (Jeremy Evans) 11 days ago

This is expected. When you do:

module A::B
end

Understand that in Ruby, this is a general form of:

module (expression)::B
end

Ruby resolves expression (e.g. constant lookup for A), then defines a constant B under it. In your example:

module X::Y
  module A::B # (`expression`::B) where expression is A
  end
end

The reference to A inside X::Y resolves to ::A because X::Y does not define a constant named A.

The idea that the above code should define X::Y::A::B cannot really work, because Ruby would have no knolwedge of whether to define X::Y::A as a module or as a class.

Actions

Also available in: Atom PDF

Like0
Like0