aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-11-07 04:09:51 +0000
committershugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-11-07 04:09:51 +0000
commit5836962f48200c71f5989315b9e2ac4db2b87541 (patch)
tree0bfbe67f67e006879dc95fd4c76f7a8b57b24975
parent1c5104ac9c0803c476b54d751b0ec4579a1828af (diff)
downloadruby-5836962f48200c71f5989315b9e2ac4db2b87541.tar.gz
* eval.c (rb_mod_refine): set RMODULE_IS_REFINEMENT to a created
refinement module, and don't override method_added. * vm_method.c (rb_method_entry_make): check redefinition of optimized methods when a method is added to a refinement module. [ruby-core:48970] [Bug #7290] * test/ruby/test_refinement.rb: related test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37534 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog11
-rw-r--r--eval.c18
-rw-r--r--include/ruby/ruby.h1
-rw-r--r--test/ruby/test_refinement.rb12
-rw-r--r--vm_method.c10
5 files changed, 35 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index 18df509fed..6057c99c5d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Wed Nov 7 12:49:39 2012 Shugo Maeda <shugo@ruby-lang.org>
+
+ * eval.c (rb_mod_refine): set RMODULE_IS_REFINEMENT to a created
+ refinement module, and don't override method_added.
+
+ * vm_method.c (rb_method_entry_make): check redefinition of
+ optimized methods when a method is added to a refinement module.
+ [ruby-core:48970] [Bug #7290]
+
+ * test/ruby/test_refinement.rb: related test.
+
Wed Nov 7 11:48:14 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* misc/ruby-additional.el (ruby-mode-set-encoding): now encoding needs
diff --git a/eval.c b/eval.c
index 08a5624ba4..bd0f085f9d 100644
--- a/eval.c
+++ b/eval.c
@@ -1157,21 +1157,6 @@ rb_mod_using(VALUE self, VALUE module)
return self;
}
-void rb_redefine_opt_method(VALUE, ID);
-
-static VALUE
-refinement_module_method_added(VALUE mod, VALUE mid)
-{
- ID id = SYM2ID(mid);
- ID id_refined_class;
- VALUE klass;
-
- CONST_ID(id_refined_class, "__refined_class__");
- klass = rb_ivar_get(mod, id_refined_class);
- rb_redefine_opt_method(klass, id);
- return Qnil;
-}
-
static VALUE
refinement_module_include(int argc, VALUE *argv, VALUE module)
{
@@ -1234,12 +1219,11 @@ rb_mod_refine(VALUE module, VALUE klass)
mod = rb_hash_lookup(refinements, klass);
if (NIL_P(mod)) {
mod = rb_module_new();
+ FL_SET(mod, RMODULE_IS_REFINEMENT);
CONST_ID(id_refined_class, "__refined_class__");
rb_ivar_set(mod, id_refined_class, klass);
CONST_ID(id_defined_at, "__defined_at__");
rb_ivar_set(mod, id_defined_at, module);
- rb_define_singleton_method(mod, "method_added",
- refinement_module_method_added, 1);
rb_define_singleton_method(mod, "include",
refinement_module_include, -1);
rb_using_refinement(cref, klass, mod);
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 8074334269..e8f0d15380 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -721,6 +721,7 @@ struct RClass {
#define RMODULE_M_TBL(m) RCLASS_M_TBL(m)
#define RMODULE_SUPER(m) RCLASS_SUPER(m)
#define RMODULE_IS_OVERLAID FL_USER2
+#define RMODULE_IS_REFINEMENT FL_USER3
struct RFloat {
struct RBasic basic;
diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb
index 20542d6492..aeb519c18d 100644
--- a/test/ruby/test_refinement.rb
+++ b/test/ruby/test_refinement.rb
@@ -191,6 +191,18 @@ class TestRefinement < Test::Unit::TestCase
assert_equal(0, 1 / 2)
end
+ def test_override_builtin_method_with_method_added
+ m = Module.new {
+ refine Fixnum do
+ def self.method_added(*args); end
+ def +(other) "overriden" end
+ end
+ }
+ assert_equal(3, 1 + 2)
+ assert_equal("overriden", m.module_eval { 1 + 2 })
+ assert_equal(3, 1 + 2)
+ end
+
def test_return_value_of_refine
mod = nil
result = nil
diff --git a/vm_method.c b/vm_method.c
index 033c81f262..ca521563e5 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -167,6 +167,8 @@ rb_free_method_entry(rb_method_entry_t *me)
static int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2);
+void rb_redefine_opt_method(VALUE, ID);
+
static rb_method_entry_t *
rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type,
rb_method_definition_t *def, rb_method_flag_t noex)
@@ -196,6 +198,14 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type,
#if NOEX_NOREDEF
rklass = klass;
#endif
+ if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
+ ID id_refined_class;
+ VALUE refined_class;
+
+ CONST_ID(id_refined_class, "__refined_class__");
+ refined_class = rb_ivar_get(klass, id_refined_class);
+ rb_redefine_opt_method(refined_class, mid);
+ }
klass = RCLASS_ORIGIN(klass);
mtbl = RCLASS_M_TBL(klass);