Bug #18905
closed:"@=".inspect is non-evaluatable
Description
There is an edge case where Symbol#inspect
returns a non-evaluatable expression:
:"@=".inspect # => :@=
:"[][]=".inspect # => :[][]=
:"$$$$=" # => :$$$$=
More specifically, the quotations are stripped if the following conditions are met (but the converse does not hold):
- It starts with
@
,@@
,$
or[
, - the prefix is not followed by an identifier, and
- it ends with
=
.
But the rule should only apply to :$=
and :[]=
, because (in my understanding) we should generally have eval(sym.inspect) == sym
for the programmers' convenience.
Updated by sawa (Tsuyoshi Sawada) over 2 years ago
Not sure what you mean. inspect
is expected to return a string, and the cases you mention indeed return a string respectively.
:"@=".inspect #=> ":@="
:"[][]=".inspect #=> ":\"[][]=\""
:"$$$$=".inspect #=> ":$$$$="
However, among them, :"@=".inspect
and :"$$$$=".inspect
do not include quotations. Is that what you are at?
Updated by nobu (Nobuyoshi Nakada) over 2 years ago
First, inspect
methods are not for eval
.
We only guarantee that sym.name.to_sym == sym
.
Updated by qnighy (Masaki Hara) over 2 years ago
sawa (Tsuyoshi Sawada) wrote in #note-1:
However, among them,
:"@=".inspect
and:"$$$$=".inspect
do not include quotations. Is that what you are at?
Ah yes, the second example is my mistake. It should have been :"[=]="
or such. I think these symbols are better quoted than not.
nobu (Nobuyoshi Nakada) wrote in #note-2:
First,
inspect
methods are not foreval
.
We only guarantee thatsym.name.to_sym == sym
.
I understand it is not a guarantee and thus this is a relatively subtle issue. Nonetheless I think the behavior is not an intended one because Ruby values (including symbols) often implement #inspect
in a way it is evaluatable.
Let me give more context on it: I was implementing the parser
gem's AST serialization in another language to use the gem as a reference implementation. Under the hood it uses Symbol#inspect
to stringify symbols and thus I was interested in the Symbol#inspect
algorithm.
Updated by ufuk (Ufuk Kayserilioglu) over 2 years ago
I was bitten by the same thing last week and was actually going to open an issue myself. Thanks for raising this @qnighy (Masaki Hara).
The thing that caught me out was that the following discrepancy:
"4_to_5".to_sym.inspect
#=> :"4_to_5"
"4_to_5=".to_sym.inspect
#=> :4_to_5=
I realize that Ruby spends a considerable amount of effort to not print symbols in a format where they could not be roundtripped, and the discprancy between :"4_to_5"
and :"4_to_5="
was surprising.
I bisected the change to the released versions of Ruby and found that the behaviour changed somewhere between ruby-2.2.0-preview1
and ruby-2.2.0-preview2
:
$ docker run --rm -e "ALL_RUBY_SINCE=ruby-2.0" rubylang/all-ruby ./all-ruby -e "puts '4_to_5='.to_sym.inspect"
ruby-2.0.0-p0 :"4_to_5="
...
ruby-2.2.0-preview1 :"4_to_5="
ruby-2.2.0-preview2 :4_to_5=
...
ruby-3.2.0-preview1 :4_to_5=
Looking at the commit log, I can see that there is a commit that adds special casing for a trailing =
but I don't understand the reason behind why the change was made: https://github.com/ruby/ruby/commit/986a893d7a420b8472c06b2e36b71b8bf00e9e21
@nobu (Nobuyoshi Nakada) I understand that Ruby does not guarantee that inspect
methods are for eval
but Ruby seems to consistently quote invalid Symbol
s in inspect
, except for when they end with =
. I think this is not consistent and Ruby might as well not quote Symbol
s in inspect
at all, in this case. I think something has to change to keep consistency.
Updated by nobu (Nobuyoshi Nakada) over 2 years ago
- Status changed from Open to Closed
Applied in changeset git|8f1759143533d2b772efd5184ba02738f66fe1fc.
[Bug #18905] Check symbol name types more strictly