* [ruby-core:101620] [Ruby master Bug#17423] `Prepend` should prepend a module before the class
2020-12-22 1:56 [ruby-core:101618] [Ruby master Bug#17423] `Prepend` should prepend a module before the class matz
@ 2020-12-22 2:33 ` merch-redmine
2020-12-24 6:02 ` [ruby-core:101672] " matz
2021-01-14 20:48 ` [ruby-core:102097] " merch-redmine
2 siblings, 0 replies; 4+ messages in thread
From: merch-redmine @ 2020-12-22 2:33 UTC (permalink / raw)
To: ruby-core
Issue #17423 has been updated by jeremyevans0 (Jeremy Evans).
This stems from the change that `Module#prepend` (and `Module#include`) now affect classes already including the receiver. You get the same behavior for Ruby 2.0-3.0 if you prepend M to A before including A in B:
```ruby
module M; end
module A; end
A.prepend M
class B; include A; end
B.prepend M
p B.ancestors
```
The difference for your original code is shown by B.ancestors before and after the prepend of M:
```ruby
module M; end
module A; end
class B; include A; end
A.send :prepend, M
p B.ancestors
B.send :prepend, M
p B.ancestors
```
Output:
```
$ ruby30 t1.rb
[B, M, A, Object, Kernel, BasicObject]
[B, M, A, Object, Kernel, BasicObject]
$ ruby27 t1.rb
[B, A, Object, Kernel, BasicObject]
[M, B, A, Object, Kernel, BasicObject]
```
Ruby has never had `include` add a module to the ancestor chain if it already exists in the ancestor chain of the receiver, and has never had `prepend` add a module to the ancestor chain if it already exists in the ancestor chain before the superclass. Prior to Ruby 2.3, Ruby wouldn't prepend the module if it was anywhere in the ancestor chain.
I'm not opposed to allow `prepend` to ignore the existing ancestor chain and always prepend the module to it. However, it seems to be a very risky change to make at the current time. Maybe we can try after the release of 3.0?
----------------------------------------
Bug #17423: `Prepend` should prepend a module before the class
https://bugs.ruby-lang.org/issues/17423#change-89409
* Author: matz (Yukihiro Matsumoto)
* Status: Open
* Priority: Normal
* Assignee: jeremyevans0 (Jeremy Evans)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
I see
```ruby
module M; end
module A; end
class B; include A; end
A.prepend M
B.prepend M
p B.ancestors
```
gives `[B, M, A, Object, Kernel, BasicObject]` now. It used to be `[M, B, A, Object, Kernel, BasicObject]`.
I think it should be prepended to class `B`. Probably it should be `[M, B, M, A, Object, Kernel, BasicObject]`.
The reason behind this change may be duplication removing, but considering the following code, it is OK to duplicate prepende modules.
```ruby
module M; end
class A; end
class B<A; end
A.prepend M
B.prepend M
p B.ancestors # => [M, B, M, A, Object, Kernel, BasicObject]
```
Am I missing something?
Matz.
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 4+ messages in thread
* [ruby-core:101672] [Ruby master Bug#17423] `Prepend` should prepend a module before the class
2020-12-22 1:56 [ruby-core:101618] [Ruby master Bug#17423] `Prepend` should prepend a module before the class matz
2020-12-22 2:33 ` [ruby-core:101620] " merch-redmine
@ 2020-12-24 6:02 ` matz
2021-01-14 20:48 ` [ruby-core:102097] " merch-redmine
2 siblings, 0 replies; 4+ messages in thread
From: matz @ 2020-12-24 6:02 UTC (permalink / raw)
To: ruby-core
Issue #17423 has been updated by matz (Yukihiro Matsumoto).
This is a serious breakage, in fact, breaks Rails. So I believe we need to change this soon. But:
* We need more time to investigate
* We don't have much time before the release
* Rails made a patch to address this issue
Thus fix this after the 3.0 release.
Matz.
----------------------------------------
Bug #17423: `Prepend` should prepend a module before the class
https://bugs.ruby-lang.org/issues/17423#change-89493
* Author: matz (Yukihiro Matsumoto)
* Status: Open
* Priority: Normal
* Assignee: jeremyevans0 (Jeremy Evans)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
I see
```ruby
module M; end
module A; end
class B; include A; end
A.prepend M
B.prepend M
p B.ancestors
```
gives `[B, M, A, Object, Kernel, BasicObject]` now. It used to be `[M, B, A, Object, Kernel, BasicObject]`.
I think it should be prepended to class `B`. Probably it should be `[M, B, M, A, Object, Kernel, BasicObject]`.
The reason behind this change may be duplication removing, but considering the following code, it is OK to duplicate prepende modules.
```ruby
module M; end
class A; end
class B<A; end
A.prepend M
B.prepend M
p B.ancestors # => [M, B, M, A, Object, Kernel, BasicObject]
```
Am I missing something?
Matz.
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 4+ messages in thread
* [ruby-core:102097] [Ruby master Bug#17423] `Prepend` should prepend a module before the class
2020-12-22 1:56 [ruby-core:101618] [Ruby master Bug#17423] `Prepend` should prepend a module before the class matz
2020-12-22 2:33 ` [ruby-core:101620] " merch-redmine
2020-12-24 6:02 ` [ruby-core:101672] " matz
@ 2021-01-14 20:48 ` merch-redmine
2 siblings, 0 replies; 4+ messages in thread
From: merch-redmine @ 2021-01-14 20:48 UTC (permalink / raw)
To: ruby-core
Issue #17423 has been updated by jeremyevans0 (Jeremy Evans).
Based on the decision made at the developer meeting (https://github.com/ruby/dev-meeting-log/blob/master/DevelopersMeeting20210113Japan.md#bug-17423-prepend-should-prepend-a-module-before-the-class-jeremyevans0), I've added a pull request that will make Module#prepend insert a module in the ancestor chain even if the receiver already includes the module: https://github.com/ruby/ruby/pull/4072
----------------------------------------
Bug #17423: `Prepend` should prepend a module before the class
https://bugs.ruby-lang.org/issues/17423#change-89954
* Author: matz (Yukihiro Matsumoto)
* Status: Open
* Priority: Normal
* Assignee: jeremyevans0 (Jeremy Evans)
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
I see
```ruby
module M; end
module A; end
class B; include A; end
A.prepend M
B.prepend M
p B.ancestors
```
gives `[B, M, A, Object, Kernel, BasicObject]` now. It used to be `[M, B, A, Object, Kernel, BasicObject]`.
I think it should be prepended to class `B`. Probably it should be `[M, B, M, A, Object, Kernel, BasicObject]`.
The reason behind this change may be duplication removing, but considering the following code, it is OK to duplicate prepende modules.
```ruby
module M; end
class A; end
class B<A; end
A.prepend M
B.prepend M
p B.ancestors # => [M, B, M, A, Object, Kernel, BasicObject]
```
Am I missing something?
Matz.
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 4+ messages in thread