Bug #2788
closednil.instance_eval pushes nil onto cref
Description
=begin
A singleton class definition of nil pushes NilClass onto cref.
It is reasonable because NilClass has nil as the only instance.
However, nil.instance_eval pushes nil onto cref, which means that method definitions are not permitted in that context.
defiant:ruby$ ruby-trunk -ve 'class <<nil; def foo; puts "foo" end; end; nil.foo'
ruby 1.9.2dev (2010-02-18 trunk 26704) [i686-linux]
foo
defiant:ruby$ ruby-trunk -ve 'nil.instance_eval {|i| def foo; puts "foo" end }; nil.foo'
ruby 1.9.2dev (2010-02-18 trunk 26704) [i686-linux]
-e:1:in block in <main>': no class/module to add method (TypeError) from -e:1:in instance_eval'
from -e:1:in `'
The behavior is the same in Ruby 1.8.7.
Is it intended or a bug?
=end
        
           Updated by akr (Akira Tanaka) over 14 years ago
          Updated by akr (Akira Tanaka) over 14 years ago
          
          
        
        
      
      - Project changed from 8 to Ruby
- Category changed from core to core
        
           Updated by marcandre (Marc-Andre Lafortune) over 13 years ago
          Updated by marcandre (Marc-Andre Lafortune) over 13 years ago
          
          
        
        
      
      - Assignee changed from matz (Yukihiro Matsumoto) to ko1 (Koichi Sasada)
- Target version set to 2.0.0
Behavior is intended, as per tests in bootstraptest/test_eval.rb and [ruby-core:16808], but I'm don't think it's the right way to go, since nil, true and false do have singleton classes.
Koichi, do you agree the following patch would be good?
diff --git a/vm_eval.c b/vm_eval.c
index aa32621..dfd4588 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -1346,7 +1346,7 @@ rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
{
VALUE klass;
- if (SPECIAL_CONST_P(self)) {
- if (FIXNUM_P(self) || SYMBOL_P(self)) {
 klass = Qnil;
 }
 else {
 @@ -1378,7 +1378,7 @@ rb_obj_instance_exec(int argc, VALUE *argv, VALUE self)
 {
 VALUE klass;
- if (SPECIAL_CONST_P(self)) {
- if (FIXNUM_P(self) || SYMBOL_P(self)) {
 klass = Qnil;
 }
 else {
 diff --git a/bootstraptest/test_eval.rb b/bootstraptest/test_eval.rb
 index c347d50..e25cc260 100644
 --- a/bootstraptest/test_eval.rb
 +++ b/bootstraptest/test_eval.rb
 @@ -264,24 +264,18 @@ assert_equal 'ok', %q{
 }, '[ruby-core:16794]'
assert_equal 'ok', %q{
- begin
- nil.instance_eval {
- 
def a() :a end
- }
- rescue TypeError
- :ok
- end
 -}, '[ruby-core:16796]'
- nil.instance_eval {
- def defd_using_instance_eval() :ok end
- }
- nil.defd_using_instance_eval
 +}, '[ruby-core:28324]'
assert_equal 'ok', %q{
- begin
- nil.instance_exec {
- 
def a() :a end
- }
- rescue TypeError
- :ok
- end
 -}, '[ruby-core:16796]'
- nil.instance_exec {
- def defd_using_instance_exec() :ok end
- }
- nil.defd_using_instance_exec
 +}, '[ruby-core:28324]'
assert_normal_exit %q{
eval("", method(:proc).call {}.binding)
        
           Updated by marcandre (Marc-Andre Lafortune) over 13 years ago
          Updated by marcandre (Marc-Andre Lafortune) over 13 years ago
          
          
        
        
      
      test-all also points out that @@class_level_variable would then refer to NilClass/FalseClass/TrueClass's class variables, contrary to other singleton classes. This would be consistent with class << nil vs class << my_string.
        
           Updated by ko1 (Koichi Sasada) over 13 years ago
          Updated by ko1 (Koichi Sasada) over 13 years ago
          
          
        
        
      
      - Assignee changed from ko1 (Koichi Sasada) to matz (Yukihiro Matsumoto)
I'm so sorry to miss your ticket for long time.
Always I get confusing about instance eval with special variables (nil, false, etc).
Matz (shugo-san is specialist?), could you determine the specification?
        
           Updated by ko1 (Koichi Sasada) over 13 years ago
          Updated by ko1 (Koichi Sasada) over 13 years ago
          
          
        
        
      
      - Assignee changed from matz (Yukihiro Matsumoto) to nobu (Nobuyoshi Nakada)
nobu has patach.
        
           Updated by shugo (Shugo Maeda) about 13 years ago
          Updated by shugo (Shugo Maeda) about 13 years ago
          
          
        
        
      
      - Priority changed from 3 to Normal
ko1 (Koichi Sasada) wrote:
nobu has patach.
Does he have a Hebrew niqqud vowel sign?
Aside from the joke, why not apply the patch, Nobu?
        
           Updated by usa (Usaku NAKAMURA) about 13 years ago
          Updated by usa (Usaku NAKAMURA) about 13 years ago
          
          
        
        
      
      Hello,
In message "[ruby-core:47015] [ruby-trunk - Bug #2788] nil.instance_eval pushes nil onto cref"
on Aug.06,2012 17:15:16, redmine@ruby-lang.org wrote:
Aside from the joke, why not apply the patch, Nobu?
Wait until he drives his time machine.
Regards,¶
U.Nakamura usa@garbagecollect.jp
        
           Updated by nobu (Nobuyoshi Nakada) about 13 years ago
          Updated by nobu (Nobuyoshi Nakada) about 13 years ago
          
          
        
        
      
      - Status changed from Assigned to Closed
- % Done changed from 0 to 100
This issue was solved with changeset r36647.
Shugo, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.
method in instance_eval
- class.c (rb_special_singleton_class_of): utility function.
- vm_eval.c (eval_under): special deal for class variable scope with
 instance_eval.
- vm_eval.c (rb_obj_instance_eval, rb_obj_instance_exec): allow method
 definition in instance_eval of special constants. [ruby-core:28324]
 [Bug #2788]