From 0954607864bcdd81ea5f3dd2ea52f638f2f32e47 Mon Sep 17 00:00:00 2001 From: shugo Date: Sat, 29 Sep 2012 02:21:27 +0000 Subject: [PATCH] * vm_insnhelper.c (rb_vm_using_modules): use using_modules before klass to fix method lookup order, and use klass even if klass is not a module to make refinements in class_eval invoked on classes work. * eval.c (rb_using_module): accept a class as the second argument. * eval.c (rb_mod_using, f_using): raise a TypeError if the argument is not a module. * test/ruby/test_refinement.rb: add new tests for the above changes. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37053 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 14 +++++++++ eval.c | 4 ++- test/ruby/test_refinement.rb | 56 ++++++++++++++++++++++++++++++++++++ vm_insnhelper.c | 21 ++++++-------- 4 files changed, 81 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index b3de5b1eea..deb65d7262 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +Sat Sep 29 11:21:06 2012 Shugo Maeda + + * vm_insnhelper.c (rb_vm_using_modules): use using_modules before + klass to fix method lookup order, and use klass even if klass is + not a module to make refinements in class_eval invoked on classes + work. + + * eval.c (rb_using_module): accept a class as the second argument. + + * eval.c (rb_mod_using, f_using): raise a TypeError if the argument + is not a module. + + * test/ruby/test_refinement.rb: add new tests for the above changes. + Sat Sep 29 02:18:57 2012 Hiroshi Shirosaki * test/ruby/test_unicode_escape.rb (TestUnicodeEscape#test_basic): diff --git a/eval.c b/eval.c index 4d27a8ec6b..345dd83079 100644 --- a/eval.c +++ b/eval.c @@ -1096,7 +1096,7 @@ rb_using_module(NODE *cref, VALUE module) ID id_overlaid_modules; VALUE overlaid_modules; - Check_Type(module, T_MODULE); + check_class_or_module(module); CONST_ID(id_overlaid_modules, "__overlaid_modules__"); overlaid_modules = rb_attr_get(module, id_overlaid_modules); if (NIL_P(overlaid_modules)) return; @@ -1117,6 +1117,7 @@ rb_mod_using(VALUE self, VALUE module) ID id_using_modules; VALUE using_modules; + Check_Type(module, T_MODULE); CONST_ID(id_using_modules, "__using_modules__"); using_modules = rb_attr_get(self, id_using_modules); if (NIL_P(using_modules)) { @@ -1345,6 +1346,7 @@ f_using(VALUE self, VALUE module) { NODE *cref = rb_vm_cref(); + Check_Type(module, T_MODULE); rb_using_module(cref, module); return self; } diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index 98645745e9..476c6442c7 100644 --- a/test/ruby/test_refinement.rb +++ b/test/ruby/test_refinement.rb @@ -361,6 +361,34 @@ class TestRefinement < Test::Unit::TestCase assert_equal([:m1, :m2], m2.module_eval { obj.foo }) end + def test_refine_module_with_double_overriding + m1 = Module.new { + def foo + [:m1] + end + } + c = Class.new { + include m1 + } + m2 = Module.new { + refine m1 do + def foo + super << :m2 + end + end + } + m3 = Module.new { + using m2 + refine m1 do + def foo + super << :m3 + end + end + } + obj = c.new + assert_equal([:m1, :m2, :m3], m3.module_eval { obj.foo }) + end + def test_refine_module_and_call_superclass_method m1 = Module.new c1 = Class.new { @@ -399,4 +427,32 @@ class TestRefinement < Test::Unit::TestCase } end end + + def test_refine_in_class_and_class_eval + c = Class.new { + refine Fixnum do + def foo + "c" + end + end + } + assert_equal("c", c.class_eval { 123.foo }) + end + + def test_kernel_using_class + c = Class.new + assert_raise(TypeError) do + using c + end + end + + def test_module_using_class + c = Class.new + m = Module.new + assert_raise(TypeError) do + m.module_eval do + using c + end + end + end end diff --git a/vm_insnhelper.c b/vm_insnhelper.c index f134487107..60547d049a 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1830,27 +1830,22 @@ rb_vm_using_modules(NODE *cref, VALUE klass) ID id_using_modules; VALUE using_modules; + if (NIL_P(klass)) return; CONST_ID(id_using_modules, "__using_modules__"); using_modules = rb_attr_get(klass, id_using_modules); - switch (TYPE(klass)) { - case T_CLASS: - if (NIL_P(using_modules)) { - VALUE super = rb_class_real(RCLASS_SUPER(klass)); - using_modules = rb_attr_get(super, id_using_modules); - if (!NIL_P(using_modules)) { - using_modules = rb_hash_dup(using_modules); - rb_ivar_set(klass, id_using_modules, using_modules); - } + if (NIL_P(using_modules) && BUILTIN_TYPE(klass) == T_CLASS) { + VALUE super = rb_class_real(RCLASS_SUPER(klass)); + using_modules = rb_attr_get(super, id_using_modules); + if (!NIL_P(using_modules)) { + using_modules = rb_hash_dup(using_modules); + rb_ivar_set(klass, id_using_modules, using_modules); } - break; - case T_MODULE: - rb_using_module(cref, klass); - break; } if (!NIL_P(using_modules)) { rb_hash_foreach(using_modules, vm_using_module_i, (VALUE) cref); } + rb_using_module(cref, klass); } static VALUE