Project

General

Profile

Feature #11460

Unhelpful error message when naming a module with the same name as an existing class

Added by iMIchael (Michael Martinez) about 4 years ago. Updated about 2 months ago.

Status:
Feedback
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:<unknown>]

Description

Summary

The error message when naming a module with the same name as an existing class causes more trouble then it helps.

Steps to Reproduce

class X;end
module X;end
=> TypeError: X is not a module

Expected Results

Ruby has this very helpful and explicit error when reassigning a value to an existing constant.

A = 1
A = 2
warning: already initialized constant A
warning: previous definition of A was here

which makes me expect Ruby to keep track of names of global constants and prevent me from colliding names with helpful warnings. This warning however raises a "Type error" which is not very intuitive. When users think of type errors they think of things like "foo" * "foo" => TypeError: no implicit conversion of String into Integer.

Actual Results

Confusion about what the actual error is, especially for people learning Ruby.


Files

mod-reopen-error-message.patch (2.82 KB) mod-reopen-error-message.patch jeremyevans0 (Jeremy Evans), 07/03/2019 11:05 PM
0001-Show-the-previous-definition-location.patch (4.89 KB) 0001-Show-the-previous-definition-location.patch nobu (Nobuyoshi Nakada), 07/04/2019 08:22 AM

History

Updated by jeremyevans0 (Jeremy Evans) about 2 months ago

The reason for the difference in behavior here is due to Ruby's open classes. When using class X or module X, if the constant X is already defined, Ruby will reopen the class or module definition, so you can operate in the context of the class or module. However, attempting to reopen a class when the object is not actually a class is a error, whereas reassigning a constant is just a warning.

The warning message you get during constant reassignment is used for classes and modules if you assign them:

X = Class.new
X = Module.new
# warning: already initialized constant X
# warning: previous definition of X was here

Likewise, the error raised when attempting to reopening an existing constant is pretty much the same for all objects that don't match the expected type:

X = 1
class X; end
# TypeError (X is not a class)
module X; end
# TypeError (X is not a module)

So I don't think there is a bug here. It is possible to change the format the error message, though. Attached is a patch that changes the error message to the include the current class of the object:

class X;end
module X;end
# TypeError (X is not a module, it is a Class)
module Y;end
class Y;end
# TypeError (Y is not a class, it is a Module)

I would appreciate feedback on whether this more detailed error message is an improvement.

Updated by duerst (Martin Dürst) about 2 months ago

jeremyevans0 (Jeremy Evans) wrote:

So I don't think there is a bug here. It is possible to change the format the error message, though. Attached is a patch that changes the error message to the include the current class of the object:

class X;end
module X;end
# TypeError (X is not a module, it is a Class)
module Y;end
class Y;end
# TypeError (Y is not a class, it is a Module)

I would appreciate feedback on whether this more detailed error message is an improvement.

I think it is.

Updated by nobu (Nobuyoshi Nakada) about 2 months ago

Is “a Integer” OK? :)

Updated by sawa (Tsuyoshi Sawada) about 2 months ago

nobu (Nobuyoshi Nakada) wrote:

Is “a Integer” OK? :)

"a(n) Integer"

#5

Updated by nobu (Nobuyoshi Nakada) about 2 months ago

Updated by shevegen (Robert A. Heiler) about 2 months ago

I would appreciate feedback on whether this more detailed error message is an improvement.

I think this depends on what the ruby user at hand is doing; and how much expertise that
ruby user may have. Some behaviour in ruby can be confusing to newcomers, such as when
variables may be assigned to nil, without explicit "x = nil".

I personally do not really need a change either way in the context of this suggestion (I
am fine with the current behaviour), but I think it is not completely unreasonable to
assume that there could be use cases for letting ruby be more verbose in this (or
similar) situation, if it leads to an improvement such as less confusion for newcomers.

In the long run it may be good to sort of have ruby in different "modes"; a bit like
the did-you-mean gem and the -w flag for running ruby code, but with more control over
the messages (as long as they are just warnings, but perhaps also some that relate to
errors, in particular when ruby interacts with the user). But as written before, I am
really mostly neutral either way - not really decidedly adopting any pro or con
opinion, just commenting to the question by jeremy. :-)

Also available in: Atom PDF