ruby-changes:26205
From: shugo <ko1@a...>
Date: Sat, 8 Dec 2012 00:49:33 +0900 (JST)
Subject: [ruby-changes:26205] shugo:r38262 (trunk): * vm_eval.c (yield_under, eval_under): do not activate refinements
shugo 2012-12-08 00:49:21 +0900 (Sat, 08 Dec 2012) New Revision: 38262 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=38262 Log: * vm_eval.c (yield_under, eval_under): do not activate refinements of the receiver in module_eval and instance_eval. * eval.c (ruby_Init_refinement): undef Class#refine. * eval.c (ruby_Init_refinement): remove Module#using. * eval.c (ruby_Init_refinement): main.using should be private. * eval.c (rb_mod_refine): the argument of Module#refine should not be a module. * insns.def (defineclass): do not activate refinements in a class or module. Modified files: trunk/ChangeLog trunk/eval.c trunk/insns.def trunk/test/ruby/test_refinement.rb trunk/vm_eval.c trunk/vm_insnhelper.c Index: ChangeLog =================================================================== --- ChangeLog (revision 38261) +++ ChangeLog (revision 38262) @@ -1,3 +1,20 @@ +Sat Dec 8 00:10:34 2012 Shugo Maeda <shugo@r...> + + * vm_eval.c (yield_under, eval_under): do not activate refinements + of the receiver in module_eval and instance_eval. + + * eval.c (ruby_Init_refinement): undef Class#refine. + + * eval.c (ruby_Init_refinement): remove Module#using. + + * eval.c (ruby_Init_refinement): main.using should be private. + + * eval.c (rb_mod_refine): the argument of Module#refine should not + be a module. + + * insns.def (defineclass): do not activate refinements in a class or + module. + Fri Dec 7 23:42:11 2012 Shugo Maeda <shugo@r...> * ext/refinement/refinement.c: include ruby/ruby.h instead of the Index: insns.def =================================================================== --- insns.def (revision 38261) +++ insns.def (revision 38262) @@ -967,7 +967,6 @@ klass, 0, VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()), class_iseq->iseq_encoded, GET_SP(), class_iseq->local_size, 0); - rb_vm_using_modules(class_iseq->cref_stack, klass); RESTORE_REGS(); INC_VM_STATE_VERSION(); Index: vm_eval.c =================================================================== --- vm_eval.c (revision 38261) +++ vm_eval.c (revision 38262) @@ -1453,7 +1453,6 @@ } cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr); cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL; - rb_vm_using_modules(cref, under); if (values == Qundef) { return vm_yield_with_cref(th, 1, &self, cref); @@ -1478,7 +1477,6 @@ else { SafeStringValue(src); } - rb_vm_using_modules(cref, under); return eval_string_with_cref(self, src, Qnil, cref, file, line); } Index: eval.c =================================================================== --- eval.c (revision 38261) +++ eval.c (revision 38262) @@ -1039,16 +1039,6 @@ return module; } -static -void check_class_or_module(VALUE obj) -{ - if (!RB_TYPE_P(obj, T_CLASS) && !RB_TYPE_P(obj, T_MODULE)) { - VALUE str = rb_inspect(obj); - rb_raise(rb_eTypeError, "%s is not a class/module", - StringValuePtr(str)); - } -} - static VALUE hidden_identity_hash_new() { @@ -1064,7 +1054,7 @@ { VALUE iclass, c, superclass = klass; - check_class_or_module(klass); + Check_Type(klass, T_CLASS); Check_Type(module, T_MODULE); if (NIL_P(cref->nd_refinements)) { cref->nd_refinements = hidden_identity_hash_new(); @@ -1098,18 +1088,7 @@ rb_hash_aset(cref->nd_refinements, klass, iclass); } -void rb_using_module(NODE *cref, VALUE module); - static int -using_module_i(VALUE module, VALUE val, VALUE arg) -{ - NODE *cref = (NODE *) arg; - - rb_using_module(cref, module); - return ST_CONTINUE; -} - -static int using_refinement(VALUE klass, VALUE module, VALUE arg) { NODE *cref = (NODE *) arg; @@ -1123,70 +1102,14 @@ { ID id_refinements; VALUE refinements; - ID id_using_modules; - VALUE using_modules; - check_class_or_module(module); - CONST_ID(id_using_modules, "__using_modules__"); - using_modules = rb_attr_get(module, id_using_modules); - if (!NIL_P(using_modules)) { - rb_hash_foreach(using_modules, using_module_i, (VALUE) cref); - } + Check_Type(module, T_MODULE); CONST_ID(id_refinements, "__refinements__"); refinements = rb_attr_get(module, id_refinements); if (NIL_P(refinements)) return; rb_hash_foreach(refinements, using_refinement, (VALUE) cref); } - -static int -check_cyclic_using(VALUE mod, VALUE _, VALUE search) -{ - VALUE using_modules; - ID id_using_modules; - CONST_ID(id_using_modules, "__using_modules__"); - - if (mod == search) { - rb_raise(rb_eArgError, "cyclic using detected"); - } - - using_modules = rb_attr_get(mod, id_using_modules); - if (!NIL_P(using_modules)) { - rb_hash_foreach(using_modules, check_cyclic_using, search); - } - - return ST_CONTINUE; -} - -/* - * call-seq: - * using(module) -> self - * - * Import class refinements from <i>module</i> into the receiver. - */ - -static VALUE -rb_mod_using(VALUE self, VALUE module) -{ - NODE *cref = rb_vm_cref(); - ID id_using_modules; - VALUE using_modules; - - Check_Type(module, T_MODULE); - check_cyclic_using(module, 0, self); - CONST_ID(id_using_modules, "__using_modules__"); - using_modules = rb_attr_get(self, id_using_modules); - if (NIL_P(using_modules)) { - using_modules = hidden_identity_hash_new(); - rb_ivar_set(self, id_using_modules, using_modules); - } - rb_hash_aset(using_modules, module, Qtrue); - rb_using_module(cref, module); - rb_clear_cache(); - rb_funcall(module, rb_intern("used"), 1, self); - return self; -} - VALUE rb_refinement_module_get_refined_class(VALUE module) { ID id_refined_class; @@ -1245,7 +1168,7 @@ if (!rb_block_given_p()) { rb_raise(rb_eArgError, "no block given"); } - check_class_or_module(klass); + Check_Type(klass, T_CLASS); CONST_ID(id_refinements, "__refinements__"); refinements = rb_attr_get(module, id_refinements); if (NIL_P(refinements)) { @@ -1645,10 +1568,11 @@ void ruby_Init_refinement(void) { - rb_define_private_method(rb_cModule, "using", rb_mod_using, 1); rb_define_private_method(rb_cModule, "refine", rb_mod_refine, 1); + rb_undef_method(rb_cClass, "refine"); rb_define_method(rb_cModule, "refinements", rb_mod_refinements, 0); - rb_define_singleton_method(rb_vm_top_self(), "using", top_using, 1); + rb_define_private_method(rb_singleton_class(rb_vm_top_self()), + "using", top_using, 1); } #if defined __GNUC__ && __GNUC__ >= 4 Index: vm_insnhelper.c =================================================================== --- vm_insnhelper.c (revision 38261) +++ vm_insnhelper.c (revision 38262) @@ -920,41 +920,6 @@ return Qundef; } -void rb_using_module(NODE *cref, VALUE module); - -static int -vm_using_module_i(VALUE module, VALUE value, VALUE arg) -{ - NODE *cref = (NODE *) arg; - - rb_using_module(cref, module); - return ST_CONTINUE; -} - -static void -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); - 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); - } - } - if (!NIL_P(using_modules)) { - rb_hash_foreach(using_modules, vm_using_module_i, - (VALUE) cref); - } - rb_using_module(cref, klass); -} - static VALUE check_match(VALUE pattern, VALUE target, enum vm_check_match_type type) { @@ -1694,42 +1659,13 @@ return vm_call_method(th, reg_cfp, &ci_entry); } -static VALUE -copy_refinement_iclass(VALUE iclass, VALUE superclass) -{ - VALUE result, c; - - Check_Type(iclass, T_ICLASS); - c = result = rb_include_class_new(RBASIC(iclass)->klass, superclass); - RCLASS_REFINED_CLASS(c) = RCLASS_REFINED_CLASS(iclass); - iclass = RCLASS_SUPER(iclass); - while (iclass && BUILTIN_TYPE(iclass) == T_ICLASS) { - c = RCLASS_SUPER(c) = rb_include_class_new(RBASIC(iclass)->klass, - RCLASS_SUPER(c)); - RCLASS_REFINED_CLASS(c) = RCLASS_REFINED_CLASS(iclass); - iclass = RCLASS_SUPER(iclass); - } - return result; -} - -static VALUE +static inline VALUE find_refinement(VALUE refinements, VALUE klass) { - VALUE refinement; - if (NIL_P(refinements)) { return Qnil; } - refinement = rb_hash_lookup(refinements, klass); - if (NIL_P(refinement) && - BUILTIN_TYPE(klass) == T_ICLASS) { - refinement = rb_hash_lookup(refinements, - RBASIC(klass)->klass); - if (!NIL_P(refinement)) { - refinement = copy_refinement_iclass(refinement, klass); - } - } - return refinement; + return rb_hash_lookup(refinements, klass); } static int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2); Index: test/ruby/test_refinement.rb =================================================================== --- test/ruby/test_refinement.rb (revision 38261) +++ test/ruby/test_refinement.rb (revision 38262) @@ -175,7 +175,8 @@ def test_module_eval foo = Foo.new assert_equal("Foo#x", foo.x) - assert_equal("FooExt#x", FooExt.module_eval { foo.x }) + assert_equal("Foo#x", FooExt.module_eval { foo.x }) + assert_equal("Foo#x", FooExt.module_eval("foo.x")) assert_equal("Foo#x", foo.x) end @@ -242,14 +243,15 @@ assert_not_equal(RefineSameClass::REFINEMENT1, RefineSameClass::REFINEMENT3) end + module FixnumFooExt + refine Fixnum do + def foo; "foo"; end + end + end + def test_respond_to? - m = Module.new { - refine Fixnum do - def foo; "foo"; end - end - } assert_equal(false, 1.respond_to?(:foo)) - assert_equal(true, m.module_eval { 1.respond_to?(:foo) }) + assert_equal(true, eval_using(FixnumFooExt, "1.respond_to?(:foo)")) assert_equal(false, 1.respond_to?(:foo)) end @@ -274,185 +276,49 @@ assert_equal(1, eval_using(ArrayEachExt, "[1, 2, 3].min")) end - def test_module_inclusion - m1 = Module.new { + module RefinePrependedClass + module M1 def foo - "m1#foo" + super << :m1 end + end - def bar - "m1#bar" - end - } - m2 = Module.new { - def bar - "m2#bar" - end + class C + prepend M1 - def baz - "m2#baz" - end - } - m3 = Module.new { - def baz - "m3#baz" - end - } - include_proc = Proc.new { - include m3, m2 - } - m = Module.new { - refine String do - include m1 - module_eval(&include_proc) - - def call_foo - foo - end - - def call_bar - bar - end - - def call_baz - baz - end - end - - def self.call_foo(s) - s.foo - end - - def self.call_bar(s) - s.bar - end - - def self.call_baz(s) - s.baz - end - } - assert_equal("m1#foo", m.module_eval { "abc".foo }) - assert_equal("m2#bar", m.module_eval { "abc".bar }) - assert_equal("m3#baz", m.module_eval { "abc".baz }) - assert_equal("m1#foo", m.module_eval { "abc".call_foo }) - assert_equal("m2#bar", m.module_eval { "abc".call_bar }) - assert_equal("m3#baz", m.module_eval { "abc".call_baz }) - assert_equal("m1#foo", m.call_foo("abc")) - assert_equal("m2#bar", m.call_bar("abc")) - assert_equal("m3#baz", m.call_baz("abc")) - end - - def test_refine_prepended_class - m1 = Module.new { def foo - super << :m1 - end - } - c = Class.new { - prepend m1 - - def foo [:c] end - } - m2 = Module.new { - refine c do + end + + module M2 + refine C do def foo super << :m2 end end - } - obj = c.new - assert_equal([:c, :m1, :m2], m2.module_eval { obj.foo }) + end end - def test_refine_module_without_overriding + def test_refine_prepended_class + x = eval_using(RefinePrependedClass::M2, + "TestRefinement::RefinePrependedClass::C.new.foo") + assert_equal([:c, :m1, :m2], x) + end + + def test_refine_module m1 = Module.new - c = Class.new { - include m1 - } - m2 = Module.new { - refine m1 do + assert_raise(TypeError) do + Module.new { + refine m1 do def foo :m2 end - end - } - obj = c.new - assert_equal(:m2, m2.module_eval { obj.foo }) - end - - def test_refine_module_with_overriding - m1 = Module.new { - def foo - super << :m1 - end - } - c0 = Class.new { - def foo - [:c0] - end - } - c = Class.new(c0) { - include m1 - } - m2 = Module.new { - refine m1 do - def foo - super << :m2 end - end - } - obj = c.new - assert_equal([:c0, :m1, :m2], m2.module_eval { obj.foo }) + } + end 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 { - def foo - "c1#foo" - end - } - c2 = Class.new(c1) { - include m1 - } - m2 = Module.new { - refine m1 do - end - } - obj = c2.new - assert_equal("c1#foo", m2.module_eval { obj.foo }) - end - def test_refine_neither_class_nor_module assert_raise(TypeError) do Module.new { @@ -474,15 +340,16 @@ end end - def test_refine_in_class_and_class_eval - c = Class.new { - refine Fixnum do - def foo - "c" + def test_refine_in_class + assert_raise(NoMethodError) do + Class.new { + refine Fixnum do + def foo + "c" + end end - end - } - assert_equal("c", c.class_eval { 123.foo }) + } + end end def test_main_using @@ -510,19 +377,33 @@ INPUT end + def test_main_using_is_private + assert_raise(NoMethodError) do + eval("self.using Module.new", TOPLEVEL_BINDING) + end + end + def test_no_kernel_using assert_raise(NoMethodError) do using Module.new end end + def test_no_module_using + assert_raise(NoMethodError) do + Module.new { + using Module.new + } + end + end + + class UsingClass + end + def test_module_using_class c = Class.new - m = Module.new assert_raise(TypeError) do - m.module_eval do - using c - end + eval("using TestRefinement::UsingClass", TOPLEVEL_BINDING) end end @@ -572,25 +453,6 @@ assert_equal({c => c_ext}, m.refinements) end - def test_refinements_no_recursion - c1 = Class.new - c1_ext = nil - m1 = Module.new { - refine c1 do - c1_ext = self - end - } - c2 = Class.new - c2_ext = nil - m2 = Module.new { - using m1 - refine c2 do - c2_ext = self - end - } - assert_equal({c2 => c2_ext}, m2.refinements) - end - def test_refine_without_block c1 = Class.new e = assert_raise(ArgumentError) { @@ -601,76 +463,6 @@ assert_equal("no block given", e.message) end - module IndirectUsing - class C - end - - module M1 - refine C do - def m1 - :m1 - end - end - end - - module M2 - refine C do - def m2 - :m2 - end - end - end - - module M3 - using M1 - using M2 - end - - module M - using M3 - - def self.call_m1 - C.new.m1 - end - - def self.call_m2 - C.new.m2 - end - end - end - - def test_indirect_using - assert_equal(:m1, IndirectUsing::M.call_m1) - assert_equal(:m2, IndirectUsing::M.call_m2) - end - - def test_indirect_using_module_eval - c = Class.new - m1 = Module.new { - refine c do - def m1 - :m1 - end - end - } - m2 = Module.new { - refine c do - def m2 - :m2 - end - end - } - m3 = Module.new { - using m1 - using m2 - } - m = Module.new { - using m3 - } - assert_equal(:m1, m.module_eval { c.new.m1 }) - assert_equal(:m2, m.module_eval { c.new.m2 }) - end - module SymbolToProc class C end @@ -722,67 +514,7 @@ m.refinements[c].inspect) end - module InlineMethodCache - class C - def foo - "original" - end - end - - module M - refine C do - def foo - "refined" - end - end - end - end - - def test_inline_method_cache - c = InlineMethodCache::C.new - f = Proc.new { c.foo } - assert_equal("original", f.call) - assert_equal("refined", InlineMethodCache::M.module_eval(&f)) - assert_equal("original", f.call) - end - - module UsingMethodCache - class C - def foo - "original" - end - end - - module M1 - refine C do - def foo - "M1" - end - end - end - - module M2 - refine C do - def foo - "M2" - end - end - end - - module M - c = C.new - ORIGINAL_FOO = c.foo - using M1 - c.foo - using M2 - M2_FOO = c.foo - end - end - def test_using_method_cache - assert_equal("original", UsingMethodCache::M::ORIGINAL_FOO) - assert_equal("M2", UsingMethodCache::M::M2_FOO) - assert_in_out_err([], <<-INPUT, %w(:M1 :M2), /Refinements are experimental/) require "refinement" @@ -816,28 +548,7 @@ INPUT end - def test_circular_using_is_not_allowed - a = Module.new - b = Module.new - - assert_raise ArgumentError do - a.module_eval do - using a - end - end - - b.module_eval do - using a - end - - assert_raise ArgumentError do - a.module_eval do - using b - end - end - end - - module RedifineRefinedMethod + module RedefineRefinedMethod class C def foo "original" @@ -860,10 +571,19 @@ end def test_redefine_refined_method - c = RedifineRefinedMethod::C.new - assert_equal("refined", RedifineRefinedMethod::M.module_eval { c.foo }) + x = eval_using(RedefineRefinedMethod::M, + "TestRefinement::RedefineRefinedMethod::C.new.foo") + assert_equal("refined", x) end + module StringExt + refine String do + def foo + "foo" + end + end + end + private def eval_using(mod, s) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/