Skip to content

Commit

Permalink
[Bug #20302] Multiple refinements cannot be applied to the same module
Browse files Browse the repository at this point in the history
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
```
  • Loading branch information
shugo committed Feb 27, 2024
1 parent 3a04ea2 commit d50f9ca
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 6 deletions.
6 changes: 0 additions & 6 deletions eval.c
Expand Up @@ -1276,12 +1276,6 @@ rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE 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);
}

Expand Down
29 changes: 29 additions & 0 deletions test/ruby/test_refinement.rb
Expand Up @@ -2672,6 +2672,35 @@ def foo = :v2 # invalidate
assert_equal(:v2, obj.cached_foo_callsite)
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

def eval_using(mod, s)
Expand Down

0 comments on commit d50f9ca

Please sign in to comment.