【一人 bugs.ruby Advent Calendar 2020】[Bug #16852] Refining Enumerable fails with ruby 2.7【18日目】

一人 bugs.ruby Advent Calendar 2020 18日目の記事になります。

[Bug #16852] Refining Enumerable fails with ruby 2.7

Ruby 2.7 系の Refinements のバグ報告チケットになります。
元々は以下のように RSpec での再現コードで報告されていた。

# file: refinement_bug.rb
module RefinementBug
  refine Enumerable do
    def refined_method
      puts "Called #refined_method"
    end
  end
end
# file: spec/spec_helper.rb
require_relative "../refinement_bug"
# file: spec/test.rb

require_relative "../refinement_bug"

using RefinementBug

puts "Using Ruby #{RUBY_VERSION}"
[].refined_method

上記のファイルがある状態で rspec を実行すると以下のようなエラーが発生していた。

~/minimal_refinement_failure> rspec spec/test.rb
Using Ruby 2.7.1

An error occurred while loading ./spec/test.rb.
Failure/Error: [].refined_method

NoMethodError:
  undefined method `refined_method' for []:Array
# ./spec/test.rb:8:in `<top (required)>'
No examples found.

Finished in 0.00003 seconds (files took 0.12287 seconds to load)
0 examples, 0 failures, 1 error occurred outside of examples

spec/test.rbusing RefinementBug しているのに #refined_method が見つからないってエラーになっています。
これ、わたしが最小構成調べて以下のようなコードで再現するのを見つけました。

module RefinementBug
  refine Enumerable do
    def refined_method
      puts "Called #refined_method"
    end
  end
end

# Error if `require "stringio"`
require "stringio"

using RefinementBug

puts "Using Ruby #{RUBY_VERSION}"

# error: undefined method `refined_method' for []:Array (NoMethodError)
[].refined_method

で、これがなんでエラーになっているのかというと stringioinclude Enumerable を行っているんですが『 Enumerablerefine で拡張したあとに include Enumerable された場合に RefinementBug が反映されなくなる』という現象でした。
更に最小構成なコードは以下になります。

module M; end
class X
  include M
end

module RefinementBug
  refine M do
    def refined_method
      puts "Called #refined_method"
    end
  end
end

class Y
  # Error if include M
  include M
end

using RefinementBug

puts "Using Ruby #{RUBY_VERSION}"

# error: undefined method `refined_method' for #<X:0x000055d4e22468c0> (NoMethodError)
X.new.refined_method

Refinements で M を拡張したあとに include M をするとなぜか以前の挙動がぶっ壊れるというやつです。
これ、何でバグってるのか全然わからないんですが現在は修正済みになっています。