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:
def __FILE__.a
end
__FILE__.a #=>  undefined method 'a' for an instance of String (NoMethodError)
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) 10 months ago
          Updated by zverok (Victor Shepelev) 10 months 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:
p __FILE__.object_id #=> 16
p __FILE__.object_id #=> 24
p __FILE__.frozen? #=> false
So, this code:
def  __FILE__.a
  puts "works!"
end
can be treated as this:
o = __FILE__
def  o.a
  puts "works!"
end
o.a
# prints "works!"
(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:
def ("file").a
end
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 _) 10 months ago
          Updated by Earlopain (Earlopain _) 10 months 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) 10 months ago
          Updated by zverok (Victor Shepelev) 10 months 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:
def __FILE__.a
end
will dutifully emit (as if it would be just a literal)
warning: literal string will be frozen in the future
...and with # frozen_string_literal: true pragma, it will fail with
can't define singleton (TypeError)
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):
def 'test.rb'.a
end
test.rb:1: syntax errors found (SyntaxError)
> 1 | def 'test.rb'.a
    |    ^ expected a delimiter to close the parameters
    |     ^ unexpected string literal; expected a method name
        
           Updated by nobu (Nobuyoshi Nakada) 8 months ago
          Updated by nobu (Nobuyoshi Nakada) 8 months ago
          
          
        
        
      
      A patch to make it syntax error: https://github.com/ruby/ruby/pull/12925
        
           Updated by matz (Yukihiro Matsumoto) 8 months ago
          Updated by matz (Yukihiro Matsumoto) 8 months ago
          
          
        
        
      
      It should raise error with or without parentheses.
Matz.
        
           Updated by nobu (Nobuyoshi Nakada) 7 months ago
          Updated by nobu (Nobuyoshi Nakada) 7 months ago
          
          
        
        
      
      - Status changed from Open to Closed
Applied in changeset git|820c541671d9485144d81138bb029f2da8379edd.
[Bug #21026] no singleton method on pseudo variable literal