aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorAlan Wu <XrXr@users.noreply.github.com>2019-07-13 12:04:01 -0400
committerAlan Wu <XrXr@users.noreply.github.com>2019-12-21 09:08:52 -0500
commit85a337f986fe6da99c7f8358f790f17b122b3903 (patch)
treef5c41137c2db802327cd4c405de7a922cbae7453 /test
parentddb6023d64a8c96348b4e67603753e2916a04f28 (diff)
downloadruby-85a337f986fe6da99c7f8358f790f17b122b3903.tar.gz
Kernel#lambda: return forwarded block as non-lambda proc
Before this commit, Kernel#lambda can't tell the difference between a directly passed literal block and one passed with an ampersand. A block passed with an ampersand is semantically speaking already a non-lambda proc. When Kernel#lambda receives a non-lambda proc, it should simply return it. Implementation wise, when the VM calls a method with a literal block, it places the code for the block on the calling control frame and passes a pointer (block handler) to the callee. Before this commit, the VM forwards block arguments by simply forwarding the block handler, which leaves the slot for block code unused when a control frame forwards its block argument. I use the vacant space to indicate that a frame has forwarded its block argument and inspect that in Kernel#lambda to detect forwarded blocks. This is a very ad-hoc solution and relies *heavily* on the way block passing works in the VM. However, it's the most self-contained solution I have. [Bug #15620]
Diffstat (limited to 'test')
-rw-r--r--test/ruby/test_lambda.rb20
1 files changed, 20 insertions, 0 deletions
diff --git a/test/ruby/test_lambda.rb b/test/ruby/test_lambda.rb
index b9412d4540..03b501a6c9 100644
--- a/test/ruby/test_lambda.rb
+++ b/test/ruby/test_lambda.rb
@@ -74,6 +74,26 @@ class TestLambdaParameters < Test::Unit::TestCase
assert_raise(ArgumentError, bug9605) {proc(&plus).call [1,2]}
end
+ def pass_along(&block)
+ lambda(&block)
+ end
+
+ def pass_along2(&block)
+ pass_along(&block)
+ end
+
+ def test_create_non_lambda_for_proc_one_level
+ f = pass_along {}
+ refute_predicate(f, :lambda?, '[Bug #15620]')
+ assert_nothing_raised(ArgumentError) { f.call(:extra_arg) }
+ end
+
+ def test_create_non_lambda_for_proc_two_levels
+ f = pass_along2 {}
+ refute_predicate(f, :lambda?, '[Bug #15620]')
+ assert_nothing_raised(ArgumentError) { f.call(:extra_arg) }
+ end
+
def test_instance_exec
bug12568 = '[ruby-core:76300] [Bug #12568]'
assert_nothing_raised(ArgumentError, bug12568) do