【一人 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.rb
で using 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
で、これがなんでエラーになっているのかというと stringio
で include Enumerable
を行っているんですが『 Enumerable
を refine
で拡張したあとに 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
をするとなぜか以前の挙動がぶっ壊れるというやつです。
これ、何でバグってるのか全然わからないんですが現在は修正済みになっています。