ruby-changes:60601
From: Jeremy <ko1@a...>
Date: Tue, 31 Mar 2020 16:31:54 +0900 (JST)
Subject: [ruby-changes:60601] bb93659fef (ruby_2_7): Fix pp when passed a empty ruby2_keywords-flagged hash as array element (#2966)
https://git.ruby-lang.org/ruby.git/commit/?id=bb93659fef From bb93659fefd7f4557129043742771a33bd30c255 Mon Sep 17 00:00:00 2001 From: Jeremy Evans <code@j...> Date: Tue, 31 Mar 2020 00:10:57 -0700 Subject: Fix pp when passed a empty ruby2_keywords-flagged hash as array element (#2966) This causes problems because the hash is passed to a block not accepting keywords. Because the hash is empty and keyword flagged, it is removed before calling the block. This doesn't cause an ArgumentError because it is a block and not a lambda. Just like any other block not passed required arguments, arguments not passed are set to nil. Issues like this are a strong reason not to have ruby2_keywords by default. Fixes [Bug #16519] This backports 28d31ead34baff1c4abc0d7d902ef4bc1d576fb2 and 0ea759eac9234afc47e8fb1bcacfe9ee12c8ffb6, but needed to be modified for 2.7 as 2.7 will perform empty keyword to positional hash conversion for required arguments, which will happen if "v" in the seplist method is empty when yielded. Co-authored-by: NARUSE, Yui <nurse@u...> diff --git a/lib/pp.rb b/lib/pp.rb index 81a9a16..012b328 100644 --- a/lib/pp.rb +++ b/lib/pp.rb @@ -223,7 +223,16 @@ class PP < PrettyPrint https://github.com/ruby/ruby/blob/trunk/lib/pp.rb#L223 else sep.call end - yield(*v) + case v.last + when Hash + if Hash.ruby2_keywords_hash?(v.last) + yield(*v, **{}) + else + yield(*v) + end + else + yield(*v) + end } end diff --git a/test/test_pp.rb b/test/test_pp.rb index 3262417..cd16af6 100644 --- a/test/test_pp.rb +++ b/test/test_pp.rb @@ -176,6 +176,11 @@ class PPSingleLineTest < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/test_pp.rb#L176 assert_equal("{1=>1}", PP.singleline_pp({ 1 => 1}, ''.dup)) # [ruby-core:02699] assert_equal("[1#{', 1'*99}]", PP.singleline_pp([1]*100, ''.dup)) end + + def test_hash_in_array + assert_equal("[{}]", PP.singleline_pp([->(*a){a.last}.ruby2_keywords.call(**{})], ''.dup)) + assert_equal("[{}]", PP.singleline_pp([Hash.ruby2_keywords_hash({})], ''.dup)) + end end class PPDelegateTest < Test::Unit::TestCase -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/