Feature #10463
closed:~@ and :!@ are not parsed correctly
Added by sawa (Tsuyoshi Sawada) almost 11 years ago. Updated almost 6 years ago.
Description
The at mark in literal symbols :~@ and :!@ are ignored.
:~@ # => :~
:!@ # => :!
Files
| tilde-bang-at-symbols.patch (2.22 KB) tilde-bang-at-symbols.patch | jeremyevans0 (Jeremy Evans), 07/18/2019 07:19 PM |
Updated by silverhammermba (Max Anselm) almost 11 years ago
Actions
#1
[ruby-core:66041]
That's because bash is trying to interpolate the string.
$ ruby -e 'p :!@'
:!
Updated by jeremyevans0 (Jeremy Evans) over 6 years ago
Actions
#2
[ruby-core:93625]
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 6 years ago
Actions
#3
[ruby-core:93640]
If :!@ and :! are different things, also !foo and foo.! are different things.
This means a backward incompatibility.
Updated by jeremyevans0 (Jeremy Evans) over 6 years ago
Actions
#4
[ruby-core:93642]
nobu (Nobuyoshi Nakada) wrote:
If
:!@and:!are different things, also!fooandfoo.!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 6 years ago
Actions
#5
[ruby-core:93643]
jeremyevans0 (Jeremy Evans) wrote:
nobu (Nobuyoshi Nakada) wrote:
If
:!@and:!are different things, also!fooandfoo.!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 6 years ago
Actions
#6
[ruby-core:93644]
nobu (Nobuyoshi Nakada) wrote:
jeremyevans0 (Jeremy Evans) wrote:
nobu (Nobuyoshi Nakada) wrote:
If
:!@and:!are different things, also!fooandfoo.!are different things.I don't believe that is true. With the above patch:
Sorry, forgot
@, I wanted to mean!fooandfoo.!@.
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 6 years ago
Actions
#7
[ruby-core:93653]
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 6 years ago
Actions
#8
[ruby-core:93834]
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) about 6 years ago
Actions
#9
[ruby-core:94031]
- Assignee set to nobu (Nobuyoshi Nakada)
Updated by ko1 (Koichi Sasada) about 6 years ago
Actions
#10
[ruby-core:94731]
- 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) almost 6 years ago
Actions
#11
[ruby-core:96372]
- 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 4 years ago
Actions
#12
- Has duplicate Bug #18246: send does not work for unary ! operator when operator isn't a literal symbol added