Feature #19777
closedMake `Kernel#lambda` raise when called without a literal block
Description
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: https://bugs.ruby-lang.org/issues/15973#note-46
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 caumongthanhnguoi1985@gmail.com (Dat Tong Ngoc) over 1 year ago
- File FACEBOOK-2_attachments.zip added
Updated by alanwu (Alan Wu) over 1 year ago
- File deleted (
FACEBOOK-2_attachments.zip)
Updated by alanwu (Alan Wu) over 1 year ago
- Tracker changed from Feature to Misc
Updated by Dan0042 (Daniel DeLorme) over 1 year 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) over 1 year ago
Discussed at the dev meeting. @matz (Yukihiro Matsumoto) said go ahead.
Updated by alanwu (Alan Wu) over 1 year ago
- Tracker changed from Misc to Feature
Updated by alanwu (Alan Wu) over 1 year 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 takashikkbn@gmail.com