...then the rest of the code *does* delete the class!
Well, you are just seeing that the GC is conservative.
Imagine that something write
class A
end
a = A.new
Object.module_eval { remove_const 'A' }
at this step, ruby can't remove completely the class because this class is
referenced by the object `a'
pigeon% cat b.rb
#!/usr/bin/ruby
class A
def a
puts "a"
end
end
a = A.new
Object.module_eval { remove_const 'A' }
class A
def b
puts "b"
end
end
b = A.new
a.a
b.b
b.a
pigeon%
pigeon% b.rb
a
b
./b.rb:20: undefined method `a' for #<A:0x401ad338> (NameError)
pigeon%
This is something similar in your case, because it exist a *temporary*
variable which still make reference to the class
I just went through all of that in my mail "all the pretty evals..."; I was
asking if these are the same. Obviously they aren't the same.
Well apparently there is another problem 
Just try this
pigeon% ruby -e 'class A; end; A.module_eval "12"'
pigeon%
pigeon% ruby -e '.module_eval "12"'
-e:1: undefined method `module_eval' for :Array (NameError)
pigeon%
#module_eval is a method defined in Module, and only object which inherit
from Module can access this method.
Now
pigeon% ruby -e 'class A; end; A.instance_eval "12"'
pigeon%
pigeon% ruby -e '.instance_eval "12"'
pigeon%
#instance_eval is defined in Kernel and *all* objects can use this method.
You have 2 methods with differents names and defined in 2 differents
classes.
Now
pigeon% ruby -e 'class A; end; A.eval "12"'
-e:1: private method `eval' called for A:Class (NameError)
pigeon%
pigeon% ruby -e '.eval "12"'
-e:1: private method `eval' called for :Array (NameError)
pigeon%
#eval is a module function of Kernel
Now to see the difference
pigeon% cat b.rb
#!/usr/bin/ruby
class A
def A.a
puts "A::a"
end
def a
puts "A#a"
end
end
def a
puts "Object#a"
end
x = A.new
eval 'p self; a'
x.instance_eval 'p self; a'
class A
eval 'p self; a'
end
A.instance_eval 'p self; a'
pigeon%
pigeon% b.rb
main
Object#a
#<A:0x401ad1e4>
A#a
A
A
pigeon%
Guy Decoux
···
A::a
A::a