Project

General

Profile

Actions

Feature #19777

closed

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

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

Status:
Closed
Assignee:
-
Target version:
-
[ruby-core:114248]

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) 10 months ago

  • File FACEBOOK-2_attachments.zip added
Actions #2

Updated by alanwu (Alan Wu) 10 months ago

  • File deleted (FACEBOOK-2_attachments.zip)
Actions #3

Updated by alanwu (Alan Wu) 9 months ago

  • Tracker changed from Feature to Misc

Updated by Dan0042 (Daniel DeLorme) 9 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) 9 months ago

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

Actions #6

Updated by alanwu (Alan Wu) 8 months ago

  • Tracker changed from Misc to Feature
Actions #7

Updated by alanwu (Alan Wu) 8 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

Actions

Also available in: Atom PDF

Like1
Like0Like0Like0Like0Like0Like0Like0