Bug #21026
closed`def __FILE__.a; end` should be a syntax error
Description
Constants like __FILE__, __LINE__ and __ENCODING__ are literals and as such you shouldn't be able to defined singleton methods on them.
It already doesn't seem to actually do anything:
Wrapping it in brackets correctly reports a syntax error:
code.rb:1: syntax error found (SyntaxError)
> 1 | def (__FILE__).a
| ^~~~~~~~ cannot define singleton method for literals
2 | end
The behavior is consistent between prism and parse.y
__ENCODING__ is frozen and so will result in a runtime error. Same for __LINE__, and also __FILE__ with frozen string literals.
Updated by zverok (Victor Shepelev) over 1 year ago
It already doesn't seem to actually do anything
This is a bunch of technicalities... But I don’t think it doesn’t do anyting :)
As far as I understand, every __FILE__ invocation in the source code produces a new instance of a string with the contents of the current file name:
So, this code:
can be treated as this:
(The subsequent calls of __FILE__ doesn’t have a method because they all return different objects.)
So, the code “works” (even if it is not of much utility). But the example with parentheses is interesting: it is not about FILE, any attempt to define a method on literal works this way:
results in...
test.rb:1: syntax error found (SyntaxError)
> 1 | def ("file").a
| ^~~~~~ cannot define singleton method for literals
2 | puts "works!"
3 | end
...so I guess __FILE__ is mostly treated as literal... Except when it does not :)
Updated by Earlopain (Earlopain _) over 1 year ago
Interesting! I didn't realize that __FILE__ will always (without frozen string literals) return a new instance. Of course __LINE__ will always have a different values but the seemingly const-ness of __FILE__ had me a bit tricked.
Updated by zverok (Victor Shepelev) over 1 year ago
As far as I understand (though it is an intuitive understanding, not backed by looking into particular implementation), __FILE__ and __LINE__ are handled at the parsing stage, behaving in (almost) all situations like there was just a corresponding literal in the code.
Say, with -W:deprecated, this code:
will dutifully emit (as if it would be just a literal)
...and with # frozen_string_literal: true pragma, it will fail with
So, as I said, it is almost like it would be a literal string... Except that with a literal string this code would be yelled at by the parser as an impossible (which doesn’t happen with __FILE__ because, I think, of the order of substitution for it to the “real” literal):
Updated by nobu (Nobuyoshi Nakada) over 1 year ago
A patch to make it syntax error: https://github.com/ruby/ruby/pull/12925
Updated by matz (Yukihiro Matsumoto) over 1 year ago
It should raise error with or without parentheses.
Matz.
Updated by nobu (Nobuyoshi Nakada) over 1 year ago
- Status changed from Open to Closed
Applied in changeset git|820c541671d9485144d81138bb029f2da8379edd.
[Bug #21026] no singleton method on pseudo variable literal