[Bug #20302] Multiple refinements cannot be applied to the same module
In the following code, the iclass tree of refinements in cref should be <iclass of Kernel@M2> -> <iclass of Kernel@M1> -> Kernel. However, the iclass tree was broken because of code for included modules of refinements in rb_using_refinement(). Refinement#include is now removed, so this commit removes such unnecessary code. ```ruby module M1 refine(Kernel) do def f1 = :f1 end end module M2 refine(Kernel) do def f2 = :f2 end end class Foo using M1 using M2 def test p f2 #=> :f2 p f1 # expected => :f1 # actual => undefined local variable or method 'f1' for an instance of Foo end end Foo.new.test ```
This commit is contained in:
parent
3a04ea2d03
commit
d50f9ca2dd
6
eval.c
6
eval.c
@ -1276,12 +1276,6 @@ rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module)
|
|||||||
|
|
||||||
RCLASS_M_TBL(c) = RCLASS_M_TBL(module);
|
RCLASS_M_TBL(c) = RCLASS_M_TBL(module);
|
||||||
|
|
||||||
module = RCLASS_SUPER(module);
|
|
||||||
while (module && module != klass) {
|
|
||||||
c = RCLASS_SET_SUPER(c, rb_include_class_new(module, RCLASS_SUPER(c)));
|
|
||||||
RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass);
|
|
||||||
module = RCLASS_SUPER(module);
|
|
||||||
}
|
|
||||||
rb_hash_aset(CREF_REFINEMENTS(cref), klass, iclass);
|
rb_hash_aset(CREF_REFINEMENTS(cref), klass, iclass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2672,6 +2672,35 @@ class TestRefinement < Test::Unit::TestCase
|
|||||||
assert_equal(:v2, obj.cached_foo_callsite)
|
assert_equal(:v2, obj.cached_foo_callsite)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# [Bug #20302]
|
||||||
|
def test_multiple_refinements_for_same_module
|
||||||
|
assert_in_out_err([], <<-INPUT, %w(:f2 :f1), [])
|
||||||
|
module M1
|
||||||
|
refine(Kernel) do
|
||||||
|
def f1 = :f1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module M2
|
||||||
|
refine(Kernel) do
|
||||||
|
def f2 = :f2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Foo
|
||||||
|
using M1
|
||||||
|
using M2
|
||||||
|
|
||||||
|
def test
|
||||||
|
p f2
|
||||||
|
p f1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Foo.new.test
|
||||||
|
INPUT
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def eval_using(mod, s)
|
def eval_using(mod, s)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user