
Issue #21525 has been reported by joel@drapper.me (Joel Drapper). ---------------------------------------- Bug #21525: Inconsistent execution order for methods with constant blocks https://bugs.ruby-lang.org/issues/21525 * Author: joel@drapper.me (Joel Drapper) * Status: Open * ruby -v: ruby 3.4.5 (2025-08-01 revision 07f7832cff) +PRISM [arm64-darwin24] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- If you call a method and pass in a splat of an array with a block argument coerced from calling a method, Ruby maintains the expected execution order and the called method receives a copy of the array prior to modification. In this example, the output is `[1, 2, 3]` since the copy is made before the `bar` method can modify it. ```ruby ARRAY = [1, 2, 3] def bar ARRAY.pop -> {} end def example(*args, &) puts args end example(*ARRAY, &bar) ``` However, when passing a constant, the block coercion itself is able to modify the array. ```ruby ARRAY = [1, 2, 3] module Foo module Bar def self.to_proc ARRAY.pop -> {} end end end def example(*args, &) puts args end example(*ARRAY, &Foo::Bar) ``` Another way to trigger this is to define a `const_missing` method that modifies the array. ```ruby ARRAY = [1, 2, 3] module Foo def self.const_missing(name) ARRAY.pop -> {} end end def example(*args, &) puts args end example(*ARRAY, &Foo::Bar) ``` In both these cases, the output is `[1, 2]` instead of the expected `[1, 2, 3]`. -- https://bugs.ruby-lang.org/