[Bug:trunk] NoMethodError message "no superclass method"

e$B$J$+$@$G$9!#e(B

trunke$B$GAH$9~$$N%a%=%C%I$+$i$Ne(BNoMethodErrore$B$N%a%C%;!<%8$,e(B"no
superclass method"e$B$K$J$j$^$;$s!#e(B

$ ./ruby -v -e ‘module Enumerable;undef min;end; (1…2).min{}’
ruby 1.9.2dev (2009-10-30 trunk 25565) [universal.x86_64-darwin9.0]
-e:1:in min': undefined methodmin’ for 1…2:Range (NoMethodError)
from -e:1:in `’

e$B0lJ}!"e(B__send__e$B$r;H$&$He(Bsupere$B$H$OL54X78$J$N$K=P$F$7$^$$$^$9!#e(B

$ ./ruby -e ‘Object.new.method(:send).call(:foo)’
-e:1:in call': super: no superclass methodfoo’ for
#Object:0x000001002f93f0 (NoMethodError)
from -e:1:in `’

e$B$7$+$b!"$b$&0lEYF1$8%a%=%C%I$r8F$V$HFs2sL$K$O=P$^$;$s!#e(B

$ ./ruby -e ‘2.times{begin Object.new.method(:send).call(:foo);
rescue NoMethodError => e; puts e.message; end}’
super: no superclass method foo' for #<Object:0x000001002e2f10> undefined methodfoo’ for #Object:0x000001002e2c68

Index: vm_eval.c

— vm_eval.c (revision 25565)
+++ vm_eval.c (working copy)
@@ -22,5 +22,4 @@ static VALUE vm_exec(rb_thread_t *th);
static void vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const
NODE *cref);
static int vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE
*dfp, VALUE ary);
-static VALUE send_internal(int argc, const VALUE *argv, VALUE recv, int
scope);

typedef enum call_type {
@@ -30,4 +29,6 @@ typedef enum call_type {
} call_type;

+static VALUE send_internal(int argc, const VALUE argv, VALUE recv,
call_type scope);
+
static inline VALUE
vm_call0(rb_thread_t
th, VALUE recv, VALUE id, int argc, const VALUE
argv,
@@ -105,5 +106,5 @@ vm_call0(rb_thread_t
th, VALUE recv, VA
klass = RCLASS_SUPER(klass);
if (!klass || !(me = rb_method_entry(klass, id))) {

  •  return method_missing(recv, id, argc, argv, 0);
    
  •  return method_missing(recv, id, argc, argv, NOEX_SUPER);
    
    }
    RUBY_VM_CHECK_INTS();
    @@ -122,5 +123,5 @@ vm_call0(rb_thread_t* th, VALUE recv, VA
    switch (def->body.optimize_type) {
    case OPTIMIZED_METHOD_TYPE_SEND:
  •  val = send_internal(argc, argv, recv, NOEX_NOSUPER | 
    

NOEX_PRIVATE);

  •  val = send_internal(argc, argv, recv, CALL_FCALL);
     break;
    
    case OPTIMIZED_METHOD_TYPE_CALL: {
    @@ -176,5 +177,5 @@ vm_call_super(rb_thread_t *th, int argc,
    me = rb_method_entry(klass, id);
    if (!me) {
  • return method_missing(recv, id, argc, argv, 0);
  • return method_missing(recv, id, argc, argv, NOEX_SUPER);
    }

@@ -220,5 +221,4 @@ rb_call0(VALUE recv, ID mid, int argc, c
VALUE klass = CLASS_OF(recv);
rb_method_entry_t *me;

  • struct cache_entry *ent;
    rb_thread_t *th = GET_THREAD();
    ID oid;
    @@ -234,26 +234,10 @@ rb_call0(VALUE recv, ID mid, int argc, c
    }

  • /* is it in the method cache? */

  • ent = cache + EXPR1(klass, mid);

  • if (ent->mid == mid && ent->klass == klass) {

  • me = ent->me;

  • if (UNDEFINED_METHOD_ENTRY_P(me)) {

  •  return method_missing(recv, mid, argc, argv,
    
  •      scope == CALL_VCALL ? NOEX_VCALL : 0);
    
  • }

  • klass = me->klass;

  • }

  • else if ((me = rb_method_entry_without_cache(klass, mid)) != 0 &&
    me->def) {

  • klass = me->klass;

  • }

  • else {

  • if (scope == 3) {

  •  return method_missing(recv, mid, argc, argv, NOEX_SUPER);
    
  • }

  • me = rb_method_entry(klass, mid);
  • if (UNDEFINED_METHOD_ENTRY_P(me)) {
    return method_missing(recv, mid, argc, argv,
    scope == CALL_VCALL ? NOEX_VCALL : 0);
    }
  • klass = me->klass;
    oid = me->def->original_id;
    noex = me->flag;
    @@ -580,5 +564,5 @@ rb_funcall_no_recursive(VALUE obj, ID id

static VALUE
-send_internal(int argc, const VALUE *argv, VALUE recv, int scope)
+send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope)
{
VALUE vid;
@@ -617,5 +601,5 @@ VALUE
rb_f_send(int argc, VALUE *argv, VALUE recv)
{

  • return send_internal(argc, argv, recv, NOEX_NOSUPER |
    NOEX_PRIVATE);
  • return send_internal(argc, argv, recv, CALL_FCALL);
    }

@@ -634,5 +618,5 @@ VALUE
rb_f_public_send(int argc, VALUE *argv, VALUE recv)
{

  • return send_internal(argc, argv, recv, NOEX_PUBLIC);
  • return send_internal(argc, argv, recv, CALL_PUBLIC);
    }

Index: test/ruby/test_object.rb

— test/ruby/test_object.rb (revision 25565)
+++ test/ruby/test_object.rb (working copy)
@@ -378,4 +378,25 @@ class TestObject < Test::Unit::TestCase
end

  • def test_no_superclass_method
  • o = Object.new
  • e = assert_raise(NoMethodError) {

o.method(:send).call(:never_defined_test_no_superclass_method)

  • }
  • m1 = e.message
  • assert_no_match(/no superclass method/, m1)
  • e = assert_raise(NoMethodError) {

o.method(:send).call(:never_defined_test_no_superclass_method)

  • }
  • assert_equal(m1, e.message)
  • e = assert_raise(NoMethodError) {
  •  o.never_defined_test_no_superclass_method
    
  • }
  • assert_equal(m1, e.message)
  • end
  • def test_superclass_method
  • assert_in_out_err(["-e", “module Enumerable;undef min;end;
    (1…2).min{}”], [], [], /no superclass method/)
  • end
  • def test_specific_eval_with_wrong_arguments
    assert_raise(ArgumentError) do

e$B%A%1%C%He(B #2312 e$B$,99?7$5$l$^$7$?!#e(B (by Nobuyoshi N.)

e$B%9%F!<%?%9e(B Opene$B$+$ie(BClosede$B$KJQ99e(B
e$B?JD=e(B % 0e$B$+$ie(B100e$B$KJQ99e(B

This issue was solved with changeset r25573.
Nobuyoshi, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


http://redmine.ruby-lang.org/issues/show/2312