Project

General

Profile

Bug #12821

Object converted to Hash unexpectedly under certain method call

Added by tanahiro (Hiroyuki Tanaka) about 3 years ago. Updated over 2 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
2.2.5p319, 2.3.1p112, 2.4.0-preview2
Backport:
[ruby-core:77527]

Description

Hi,

I saw a bit strange behavior (at least for me) with the code below; an object given as an argument to a method with a default value and a keyword argument becomes Hash class if the object has 'to_hash' method with ruby >= 2.2, but it is not converted to Hash with ruby 2.1.
I expected the behavior of ruby 2.1.
Is this a bug or expected behavior of ruby >= 2.2?

I tested both on Linux x86_64 (CentOS 6) and Mac OS X 10.11.6.

class Test1
end

class Test2
  def to_hash
    {0 => [0, 1]}
  end
end

def argtest1 foo, bar: nil
  p foo.class
end

def argtest2 foo = nil, bar: nil
  p foo.class
end

test1 = Test1.new
test2 = Test2.new

argtest1(test1) # => Test1
argtest1(test2) # => Test2

argtest2(test1) # => Test1
argtest2(test2) # => Hash (2.2.5p319, 2.3.1p112, 2.4.0-preview2), Test2 (2.1.10p492)

Regards,
Hiroyuki Tanaka


Related issues

Related to Ruby master - Feature #14183: "Real" keyword argumentClosedActions
Has duplicate Ruby master - Bug #12884: Using a HashWithIndifferentAccess with a default value in a function with a keyword parameter converts it to a Hash.ClosedActions

History

Updated by kernigh (George Koehler) about 3 years ago

It's not what I expected, but Ruby is splitting test2 into two hashes, with all keywords into the second hash. There are no keywords in {0 => [0, 1]}, so Ruby passes {0 => [0, 1]} as foo and {} as keywords.

def argtest2 foo = nil, bar: nil
  printf "foo = %p (%p), bar: %p\n", foo, foo.class, bar
end

argtest2(0 => [0, 1], bar: 2) # => foo = {0=>[0, 1]} (Hash), bar: 2
argtest2(bar: 2, 0 => [0, 1]) # => foo = {0=>[0, 1]} (Hash), bar: 2
argtest2(0 => [0, 1])         # => foo = {0=>[0, 1]} (Hash), bar: nil

So argtest2(test2) acts like argtest2(0 => [0, 1]). I don't know why Ruby does this split, or why Ruby 2.1 was different.

#2

Updated by shyouhei (Shyouhei Urabe) about 3 years ago

  • Has duplicate Bug #12884: Using a HashWithIndifferentAccess with a default value in a function with a keyword parameter converts it to a Hash. added

Updated by nobu (Nobuyoshi Nakada) about 3 years ago

  • Description updated (diff)
  • Subject changed from Object converted to Hash unexpectedly uder certain method call to Object converted to Hash unexpectedly under certain method call

Updated by rrroybbbean (RRRoy BBBean) about 3 years ago

I get the same odd behavior with:

ruby --version ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]

./ruby --version ruby 2.4.0preview2 (2016-09-09 trunk 56129) [x86_64-linux]

It looks like the combination ( foo = nil, bar: nil ) causes the issue.

On 10/31/2016 01:01 AM, nobu@ruby-lang.org wrote:

Issue #12821 has been updated by Nobuyoshi Nakada.

Subject changed from Object converted to Hash unexpectedly uder certain method call to Object converted to Hash unexpectedly under certain method call
Description updated


Bug #12821: Object converted to Hash unexpectedly under certain method call
https://bugs.ruby-lang.org/issues/12821#change-61140

  • Author: Hiroyuki Tanaka
  • Status: Open
  • Priority: Normal
  • Assignee:
  • ruby -v: 2.2.5p319, 2.3.1p112, 2.4.0-preview2

* Backport: 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN

Hi,

I saw a bit strange behavior (at least for me) with the code below; an object given as an argument to a method with a default value and a keyword argument becomes Hash class if the object has 'to_hash' method with ruby >= 2.2, but it is not converted to Hash with ruby 2.1.
I expected the behavior of ruby 2.1.
Is this a bug or expected behavior of ruby >= 2.2?

I tested both on Linux x86_64 (CentOS 6) and Mac OS X 10.11.6.

class Test1
end

class Test2
   def to_hash
     {0 => [0, 1]}
   end
end

def argtest1 foo, bar: nil
   p foo.class
end

def argtest2 foo = nil, bar: nil
   p foo.class
end

test1 = Test1.new
test2 = Test2.new

argtest1(test1) # => Test1
argtest1(test2) # => Test2

argtest2(test1) # => Test1
argtest2(test2) # => Hash (2.2.5p319, 2.3.1p112, 2.4.0-preview2), Test2 (2.1.10p492)

Regards,
Hiroyuki Tanaka

Updated by naruse (Yui NARUSE) over 2 years ago

  • Backport deleted (2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN)

Updated by naruse (Yui NARUSE) over 2 years ago

  • Status changed from Open to Closed
#7

Updated by hsbt (Hiroshi SHIBATA) almost 2 years ago

Also available in: Atom PDF