ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:80748] [Ruby trunk Bug#13446] refinements with prepend for module has strange behavior
       [not found] <redmine.issue-13446.20170418011731@ruby-lang.org>
@ 2017-04-18  1:17 ` mtsmfm
  2017-06-16  2:28 ` [ruby-core:81696] [Ruby trunk Bug#13446][Assigned] " nobu
  2019-10-12 23:51 ` [ruby-core:95310] [Ruby master Bug#13446] " merch-redmine
  2 siblings, 0 replies; 3+ messages in thread
From: mtsmfm @ 2017-04-18  1:17 UTC (permalink / raw)
  To: ruby-core

Issue #13446 has been reported by mtsmfm (Fumiaki Matsushima).

----------------------------------------
Bug #13446: refinements with prepend for module has strange behavior
https://bugs.ruby-lang.org/issues/13446

* Author: mtsmfm (Fumiaki Matsushima)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]
* Backport: 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: UNKNOWN
----------------------------------------
~~~
using Module.new {
  refine Enumerable do
    alias :orig_sum :sum
  end
}

module Enumerable
  def sum(*args)
    orig_sum(*args)
  end
end

class GenericEnumerable
  include Enumerable

  def each
  end
end

# GenericEnumerable.new.sum # if we uncomment this line, `GenericEnumerable#sum` will work
Enumerable.prepend(Module.new) # if we comment out this line, `GenericEnumerable#sum` will work

p GenericEnumerable.new.sum # undefined method `orig_sum' for #<GenericEnumerable:0x0000000127c120 @values=[1, 2, 3]> (NoMethodError)
~~~

Is this intentional?



-- 
https://bugs.ruby-lang.org/

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

* [ruby-core:81696] [Ruby trunk Bug#13446][Assigned] refinements with prepend for module has strange behavior
       [not found] <redmine.issue-13446.20170418011731@ruby-lang.org>
  2017-04-18  1:17 ` [ruby-core:80748] [Ruby trunk Bug#13446] refinements with prepend for module has strange behavior mtsmfm
@ 2017-06-16  2:28 ` nobu
  2019-10-12 23:51 ` [ruby-core:95310] [Ruby master Bug#13446] " merch-redmine
  2 siblings, 0 replies; 3+ messages in thread
From: nobu @ 2017-06-16  2:28 UTC (permalink / raw)
  To: ruby-core

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

Description updated
Status changed from Open to Assigned
Assignee set to nobu (Nobuyoshi Nakada)

----------------------------------------
Bug #13446: refinements with prepend for module has strange behavior
https://bugs.ruby-lang.org/issues/13446#change-65384

* Author: mtsmfm (Fumiaki Matsushima)
* Status: Assigned
* Priority: Normal
* Assignee: nobu (Nobuyoshi Nakada)
* Target version: 
* ruby -v: ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]
* Backport: 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: UNKNOWN
----------------------------------------
~~~ruby
using Module.new {
  refine Enumerable do
    alias :orig_sum :sum
  end
}

module Enumerable
  def sum(*args)
    orig_sum(*args)
  end
end

class GenericEnumerable
  include Enumerable

  def each
  end
end

# GenericEnumerable.new.sum # if we uncomment this line, `GenericEnumerable#sum` will work
Enumerable.prepend(Module.new) # if we comment out this line, `GenericEnumerable#sum` will work

p GenericEnumerable.new.sum # undefined method `orig_sum' for #<GenericEnumerable:0x0000000127c120 @values=[1, 2, 3]> (NoMethodError)
~~~

Is this intentional?



-- 
https://bugs.ruby-lang.org/

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

* [ruby-core:95310] [Ruby master Bug#13446] refinements with prepend for module has strange behavior
       [not found] <redmine.issue-13446.20170418011731@ruby-lang.org>
  2017-04-18  1:17 ` [ruby-core:80748] [Ruby trunk Bug#13446] refinements with prepend for module has strange behavior mtsmfm
  2017-06-16  2:28 ` [ruby-core:81696] [Ruby trunk Bug#13446][Assigned] " nobu
@ 2019-10-12 23:51 ` merch-redmine
  2 siblings, 0 replies; 3+ messages in thread
From: merch-redmine @ 2019-10-12 23:51 UTC (permalink / raw)
  To: ruby-core

Issue #13446 has been updated by jeremyevans0 (Jeremy Evans).


Fixing this first requires fixing #16242, which allows including a module that uses prepend and is refined.  However, the fix for #16242 does not fix the example in this case, as this prepends the included module after the module is included.

The reason this is still broken after the fix for #16242 is that a refined module that hasn't been prepended to yet keeps the refined methods in the module's method table. When prepending, the module's method table is moved to the origin iclass, and then the refined methods are moved from the method table to a new method table in the module itself.

Unfortunately, that means that if a class has included the module, prepending breaks the refinements, because when the methods are moved from the origin iclass method table to the module method table, they are removed from the method table from the iclass created when the module was included earlier.

Fix this by always creating an origin iclass when including a module that has any refinements, even if the refinements are not currently used (see https://github.com/ruby/ruby/pull/2550). I wasn't sure the best way to do that. The approach I choose was to use an object flag. The flag is set on the module when Module#refine is called, and if the flag is present when the module is included in another module or class, an origin iclass is created for the module.

----------------------------------------
Bug #13446: refinements with prepend for module has strange behavior
https://bugs.ruby-lang.org/issues/13446#change-81993

* Author: mtsmfm (Fumiaki Matsushima)
* Status: Assigned
* Priority: Normal
* Assignee: nobu (Nobuyoshi Nakada)
* Target version: 
* ruby -v: ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]
* Backport: 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: UNKNOWN
----------------------------------------
~~~ruby
using Module.new {
  refine Enumerable do
    alias :orig_sum :sum
  end
}

module Enumerable
  def sum(*args)
    orig_sum(*args)
  end
end

class GenericEnumerable
  include Enumerable

  def each
  end
end

# GenericEnumerable.new.sum # if we uncomment this line, `GenericEnumerable#sum` will work
Enumerable.prepend(Module.new) # if we comment out this line, `GenericEnumerable#sum` will work

p GenericEnumerable.new.sum # undefined method `orig_sum' for #<GenericEnumerable:0x0000000127c120 @values=[1, 2, 3]> (NoMethodError)
~~~

Is this intentional?



-- 
https://bugs.ruby-lang.org/

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

end of thread, other threads:[~2019-10-12 23:52 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <redmine.issue-13446.20170418011731@ruby-lang.org>
2017-04-18  1:17 ` [ruby-core:80748] [Ruby trunk Bug#13446] refinements with prepend for module has strange behavior mtsmfm
2017-06-16  2:28 ` [ruby-core:81696] [Ruby trunk Bug#13446][Assigned] " nobu
2019-10-12 23:51 ` [ruby-core:95310] [Ruby master Bug#13446] " 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).