Project

General

Profile

Actions

Feature #20609

open

Nested module namespace misses fallback to top level

Added by abdullah.arif (Abdullah Arif) 5 months ago. Updated 5 months 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) 5 months 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