ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:101618] [Ruby master Bug#17423] `Prepend` should prepend a module before the class
@ 2020-12-22  1:56 matz
  2020-12-22  2:33 ` [ruby-core:101620] " merch-redmine
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: matz @ 2020-12-22  1:56 UTC (permalink / raw)
  To: ruby-core

Issue #17423 has been reported by matz (Yukihiro Matsumoto).

----------------------------------------
Bug #17423: `Prepend` should prepend a module before the class
https://bugs.ruby-lang.org/issues/17423

* 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: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

end of thread, other threads:[~2021-01-14 20:48 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [ruby-core:102097] " merch-redmine

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).