Project

General

Profile

Bug #16473

New deprecated warning disallows keyword arguments bypassing

Added by puchuu (Andrew Aladjev) 6 months ago. Updated 6 months ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
2.7.0
[ruby-core:96628]

Description

Hello. I see that ruby 2.7.0 prints unnecessary deprecated warning during arguments bypassing.

def kw(a: 1)
  puts "kw #{a}"
end

def non_kw(a = {}, *args)
  puts "non kw #{a}"
  kw *args
end

non_kw({ :a => 2 }, :a => 2)
non_kw({ :a => 3 })
non_kw

The right output is:

non kw {:a=>2}
kw 2
non kw {:a=>3}
kw 1
non kw {}
kw 1

Ruby 2.7.0 provides deprecated warning:

warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call

*args is bypassing arguments without any conversion. It looks like ruby converts last hash to keywords and than converts it back to hash. I think it is a bug.


Related issues

Related to Ruby master - Feature #16463: Fixing *args-delegation in Ruby 2.7: ruby2_keywords semantics by default in 2.7.1Closedmatz (Yukihiro Matsumoto)Actions
#1

Updated by puchuu (Andrew Aladjev) 6 months ago

  • Subject changed from New deprecated warning disallows arguments bypassing to New deprecated warning disallows keyword arguments bypassing

Updated by jeremyevans0 (Jeremy Evans) 6 months ago

  • Status changed from Open to Rejected

This behavior is expected. The positional hash argument is converted to keyword arguments when kw is called. That is not going to work in Ruby 3 (see #14183), hence the warning.

For delegating argument to a method that accepts keywords, you should probably use ruby2_keywords (if you also need to support older ruby versions):

ruby2_keywords :non_kw if respond_to?(:ruby2_keywords, true)

Updated by puchuu (Andrew Aladjev) 6 months ago

jeremyevans0 (Jeremy Evans), what will be the right way to bypass keyword arguments?

def non_kw(a = {}, **keyword_args)
  puts "non kw #{a}"
  kw **keyword_args
end

This variant is wrong with ruby 2, because it provides:

non kw {:a=>2}
kw 2
warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
warning: The called method `non_kw' is defined here
non kw {}
kw 3
non kw {}
kw 1

Will it work with ruby 3? Thank you.

Updated by jeremyevans0 (Jeremy Evans) 6 months ago

puchuu (Andrew Aladjev) wrote:

jeremyevans0 (Jeremy Evans), what will be the right way to bypass keyword arguments?

As mentioned earlier, you should probably use ruby2_keywords. In this particular case, even if you don't want to support earlier Ruby versions, because you don't want the positional hash argument being interpreted as keywords by non_kw.

Updated by Dan0042 (Daniel DeLorme) 6 months ago

In this particular case there would be a bug if *args had more than one element, so I think the cleaner fix would be

def non_kw(a = {}, b = {})
  puts "non kw #{a}"
  kw **b
end

I really think the ruby2_keywords workaround should be strictly reserved for cases where portability and generic delegation require it.

#6

Updated by Eregon (Benoit Daloze) 6 months ago

  • Related to Feature #16463: Fixing *args-delegation in Ruby 2.7: ruby2_keywords semantics by default in 2.7.1 added

Updated by Eregon (Benoit Daloze) 6 months ago

This is one clear case where #16463 would solve it intuitively.

Also available in: Atom PDF