Reading the Ruby source code, I can interpret:
instance_eval does the following:
return specific_eval(argc, argv, klass, self)
which in turn starts:
if (rb_block_given_p()) { if (argc > 0) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc); } return yield_under(klass, self, Qundef); }
You can see that they pass Qundef for the VALUES argument.
if (values == Qundef) { return vm_yield_with_cref(th, 1, &self, cref); }
In this particular line of code, they manually set argc (argument count) to 1, and the argument to self. Later, the code that prepares the block sets the arguments to the block for these arguments, so the first argument is "self", and the rest is nil.
The code that sets the block arguments executes:
arg0 = argv[0]; ... bunch of code ... else { argv[0] = arg0; } for (i=argc; i<m; i++) { argv[i] = Qnil; }
Result:
1.9.3p194 :006 > instance_eval do |x, y, z, a, b, c, d| x.class end => Object 1.9.3p194 :008 > instance_eval do |x, y, z, a, b, c, d| y.class end => NilClass
Why? I have no idea, but the code seems intentional. It would be nice to ask the performers a question and see what they can say about it.
[change]
This is probably the case because the blocks you pass to instance_eval may or may not be created for it (code that depends on whether it is set up for the class that the block needs to be changed), instead they can assume that you are going to pass them the instance that you want to change as an argument, and that way they will work with instance_eval.
irb(main):001:0> blk = Proc.new do |x| x.class end #<Proc: 0x007fd2018447b8@ (irb):1> irb(main):002:0> blk.call NilClass irb(main):003:0> instance_eval &blk Object
Of course, this is only a theory and without official documentation, which I can only guess about.