Feature #10463
closed:~@ and :!@ are not parsed correctly
Description
The at mark in literal symbols :~@
and :!@
are ignored.
:~@ # => :~
:!@ # => :!
Files
Updated by silverhammermba (Max Anselm) about 10 years ago
That's because bash is trying to interpolate the string.
$ ruby -e 'p :!@'
:!
Updated by jeremyevans0 (Jeremy Evans) over 5 years ago
I did some research, and this is related to the fact that Ruby allows !@
and ~@
as method names (back to the initial SVN revision for ~@
), silently dropping the @
from the method name:
class A
def !@; :!@ end
def ~@; :~@ end
end
!A.new
# :!
~A.new
# :~
A.instance_methods(false)
# => [:!, :~]
This diff would remove this behavior:
diff --git a/parse.y b/parse.y
index 33f1ef072e..ed7dae8955 100644
--- a/parse.y
+++ b/parse.y
@@ -8772,6 +8772,7 @@ parser_yylex(struct parser_params *p)
if (IS_AFTER_OPERATOR()) {
SET_LEX_STATE(EXPR_ARG);
if (c == '@') {
+ pushback(p, c);
return '!';
}
}
@@ -9184,9 +9185,6 @@ parser_yylex(struct parser_params *p)
case '~':
if (IS_AFTER_OPERATOR()) {
- if ((c = nextc(p)) != '@') {
- pushback(p, c);
- }
SET_LEX_STATE(EXPR_ARG);
}
else {
However, it breaks using ~@
and !@
as method names, which is breaks one test in bootstraptest. This is because both the symbol and the method name use fname
in the parser. There is probably a way to remove support for using these in symbols but keeping the support in method names that I am not currently aware of. However, I'm sure if we want to keep supporting ~@
and !@
in method names.
FWIW, JRuby handles :~@
and :!@
the same way as CRuby.
Updated by nobu (Nobuyoshi Nakada) over 5 years ago
If :!@
and :!
are different things, also !foo
and foo.!
are different things.
This means a backward incompatibility.
Updated by jeremyevans0 (Jeremy Evans) over 5 years ago
nobu (Nobuyoshi Nakada) wrote:
If
:!@
and:!
are different things, also!foo
andfoo.!
are different things.
I don't believe that is true. With the above patch:
class A
def !; :! end
def ~; :~ end
end
!A.new
# :!
A.new.!
# :!
~A.new
# :~
A.new.~
# :~
The @
in :!@
and def !@; end
was ignored during lexing before, it doesn't affect the semantics. This is different than +@
and +
:
class A
def +; :+ end
def +@; :+@ end
end
+A.new
# :+@
A.new.+
# :+
This means a backward incompatibility.
The backward incompatibility should be limited to making the following invalid syntax:
def !@; end
def ~@; end
alias foo !@
alias bar ~@
:!@
:~@
Currently, :!@
is different than :"!@"
, which very much appears to be a bug. With the above patch :!@
is a syntax error (:"!@"
is still valid).
Updated by nobu (Nobuyoshi Nakada) over 5 years ago
jeremyevans0 (Jeremy Evans) wrote:
nobu (Nobuyoshi Nakada) wrote:
If
:!@
and:!
are different things, also!foo
andfoo.!
are different things.I don't believe that is true. With the above patch:
Sorry, forgot @
, I wanted to mean !foo
and foo.!@
.
Updated by jeremyevans0 (Jeremy Evans) over 5 years ago
nobu (Nobuyoshi Nakada) wrote:
jeremyevans0 (Jeremy Evans) wrote:
nobu (Nobuyoshi Nakada) wrote:
If
:!@
and:!
are different things, also!foo
andfoo.!
are different things.I don't believe that is true. With the above patch:
Sorry, forgot
@
, I wanted to mean!foo
andfoo.!@
.
Well, foo.!@
would be a syntax error with the patch. Is there a reason other than backwards compatibility to keep this automatic aliasing of !@
to !
and ~@
to ~
? If not, maybe we could deprecate this in 2.7 and remove it in Ruby 3 (if matz approves).
Updated by shevegen (Robert A. Heiler) over 5 years ago
Interesting - I did not know this. sawa finds stuff. :)
Personally I would be in favour of changing the behaviour as Jeremy described (I also think this
may be a bug or perhaps an oddity), but I guess it depends on a) whether matz wants to change it
in the first place and b) then when to change it, if a) evaluates to a change.
A secondary consideration may be to query how many ruby users depend on this backwards behaviour.
I have no statistical dataset to make a statement either way, but from intuition, I would venture
that this change would not affect a lot of ruby code out there; I could be wrong though.
Updated by jeremyevans0 (Jeremy Evans) over 5 years ago
matz confirmed in the last developer meeting that he wants def !@; end
to continue to work. However, I still think we should fix it so that :!@
and :~@
are not treated as :!
and :~
. This is a bit tricky to do as the parser currently uses the same lex state for both cases (EXPR_FNAME
).
The simplest way I can think to fix this is in the attached patch. It changes the :!
and :~
cases to use lex state EXPR_FNAME|EXPR_FITEM
, and changes the code to check on whether EXPR_FITEM
is one of the lex states. If EXPR_FITEM
is one of the lex states, then it doesn't ignore the @
.
Updated by ko1 (Koichi Sasada) over 5 years ago
- Assignee set to nobu (Nobuyoshi Nakada)
Updated by ko1 (Koichi Sasada) over 5 years ago
- Tracker changed from Bug to Feature
- Assignee changed from nobu (Nobuyoshi Nakada) to matz (Yukihiro Matsumoto)
- ruby -v deleted (
2.1.4) - Backport deleted (
2.0.0: UNKNOWN, 2.1: UNKNOWN)
Updated by matz (Yukihiro Matsumoto) about 5 years ago
- Status changed from Open to Rejected
I don't see the practical benefit of this proposal. Besides that incompatibility is a clear drawback.
Matz.
Updated by jeremyevans0 (Jeremy Evans) about 3 years ago
- Has duplicate Bug #18246: send does not work for unary ! operator when operator isn't a literal symbol added