From 5f382d41c30b1e433d777a8daaedb247d7f2a57c Mon Sep 17 00:00:00 2001
From: Charles Oliver Nutter <headius@headius.com>
Date: Fri, 21 Oct 2016 09:33:25 -0500
Subject: Explicitly unpack the expanded args to avoid execution order diff.

In https://bugs.ruby-lang.org/issues/12860 I argue that MRI's
execution order here is incorrect. The splatting of the 'c' args
should happen before the shift, but it happens after. On JRuby, it
behaves the way you would expect, leading to the 'c' args splat
still containing the block and producing an error like "cannot
convert proc to symbol" when the send attempts to coerce
it.

This patch makes the unpacking order explicit with a multi-assign,
which behaves properly on all implementations I tested.
---
 activesupport/lib/active_support/callbacks.rb | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index 890b1cd73b..9b9c9cbbdd 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -410,8 +410,8 @@ module ActiveSupport
         # values.
         def make_lambda
           lambda do |target, value, &block|
-            c = expand(target, value, block)
-            c.shift.send(*c, &c.shift)
+            target, block, method, *arguments = expand(target, value, block)
+            target.send(method, *arguments, &block)
           end
         end
 
@@ -419,8 +419,8 @@ module ActiveSupport
         # values, but then return the boolean inverse of that result.
         def inverted_lambda
           lambda do |target, value, &block|
-            c = expand(target, value, block)
-            ! c.shift.send(*c, &c.shift)
+            target, block, method, *arguments = expand(target, value, block)
+            ! target.send(method, *arguments, &block)
           end
         end
 
-- 
cgit v1.2.3