aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-09-23 11:46:33 +0000
committershugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-09-23 11:46:33 +0000
commitb166d4bc7c9710e1b6184659d2f51710228998f6 (patch)
tree97d7228c670ed87e3c39b77f7d96b97503bd170d
parentf32fba70c5984f990503bdc5b3aac245117de4d6 (diff)
downloadruby-b166d4bc7c9710e1b6184659d2f51710228998f6.tar.gz
* eval.c (rb_mod_refine): refine modules as well.
[ruby-core:76199] [Feature #12534] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56213 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog5
-rw-r--r--diff13
-rw-r--r--eval.c20
-rw-r--r--test/ruby/test_refinement.rb61
-rw-r--r--vm_method.c8
5 files changed, 93 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 87edb68dff..8d4752ef3f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Fri Sep 23 20:36:05 2016 Shugo Maeda <shugo@ruby-lang.org>
+
+ * eval.c (rb_mod_refine): refine modules as well.
+ [ruby-core:76199] [Feature #12534]
+
Fri Sep 23 20:19:09 2016 Akinori MUSHA <knu@iDaemons.org>
* man/ruby.1: Update the paragraphs in "Rich Libraries" which
diff --git a/diff b/diff
new file mode 100644
index 0000000000..b16c897709
--- /dev/null
+++ b/diff
@@ -0,0 +1,13 @@
+diff --git a/tool/mkconfig.rb b/tool/mkconfig.rb
+index 6b6f14c..ee0642c 100755
+--- a/tool/mkconfig.rb
++++ b/tool/mkconfig.rb
+@@ -20,7 +20,7 @@
+ require "fileutils"
+ mkconfig = File.basename($0)
+
+-fast = {'prefix'=>TRUE, 'ruby_install_name'=>TRUE, 'INSTALL'=>TRUE, 'EXEEXT'=>TRUE}
++fast = {'prefix'=>true, 'ruby_install_name'=>true, 'INSTALL'=>true, 'EXEEXT'=>true}
+
+ win32 = /mswin/ =~ arch
+ universal = /universal.*darwin/ =~ arch
diff --git a/eval.c b/eval.c
index 1baf914a3a..5f5da2881a 100644
--- a/eval.c
+++ b/eval.c
@@ -1092,6 +1092,16 @@ rb_mod_prepend(int argc, VALUE *argv, VALUE module)
return module;
}
+static void
+ensure_class_or_module(VALUE obj)
+{
+ if (!RB_TYPE_P(obj, T_CLASS) && !RB_TYPE_P(obj, T_MODULE)) {
+ rb_raise(rb_eTypeError,
+ "wrong argument type %"PRIsVALUE" (expected Class or Module)",
+ rb_obj_class(obj));
+ }
+}
+
static VALUE
hidden_identity_hash_new(void)
{
@@ -1106,7 +1116,7 @@ rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module)
{
VALUE iclass, c, superclass = klass;
- Check_Type(klass, T_CLASS);
+ ensure_class_or_module(klass);
Check_Type(module, T_MODULE);
if (NIL_P(CREF_REFINEMENTS(cref))) {
CREF_REFINEMENTS_SET(cref, hidden_identity_hash_new());
@@ -1231,11 +1241,11 @@ add_activated_refinement(VALUE activated_refinements,
/*
* call-seq:
- * refine(klass) { block } -> module
+ * refine(mod) { block } -> module
*
- * Refine <i>klass</i> in the receiver.
+ * Refine <i>mod</i> in the receiver.
*
- * Returns an overlaid module.
+ * Returns a module, where refined methods are defined.
*/
static VALUE
@@ -1255,7 +1265,7 @@ rb_mod_refine(VALUE module, VALUE klass)
rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine");
}
- Check_Type(klass, T_CLASS);
+ ensure_class_or_module(klass);
CONST_ID(id_refinements, "__refinements__");
refinements = rb_attr_get(module, id_refinements);
if (NIL_P(refinements)) {
diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb
index c3c2dbc61f..4f7918e810 100644
--- a/test/ruby/test_refinement.rb
+++ b/test/ruby/test_refinement.rb
@@ -345,17 +345,64 @@ class TestRefinement < Test::Unit::TestCase
assert_equal([:c, :m1, :m2], x)
end
- def test_refine_module
- m1 = Module.new
- assert_raise(TypeError) do
- Module.new {
- refine m1 do
+ module RefineModule
+ module M
+ def foo
+ "M#foo"
+ end
+
+ def bar
+ "M#bar"
+ end
+
+ def baz
+ "M#baz"
+ end
+ end
+
+ class C
+ include M
+
+ def baz
+ "#{super} C#baz"
+ end
+ end
+
+ module M2
+ refine M do
def foo
- :m2
+ "M@M2#foo"
end
+
+ def bar
+ "#{super} M@M2#bar"
end
- }
+
+ def baz
+ "#{super} M@M2#baz"
+ end
+ end
end
+
+ using M2
+
+ def self.call_foo
+ C.new.foo
+ end
+
+ def self.call_bar
+ C.new.bar
+ end
+
+ def self.call_baz
+ C.new.baz
+ end
+ end
+
+ def test_refine_module
+ assert_equal("M@M2#foo", RefineModule.call_foo)
+ assert_equal("M#bar M@M2#bar", RefineModule.call_bar)
+ assert_equal("M#baz C#baz", RefineModule.call_baz)
end
def test_refine_neither_class_nor_module
diff --git a/vm_method.c b/vm_method.c
index b5a6f538d0..c7417de455 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -439,13 +439,17 @@ make_method_entry_refined(VALUE owner, rb_method_entry_t *me)
}
else {
struct {
- const struct rb_method_entry_struct *orig_me;
+ struct rb_method_entry_struct *orig_me;
VALUE owner;
} refined;
rb_vm_check_redefinition_opt_method(me, me->owner);
- refined.orig_me = rb_method_entry_clone(me);
+ refined.orig_me =
+ rb_method_entry_alloc(me->called_id, me->owner,
+ me->defined_class || owner,
+ method_definition_addref(me->def));
+ METHOD_ENTRY_FLAGS_COPY(refined.orig_me, me);
refined.owner = owner;
method_definition_set(me, method_definition_create(VM_METHOD_TYPE_REFINED, me->called_id), (void *)&refined);