Feature #19777


Make `Kernel#lambda` raise when called without a literal block

Added by alanwu (Alan Wu) 12 months ago. Updated 10 months ago.

Target version:


Since 3.0.0, released in 2020, calling Kernel#lambda without a literal block
has been issuing a deprecation warning:

Warning[:deprecated] = true
def foo(&b) lambda(&b) end
foo {}
# => test.rb:2: warning: lambda without a literal block is deprecated; use the proc without lambda instead

I think enough time has passed and we should make it raise in all situations
where it currently issues a deprecation warning. The original decision to
deprecate is here:

The new behavior allows one to predict whether Kernel#lambda will return by
inspecting its direct caller, checking whether the call site has a literal
block. It will remove some hard-to-predict cases where Kernel#lambda receives
a non-literal block forwarded with super or rb_funcall_passing_block. The
method will always return a lambda, if it returns. However, note that send
will be a special exception in this new model:

Warning[:deprecated] = true

singleton_class.send(:public, :lambda)

p (send(:lambda) {}).lambda?         # => true without warning
p (public_send(:lambda) {}).lambda?  # => true with warning, would raise instead

This newer model is friendlier to some optimization we're investigating for
YJIT as it has fewer moving parts.

Updated by (Dat Tong Ngoc) 12 months ago

  • File added
Actions #2

Updated by alanwu (Alan Wu) 12 months ago

  • File deleted (
Actions #3

Updated by alanwu (Alan Wu) 11 months ago

  • Tracker changed from Feature to Misc

Updated by Dan0042 (Daniel DeLorme) 11 months ago

The ship has sailed, but I should at least mention I am disappointed at this turn of things. Again deprecating things for no concrete benefit. How ironic that #15973 started with "change Kernel#lambda so it always returns a lambda" and ended with "let's make sure people can't do that".

Updated by mame (Yusuke Endoh) 11 months ago

Discussed at the dev meeting. @matz (Yukihiro Matsumoto) said go ahead.

Actions #6

Updated by alanwu (Alan Wu) 10 months ago

  • Tracker changed from Misc to Feature
Actions #7

Updated by alanwu (Alan Wu) 10 months ago

  • Status changed from Open to Closed

Applied in changeset git|39ee3e22bd3d071c1c283b6b8dbd1af413342fb1.

Make Kernel#lambda raise when given non-literal block

Previously, Kernel#lambda returned a non-lambda proc when given a
non-literal block and issued a warning under the :deprecated category.
With this change, Kernel#lambda will always return a lambda proc, if it
returns without raising.

Due to interactions with block passing optimizations, we previously had
two separate code paths for detecting whether Kernel#lambda got a
literal block. This change allows us to remove one path, the hack done
with rb_control_frame_t::block_code introduced in 85a337f for supporting
situations where Kernel#lambda returned a non-lambda proc.

[Feature #19777]

Co-authored-by: Takashi Kokubun


Also available in: Atom PDF