In Ruby 3.4 why does Ruby's it
default block parameter get set to false
after a rescue
in a block?
42.tap do
puts "it is #{it}"
raise "uh oh"
rescue
puts "it is now #{it}"
end
prints:
it is 42
it is now false
If you use _1
instead of it
it works as expected.
According to Bug #21313 – it
in rescue/ensure on prism, this is a bug that is specific to the YARV Ruby Implementation, and even more precisely, the bug only occurs when using the new Prism parser:
ruby bug21313.rb
# ruby 3.4.5 (2025-07-16 revision 20cda200d3) +PRISM [arm64-darwin24]
# false
ruby --parser=parse.y bug21313.rb
# ruby 3.4.5 (2025-07-16 revision 20cda200d3) [arm64-darwin24]
# 0
jruby bug21313.rb
# jruby 10.0.1.0 (3.4.2) 2025-07-17 0f10d1dfdf OpenJDK 64-Bit Server VM 24.0.2 on 24.0.2 +indy +jit [arm64-darwin]
# 0
As you can see, with JRuby, the result is correct. Also, with YARV, the result is correct if you turn off the Prism parser.
TruffleRuby, MRuby, PicoRuby, and Opal do not support it
.
The bug was fixed in Pull Request 13360 [Bug #21313] Handle it
in rescue and ensure blocks. It looks like the bug fix was not backported to YARV 3.4, so you will have to wait until YARV 3.5 if you need YARV and Prism, or use YARV without Prism or JRuby in the meantime.
For the record, this is the test case (cribbed from the bug report):
puts RUBY_DESCRIPTION
1.times do
raise
rescue
p it
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With