stack overflow on super
It looks like
super behavior is a bit different in 1.8 and 1.9. Please find the example below:
class Base def foo puts "bar" end end module Override def foo puts "override" super end end class A < Base end class B < A end B.send(:include, Override) A.send(:include, Override) B.new.foo ruby 1.8.7 (2009-06-12 patchlevel 174) [i486-linux] output: override override bar
and ruby 1.9.3dev (2010-05-26 trunk 28028) [i686-linux] output:
.... override override override override override super.rb:9: stack level too deep (SystemStackError)
Hope that helps.
- vm_insnhelper.c (vm_search_super_method): do not skip calling same methods in super. [Bug #3351]
- test/ruby/test_super.rb: fix a test.
#1 Updated by Marc-Andre Lafortune about 6 years ago
- Priority changed from Normal to 3
- Category set to core
I thought I had submitted that bug, actually, but seems I forgot!
Just to clarify: this happens when a module appears twice in the list of ancestors. Ruby typically forbids this, but if the module is included in just the right order, it is possible. In the example given, invert the two includes and Override is included only once.
#6 Updated by Shugo Maeda almost 4 years ago
- % Done changed from 0 to 100
- Status changed from Assigned to Closed
This issue was solved with changeset r36612.
Serge, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.
- insns.def (invokesuper): don't skip the same class. instead, use rb_method_entry_get_with_omod() to avoid infinite loop when super is used with refinements. [Bug #3351]
#10 [ruby-core:50857] Updated by Shugo Maeda over 3 years ago
- Assignee changed from Shugo Maeda to Yukihiro Matsumoto
mame (Yusuke Endoh) wrote:
Shugo-san, ko1, what's the status?
Override#foo is called only once, because in the SVN trunk, if a method found by super is the current method, it's skipped to avoid an infinite loop. The check was introduced for super in a refinement. Without it, super in a refinement causes an infinite loop.
Do you think this issue important?
I don't think so. Can I leave it as is, Matz?
#11 [ruby-core:50860] Updated by Anonymous over 3 years ago
#15 [ruby-core:69826] Updated by Koichi Sasada almost 1 year ago
Just now, we avoid this issue by putting
klass into each frame.
However, the workaround is remaining.
Now, ancestors is here:
[B, Override, A, Override, Base, Object, Kernel, BasicObject]
and now MRI calls
Override#foo only once. It skips second Override#foo.
However, if there is a
A#foo, then call
override A override bar
It is ugly workaround. So I want to remove such skipping.
Matz: Can I call
Override#foo twice even if it is duplicated with last call?