
Issue #21525 has been updated by joel@drapper.me (Joel Drapper). The behaviour is a little surprising if you don’t understand why it’s different in these cases. But no I can’t think of any non-pathological reason to actually do this in production code and I agree that the performance benefit is probably worth the cost of slight inconsistency in extreme edge cases. There are much worse examples of where Ruby executes out of order, such as ```ruby b.push(bar) while (bar = a.pop) ``` This one actually has caught me out with production code a number of times and still catches me out regularly. ---------------------------------------- Bug #21525: Inconsistent execution order for methods with constant blocks https://bugs.ruby-lang.org/issues/21525#change-114198 * 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/