Feature #20912
closedAdd warning when redefining __id__ as well as object_id
Description
Currently if you create a class and redefine or remove either object_id
or __send__
it will issue a warning. There's no such warning on __id__
.
❯ ruby -we 'class << Object.new; def object_id = 1; end'
-e:1: warning: redefining `object_id' may cause serious problems
❯ ruby -we 'class << Object.new; def __id__ = 1; end'
❯
It makes sense that there's no warning on send
, because we expect __send__
to be the method reliably available. __send__
is on BasicObject
, send
is only on Kernel
. This seems a little inconsistent that object_id
warns while __id__
does not warn. __id__
is the equivalent to __send__
as it's also on BasicObject
, where object_id
is only on Kernel
.
This may be a more obvious problem in Ruby 3.4.0 as commit:cffd380390967d17899fde0a81f5151ae6ddd076 makes the warning print in more cases.
I propose we change this warning to be emitted only when __id__
is redefined and not when object_id
is redefined:
Proposed behaviour:
❯ ruby -we 'class << Object.new; def object_id = 1; end'
❯ ruby -we 'class << Object.new; def __id__ = 1; end'
-e:1: warning: redefining `__id__' may cause serious problems
❯
Updated by jhawthorn (John Hawthorn) 22 days ago
Updated by nobu (Nobuyoshi Nakada) 22 days ago
Agree that __id__
should be warned.
As for object_id
, do you want to redefine it?
Updated by jhawthorn (John Hawthorn) 22 days ago
nobu (Nobuyoshi Nakada) wrote in #note-2:
As for
object_id
, do you want to redefine it?
I think it's best not to redefine, but a warning is probably more severe than is needed. I don't think it causes "serious problems", especially because since object_id
doesn't exist on BasicObject
calling code can't expect all objects to have the default implementation of object_id
.
Updated by byroot (Jean Boussier) 22 days ago
do you want to redefine it?
Shopify has case like this where one of the GraphQL attribute is object_id
and that cause a warning to be emitted. I also know the Facebook API has (or used to have) an object_id
field.
Overall, it's not very common, but not totally rare either to want to redefine object_id
.
Updated by mame (Yusuke Endoh) 22 days ago
I think it's a good idea to warn against redefining __id__
, but I think we should keep warning against redefining object_id
as well.
The reason is that it is relatively well known that "we should use __send__
instead of send
for unknown objects", but I think it is less well known that "we should use __id__
instead of object_id
". In fact, object_id
is called far more often than __id__
.
$ gem-codesearch \\.object_id | wc -l
24048
$ gem-codesearch \\.__id__ | wc -l
3763
I don't know how many of these call object_id for instances of user-defined classes, but such gems may not work properly if object_id
is redefined.
If we really want to allow the redefinition of object_id
, we will need to create a consensus that a call to object_id
for unknown objects is dangerous, and get people to fix gems so that __id__
is used instead of object_id
for unknown objects.
However, if you are currently not in that much trouble, I guess it would be better to maintain the current status.
Incidentally, the names __id__
and object_id
have an interesting history.
- There used to be only
Object#id
. -
Object#__id__
was introduced to avoid the redefinition of the method nameid
. -
Object#object_id
was also introduced. -
Object#id
was completely removed to allow application authors to use tje nameid
freely. - And
__id__
andobject_id
were left.
I asked matz why the new name object_id
was introduced when __id__
was already there.
He answered, "I didn't want to have to always use __id__
because it would be ugly".
https://twitter.com/yukihiro_matz/status/1861726864332742995
Indeed, it's not very cool to call __id__
on an object that you know you don't have to worry about redefining.
Updated by byroot (Jean Boussier) 22 days ago
Is object_id
really called that much? I can't really think of something that really depend on it from the top of my head.
Updated by Eregon (Benoit Daloze) 21 days ago · Edited
mame (Yusuke Endoh) wrote in #note-5:
I think it's a good idea to warn against redefining
__id__
, but I think we should keep warning against redefiningobject_id
as well.The reason is that it is relatively well known that "we should use
__send__
instead ofsend
for unknown objects", but I think it is less well known that "we should use__id__
instead ofobject_id
". In fact,object_id
is called far more often than__id__
.
I agree and I think this a well thought out argument.
In fact I used object_id plenty of times but almost never __id__
.
He answered, "I didn't want to have to always use
__id__
because it would be ugly".
Same feeling here, I always prefer to use send/object_id when it's safe, because I think it looks much better/is more readable.
Maybe it would even make sense to warn for send
to discourage overriding it, but out of scope and probably not worth it (considering e.g. Socket#send in stdlib).
Is object_id really called that much?
It seems used a lot, yes: https://github.com/search?q=%2F%5C.object_id%5Cb%2F+language%3ARuby+&type=code&p=1
One example use is when overriding inspect
.
Updated by byroot (Jean Boussier) 21 days ago
It seems used a lot, yes:
I meant in context where it is called on an unknown object where object_id
may have been redefined and cause the "serious problem" the warning hints at. I've dealt with tons of meta-programing messes over the last decade, I don't remember a case where object_id
was involved.
Skimming over these code sample I mostly see code that is just meant to use equal?
instead, and some small snipets to showcase whether the object is similar etc.
Updated by matz (Yukihiro Matsumoto) 20 days ago
I am strongly discourage redefining object_id
, so we should keep the warning. I am not against warning __id__
redefinition.
Matz.
Updated by jhawthorn (John Hawthorn) 19 days ago
- Subject changed from Move warning when redefining object_id to __id__ to Add warning when redefining __id__ as well as object_id
Okay, I will add the warning to __id__
as well as object_id
Updated by jhawthorn (John Hawthorn) 19 days ago
- Status changed from Open to Closed
Applied in changeset git|f1dda5ed011b79d0d7bd31b09b55b5e19d8abd0c.
Warn when redefining id as well as object_id
[Feature #20912]