Project

General

Profile

Actions

Bug #21525

closed

Inconsistent execution order for methods with constant blocks

Added by joel@drapper.me (Joel Drapper) 2 days ago. Updated 1 day ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 3.4.5 (2025-08-01 revision 07f7832cff) +PRISM [arm64-darwin24]
[ruby-core:122892]

Description

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.

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.

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.

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].


Related issues 1 (0 open1 closed)

Related to Ruby - Bug #20640: Evaluation Order Issue in f(**h, &h.delete(key))Closedjeremyevans0 (Jeremy Evans)Actions
Actions

Also available in: Atom PDF

Like0
Like1Like0Like0Like0