ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:117624] [Ruby master Bug#20440] `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class
@ 2024-04-20  9:01 ozydingo (Andrew Schwartz) via ruby-core
  2024-04-20  9:12 ` [ruby-core:117625] " ozydingo (Andrew Schwartz) via ruby-core
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: ozydingo (Andrew Schwartz) via ruby-core @ 2024-04-20  9:01 UTC (permalink / raw)
  To: ruby-core; +Cc: ozydingo (Andrew Schwartz)

Issue #20440 has been reported by ozydingo (Andrew Schwartz).

----------------------------------------
Bug #20440: `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class
https://bugs.ruby-lang.org/issues/20440

* Author: ozydingo (Andrew Schwartz)
* Status: Open
* ruby -v: 3.3.0
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
Apologies for the verbose title, but that's the specific set of conditions that AFAICT are required to reproduce the bug!

Here's the simplest setup I can reproduce:

```rb
class Base
  def foo(*args, x: 1)
    puts "Base: calling foo with args: #{args}, x: #{x}"
  end

  def foo!(x: 1)
    puts "Base: calling foo! with x: #{x}"
    foo(x: x)
  end
end

class Child < Base
  def foo(*)
    puts "Child: calling foo"
    super
  end
end
```

When I call `Child.new.foo!`, I expect it to call the base class method `foo!`, which will use the default keyword arg `x: 1`; then the child method `foo` with `x: 1`, and finally the base method `foo` with `x: 1`. However, this is not what I observe:

```rb
Child.new.foo!

Base: calling foo! with x: 1
Child: calling foo
Base: calling foo with args: [{:x=>1}], x: 1
```

So when the child `foo` method called `super`, it passed not only `x: 1` as a keyword arg, but *also* `{x: 1}` as a Hash positional arg to the super method.

This is breaking my upgrade to Ruby 3.0 as I have a similar setup but without the `*args` param, this I am getting the error "wrong number of arguments (given 1, expected 0)".



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-core:117625] [Ruby master Bug#20440] `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class
  2024-04-20  9:01 [ruby-core:117624] [Ruby master Bug#20440] `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class ozydingo (Andrew Schwartz) via ruby-core
@ 2024-04-20  9:12 ` ozydingo (Andrew Schwartz) via ruby-core
  2024-04-20  9:55 ` [ruby-core:117626] " nobu (Nobuyoshi Nakada) via ruby-core
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: ozydingo (Andrew Schwartz) via ruby-core @ 2024-04-20  9:12 UTC (permalink / raw)
  To: ruby-core; +Cc: ozydingo (Andrew Schwartz)

Issue #20440 has been updated by ozydingo (Andrew Schwartz).


In fact it seems we can simplify this to just calling `Child.new.foo(x: 1)`; no need for the base class `foo!` method.

Apologies if I'm misunderstanding `*` and `super`, but my understanding is `super` should be passing all args as they are to the super method, and `*` should accept any combination of args, is that correct?

```rb
Child.new.foo(x: 1)

Child: calling foo
Base: calling foo with args: [{:x=>1}], x: 1
```

----------------------------------------
Bug #20440: `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class
https://bugs.ruby-lang.org/issues/20440#change-108032

* Author: ozydingo (Andrew Schwartz)
* Status: Open
* ruby -v: 3.3.0
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
Apologies for the verbose title, but that's the specific set of conditions that AFAICT are required to reproduce the bug!

Here's the simplest setup I can reproduce:

```rb
class Base
  def foo(*args, x: 1)
    puts "Base: calling foo with args: #{args}, x: #{x}"
  end

  def foo!(x: 1)
    puts "Base: calling foo! with x: #{x}"
    foo(x: x)
  end
end

class Child < Base
  def foo(*)
    puts "Child: calling foo"
    super
  end
end
```

When I call `Child.new.foo!`, I expect it to call the base class method `foo!`, which will use the default keyword arg `x: 1`; then the child method `foo` with `x: 1`, and finally the base method `foo` with `x: 1`. However, this is not what I observe:

```rb
Child.new.foo!

Base: calling foo! with x: 1
Child: calling foo
Base: calling foo with args: [{:x=>1}], x: 1
```

So when the child `foo` method called `super`, it passed not only `x: 1` as a keyword arg, but *also* `{x: 1}` as a Hash positional arg to the super method.

This is breaking my upgrade to Ruby 3.0 as I have a similar setup but without the `*args` param, this I am getting the error "wrong number of arguments (given 1, expected 0)".



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-core:117626] [Ruby master Bug#20440] `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class
  2024-04-20  9:01 [ruby-core:117624] [Ruby master Bug#20440] `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class ozydingo (Andrew Schwartz) via ruby-core
  2024-04-20  9:12 ` [ruby-core:117625] " ozydingo (Andrew Schwartz) via ruby-core
@ 2024-04-20  9:55 ` nobu (Nobuyoshi Nakada) via ruby-core
  2024-04-20 11:04 ` [ruby-core:117627] " Eregon (Benoit Daloze) via ruby-core
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: nobu (Nobuyoshi Nakada) via ruby-core @ 2024-04-20  9:55 UTC (permalink / raw)
  To: ruby-core; +Cc: nobu (Nobuyoshi Nakada)

Issue #20440 has been updated by nobu (Nobuyoshi Nakada).


You need to make `foo` `ruby2_keywords` to let it work as same as 2.7 or earlier.

```rb
class Child < Base
  ruby2_keywords def foo(*)
    puts "Child: calling foo"
    super
  end
end
Child.new.foo!
```
```
Base: calling foo! with x: 1
Child: calling foo
Base: calling foo with args: [], x: 1
```

Note that `require 'ruby2_keyword'` is necessary before ruby 2.7.

----------------------------------------
Bug #20440: `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class
https://bugs.ruby-lang.org/issues/20440#change-108033

* Author: ozydingo (Andrew Schwartz)
* Status: Open
* ruby -v: 3.3.0
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
Apologies for the verbose title, but that's the specific set of conditions that AFAICT are required to reproduce the bug!

Here's the simplest setup I can reproduce:

```rb
class Base
  def foo(*args, x: 1)
    puts "Base: calling foo with args: #{args}, x: #{x}"
  end

  def foo!(x: 1)
    puts "Base: calling foo! with x: #{x}"
    foo(x: x)
  end
end

class Child < Base
  def foo(*)
    puts "Child: calling foo"
    super
  end
end
```

When I call `Child.new.foo!`, I expect it to call the base class method `foo!`, which will use the default keyword arg `x: 1`; then the child method `foo` with `x: 1`, and finally the base method `foo` with `x: 1`. However, this is not what I observe:

```rb
Child.new.foo!

Base: calling foo! with x: 1
Child: calling foo
Base: calling foo with args: [{:x=>1}], x: 1
```

So when the child `foo` method called `super`, it passed not only `x: 1` as a keyword arg, but *also* `{x: 1}` as a Hash positional arg to the super method.

This is breaking my upgrade to Ruby 3.0 as I have a similar setup but without the `*args` param, this I am getting the error "wrong number of arguments (given 1, expected 0)".



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-core:117627] [Ruby master Bug#20440] `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class
  2024-04-20  9:01 [ruby-core:117624] [Ruby master Bug#20440] `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class ozydingo (Andrew Schwartz) via ruby-core
  2024-04-20  9:12 ` [ruby-core:117625] " ozydingo (Andrew Schwartz) via ruby-core
  2024-04-20  9:55 ` [ruby-core:117626] " nobu (Nobuyoshi Nakada) via ruby-core
@ 2024-04-20 11:04 ` Eregon (Benoit Daloze) via ruby-core
  2024-04-21  7:02 ` [ruby-core:117628] " ozydingo (Andrew Schwartz) via ruby-core
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Eregon (Benoit Daloze) via ruby-core @ 2024-04-20 11:04 UTC (permalink / raw)
  To: ruby-core; +Cc: Eregon (Benoit Daloze)

Issue #20440 has been updated by Eregon (Benoit Daloze).


See https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/
it also explains `(*, **)` and `(...)` which are better if you don't need compatibility with Ruby < 2.7.

----------------------------------------
Bug #20440: `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class
https://bugs.ruby-lang.org/issues/20440#change-108034

* Author: ozydingo (Andrew Schwartz)
* Status: Open
* ruby -v: 3.3.0
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
Apologies for the verbose title, but that's the specific set of conditions that AFAICT are required to reproduce the bug!

Here's the simplest setup I can reproduce:

```rb
class Base
  def foo(*args, x: 1)
    puts "Base: calling foo with args: #{args}, x: #{x}"
  end

  def foo!(x: 1)
    puts "Base: calling foo! with x: #{x}"
    foo(x: x)
  end
end

class Child < Base
  def foo(*)
    puts "Child: calling foo"
    super
  end
end
```

When I call `Child.new.foo!`, I expect it to call the base class method `foo!`, which will use the default keyword arg `x: 1`; then the child method `foo` with `x: 1`, and finally the base method `foo` with `x: 1`. However, this is not what I observe:

```rb
Child.new.foo!

Base: calling foo! with x: 1
Child: calling foo
Base: calling foo with args: [{:x=>1}], x: 1
```

So when the child `foo` method called `super`, it passed not only `x: 1` as a keyword arg, but *also* `{x: 1}` as a Hash positional arg to the super method.

This is breaking my upgrade to Ruby 3.0 as I have a similar setup but without the `*args` param, this I am getting the error "wrong number of arguments (given 1, expected 0)".



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-core:117628] [Ruby master Bug#20440] `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class
  2024-04-20  9:01 [ruby-core:117624] [Ruby master Bug#20440] `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class ozydingo (Andrew Schwartz) via ruby-core
                   ` (2 preceding siblings ...)
  2024-04-20 11:04 ` [ruby-core:117627] " Eregon (Benoit Daloze) via ruby-core
@ 2024-04-21  7:02 ` ozydingo (Andrew Schwartz) via ruby-core
  2024-04-21  7:44 ` [ruby-core:117629] [Ruby master Bug#20440] `super` from child class duplicating a keyword argument as a positional Hash zverok (Victor Shepelev) via ruby-core
  2024-04-21  8:16 ` [ruby-core:117630] " ozydingo (Andrew Schwartz) via ruby-core
  5 siblings, 0 replies; 7+ messages in thread
From: ozydingo (Andrew Schwartz) via ruby-core @ 2024-04-21  7:02 UTC (permalink / raw)
  To: ruby-core; +Cc: ozydingo (Andrew Schwartz)

Issue #20440 has been updated by ozydingo (Andrew Schwartz).


Thanks both. I understand that Ruby 3 requires explicit handling of keyword arguments. What still seems off to me is that `super` is _modifying_ the arguments. The child method is being passed a keyword argument, and `super` is forwarding keywords arguments *and* a Hash positional argument. Should it not be the case that either the method defined with only `*` does not accept keyword arguments or that `super` preserves the form of the arguments that were passed?

----------------------------------------
Bug #20440: `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class
https://bugs.ruby-lang.org/issues/20440#change-108036

* Author: ozydingo (Andrew Schwartz)
* Status: Closed
* ruby -v: 3.3.0
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
Apologies for the verbose title, but that's the specific set of conditions that AFAICT are required to reproduce the bug!

Here's the simplest setup I can reproduce:

```rb
class Base
  def foo(*args, x: 1)
    puts "Base: calling foo with args: #{args}, x: #{x}"
  end

  def foo!(x: 1)
    puts "Base: calling foo! with x: #{x}"
    foo(x: x)
  end
end

class Child < Base
  def foo(*)
    puts "Child: calling foo"
    super
  end
end
```

When I call `Child.new.foo!`, I expect it to call the base class method `foo!`, which will use the default keyword arg `x: 1`; then the child method `foo` with `x: 1`, and finally the base method `foo` with `x: 1`. However, this is not what I observe:

```rb
Child.new.foo!

Base: calling foo! with x: 1
Child: calling foo
Base: calling foo with args: [{:x=>1}], x: 1
```

So when the child `foo` method called `super`, it passed not only `x: 1` as a keyword arg, but *also* `{x: 1}` as a Hash positional arg to the super method.

This is breaking my upgrade to Ruby 3.0 as I have a similar setup but without the `*args` param, this I am getting the error "wrong number of arguments (given 1, expected 0)".



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-core:117629] [Ruby master Bug#20440] `super` from child class duplicating a keyword argument as a positional Hash
  2024-04-20  9:01 [ruby-core:117624] [Ruby master Bug#20440] `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class ozydingo (Andrew Schwartz) via ruby-core
                   ` (3 preceding siblings ...)
  2024-04-21  7:02 ` [ruby-core:117628] " ozydingo (Andrew Schwartz) via ruby-core
@ 2024-04-21  7:44 ` zverok (Victor Shepelev) via ruby-core
  2024-04-21  8:16 ` [ruby-core:117630] " ozydingo (Andrew Schwartz) via ruby-core
  5 siblings, 0 replies; 7+ messages in thread
From: zverok (Victor Shepelev) via ruby-core @ 2024-04-21  7:44 UTC (permalink / raw)
  To: ruby-core; +Cc: zverok (Victor Shepelev)

Issue #20440 has been updated by zverok (Victor Shepelev).


> What still seems off to me is that super is modifying the arguments.

If I understand correctly, what “modifies” the argument is child’s `foo` signature:
```ruby
def foo(*) # <= this says “accept only positional args” (implicitly converting keyword ones to hash)
  super # <= this implicitly has a signature same as foo: super(*), passing only positional ones to the parent
end
```

The way to “fix” the code (if you own it) is this:
```ruby
class Child < Base
  def foo(*, **) # the declaration that leaves keyword ones and positional ones separated
    puts "Child: calling foo"
    super # super is implicitly called as super(*, **), passing them separately
  end
end
```
The printed output:
```
Base: calling foo! with x: 1
Child: calling foo
Base: calling foo with args: [], x: 1
```

----------------------------------------
Bug #20440: `super` from child class duplicating a keyword argument as a positional Hash
https://bugs.ruby-lang.org/issues/20440#change-108038

* Author: ozydingo (Andrew Schwartz)
* Status: Closed
* ruby -v: 3.3.0
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
Apologies for the verbose title, but that's the specific set of conditions that AFAICT are required to reproduce the bug!

Here's the simplest setup I can reproduce:

```rb
class Base
  def foo(*args, x: 1)
    puts "Base: calling foo with args: #{args}, x: #{x}"
  end

  def foo!(x: 1)
    puts "Base: calling foo! with x: #{x}"
    foo(x: x)
  end
end

class Child < Base
  def foo(*)
    puts "Child: calling foo"
    super
  end
end
```

When I call `Child.new.foo!`, I expect it to call the base class method `foo!`, which will use the default keyword arg `x: 1`; then the child method `foo` with `x: 1`, and finally the base method `foo` with `x: 1`. However, this is not what I observe:

```rb
Child.new.foo!

Base: calling foo! with x: 1
Child: calling foo
Base: calling foo with args: [{:x=>1}], x: 1
```

So when the child `foo` method called `super`, it passed not only `x: 1` as a keyword arg, but *also* `{x: 1}` as a Hash positional arg to the super method.

This is breaking my upgrade to Ruby 3.0 as I have a similar setup but without the `*args` param, this I am getting the error "wrong number of arguments (given 1, expected 0)".



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-core:117630] [Ruby master Bug#20440] `super` from child class duplicating a keyword argument as a positional Hash
  2024-04-20  9:01 [ruby-core:117624] [Ruby master Bug#20440] `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class ozydingo (Andrew Schwartz) via ruby-core
                   ` (4 preceding siblings ...)
  2024-04-21  7:44 ` [ruby-core:117629] [Ruby master Bug#20440] `super` from child class duplicating a keyword argument as a positional Hash zverok (Victor Shepelev) via ruby-core
@ 2024-04-21  8:16 ` ozydingo (Andrew Schwartz) via ruby-core
  5 siblings, 0 replies; 7+ messages in thread
From: ozydingo (Andrew Schwartz) via ruby-core @ 2024-04-21  8:16 UTC (permalink / raw)
  To: ruby-core; +Cc: ozydingo (Andrew Schwartz)

Issue #20440 has been updated by ozydingo (Andrew Schwartz).


Ok I see it now; `super` isn't passing the args as both forms, it's passing _only_ as a positional Hash. The `x: 1` is coming from my default kwarg, which I was blinded to as I attempted to reduce the example to a general form. Thanks all!

----------------------------------------
Bug #20440: `super` from child class duplicating a keyword argument as a positional Hash
https://bugs.ruby-lang.org/issues/20440#change-108039

* Author: ozydingo (Andrew Schwartz)
* Status: Closed
* ruby -v: 3.3.0
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
Apologies for the verbose title, but that's the specific set of conditions that AFAICT are required to reproduce the bug!

Here's the simplest setup I can reproduce:

```rb
class Base
  def foo(*args, x: 1)
    puts "Base: calling foo with args: #{args}, x: #{x}"
  end

  def foo!(x: 1)
    puts "Base: calling foo! with x: #{x}"
    foo(x: x)
  end
end

class Child < Base
  def foo(*)
    puts "Child: calling foo"
    super
  end
end
```

When I call `Child.new.foo!`, I expect it to call the base class method `foo!`, which will use the default keyword arg `x: 1`; then the child method `foo` with `x: 1`, and finally the base method `foo` with `x: 1`. However, this is not what I observe:

```rb
Child.new.foo!

Base: calling foo! with x: 1
Child: calling foo
Base: calling foo with args: [{:x=>1}], x: 1
```

So when the child `foo` method called `super`, it passed not only `x: 1` as a keyword arg, but *also* `{x: 1}` as a Hash positional arg to the super method.

This is breaking my upgrade to Ruby 3.0 as I have a similar setup but without the `*args` param, this I am getting the error "wrong number of arguments (given 1, expected 0)".



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-04-21  8:16 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-20  9:01 [ruby-core:117624] [Ruby master Bug#20440] `super` from child class passing keyword arg as Hash if in a method with passthrough args called from base class ozydingo (Andrew Schwartz) via ruby-core
2024-04-20  9:12 ` [ruby-core:117625] " ozydingo (Andrew Schwartz) via ruby-core
2024-04-20  9:55 ` [ruby-core:117626] " nobu (Nobuyoshi Nakada) via ruby-core
2024-04-20 11:04 ` [ruby-core:117627] " Eregon (Benoit Daloze) via ruby-core
2024-04-21  7:02 ` [ruby-core:117628] " ozydingo (Andrew Schwartz) via ruby-core
2024-04-21  7:44 ` [ruby-core:117629] [Ruby master Bug#20440] `super` from child class duplicating a keyword argument as a positional Hash zverok (Victor Shepelev) via ruby-core
2024-04-21  8:16 ` [ruby-core:117630] " ozydingo (Andrew Schwartz) via ruby-core

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).