Issue #2788 has been updated by Marc-Andre Lafortune.

Assignee changed from Yukihiro Matsumoto to 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)

----------------------------------------
Bug #2788: nil.instance_eval pushes nil onto cref
https://bugs.ruby-lang.org/issues/2788

Author: Shugo Maeda
Status: Assigned
Priority: Low
Assignee: Koichi Sasada
Category: core
Target version: 2.0.0
ruby -v: ruby 1.9.2dev (2010-02-18 trunk 26704) [i686-linux]


=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 `<main>'
 
 The behavior is the same in Ruby 1.8.7.
 Is it intended or a bug?
=end



-- 
http://bugs.ruby-lang.org/