Project

General

Profile

Bug #8982

Updated by nobu (Nobuyoshi Nakada) over 10 years ago

=begin 
 Given the following script: 

  

 ``` 
 def raise_no_method_error_for_anonymous_class_with_inspect(&block) 
    
   klass = Class.new do 
      
     define_method(:inspect, &block) 
    
   end 

    

   begin 
      
     instance = klass.new 
      
     puts "#inspect output: #{instance.inspect} (#{instance.inspect.length} chars)" 
      
     instance.undefined_method 
    
   rescue NoMethodError => e 
      
     puts e.message 
    
   end 

    

   puts 
  
 end 

  

 raise_no_method_error_for_anonymous_class_with_inspect do 
    
   "#<MyAnonymousClass>" 
  
 end 

  

 raise_no_method_error_for_anonymous_class_with_inspect do 
    
   "<MyAnonymousClass>" 
  
 end 

  

 raise_no_method_error_for_anonymous_class_with_inspect do 
    
   "#<MyAnonymousClass #{'a' * 45}>" 
  
 end 

  

 raise_no_method_error_for_anonymous_class_with_inspect do 
    
   "#<MyAnonymousClass #{'a' * 46}>" 
  
 end 
 ``` 

 It produces the following output: 

  

 ``` 
 #inspect output: #<MyAnonymousClass> (19 chars) 
  
 undefined method `undefined_method' for #<MyAnonymousClass> 

  

 #inspect output: <MyAnonymousClass> (18 chars) 
  
 undefined method `undefined_method' for <MyAnonymousClass>:#<Class:0x1017270e8> 

  

 #inspect output: #<MyAnonymousClass aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa> (65 chars) 
  
 undefined method `undefined_method' for #<MyAnonymousClass aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa> 

  

 #inspect output: #<MyAnonymousClass aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa> (66 chars) 
  
 undefined method `undefined_method' for #<#<Class:0x1017266e8>:0x101726698> 
 ``` 

 There are two surprising things here: 

 * It matters whether or not the first character in my `inspect` is a `#`.    If it's not, ruby appends the class's `#inspect` output to it. 
 * It matters how long my `inspect` string is.    If it's less than 66 characters, it's used; if it's more than 65, it's discarded, and the default anonymous `#inspect` is used instead. 

 Both of these things are extremely surprising and seem very arbitrary and inconsistent. 

 I brought this up on ruby parley and @charliesome was kind enough to point me to the code that's the source of this issue: 

 ((<error.c#L1091-1104|URL:https://github.com/ruby/ruby/blob/870dc20922d1ab0b628d24e64e971e8eb77ecd61/error.c#L1091-1104>)) https://github.com/ruby/ruby/blob/870dc20922d1ab0b628d24e64e971e8eb77ecd61/error.c#L1091-1104 

 So it looks intentional, but I think this is a bug. 
 =end 

Back