Bug #2402

super in instance_eval

Added by shugo (Shugo Maeda) over 2 years ago. Updated 11 months ago.

[ruby-dev:39772]
Status:Assigned Start date:11/25/2009
Priority:Normal Due date:
Assignee:ko1 (Koichi Sasada) % Done:

0%

Category:-
Target version:2.0.0
ruby -v:ruby 1.9.2dev (2009-11-24 trunk 25909) [i686-linux]

Description

instance_evalのブロック内でsuperを呼ぶと、instance_evalで変更された
selfに対してsuperの呼び出しを行ってしまうようです。

defiant:build$ cat t.rb
class Foo
  def foo
    p self
  end
end

class Bar < Foo
  def foo
    x = Object.new
    x.instance_eval do
      super
    end
  end
end

Bar.new.foo
defiant:build$ ./ruby-trunk.1124 -v t.rb
ruby 1.9.2dev (2009-11-24 trunk 25909) [i686-linux]
#<Object:0x8590f6c>

Foo#fooが呼ばれるのにselfがObjectという、ちょっとおかしなことになっています。
ちょっと自信がありませんが、一応パッチを添付します。

super_in_instance_eval_fix.diff (2 kB) shugo (Shugo Maeda), 11/25/2009 05:55 pm


Related issues

related to ruby-trunk - Bug #3136: reuse of singleton method definition causes SEGV Closed 04/12/2010

Associated revisions

Revision 28043
Added by mame (Yusuke Endoh) almost 2 years ago

* insns.def (invokesuper): check consistency between class of self and class of method being invoked by super. This is temporary measure for YARV. See [ruby-core:30313] in detail. See [ruby-dev:40959] [ruby-dev:39772] [ruby-core:27000] [ruby-core:27230] * vm_insnhelper.c (vm_search_superclass): ditto.

History

Updated by shugo (Shugo Maeda) over 2 years ago

特異クラス定義でsuperした時はNoMethodErrorになるようです。

defiant:build$ cat t2.rb  
class Foo
  def foo
    p self
  end
end

class Bar < Foo
  def foo
    x = Object.new
    class << x
      super
    end
  end
end

Bar.new.foo
defiant:build$ ./ruby-trunk.1124 -v t2.rb 
ruby 1.9.2dev (2009-11-24 trunk 25909) [i686-linux]
t2.rb:11:in `singletonclass': super called outside of method (NoMethodError)
	from t2.rb:10:in `foo'
	from t2.rb:16:in `<main>'

1.8ではFoo#fooが呼ばれます。

defiant:build$ ruby-1_8 -v t2.rb         
ruby 1.8.8dev (2009-10-22 revision 25430) [i686-linux]
#<Bar:0xb7ea443c>

参考までに他の処理系では以下のような挙動でした。

defiant:build$ ir -v t2.rb
IronRuby 0.9.1.0 on .NET 2.0.0.0
#<Bar:0x0000056>
defiant:build$ jruby -v t2.rb
jruby 1.5.0.dev (ruby 1.8.7 patchlevel 174) (2009-11-12 421150b) (Java HotSpot(TM) Client VM 1.6.0_16) [i386-java]
#<Class:#<Object:0x180cf2a>>
defiant:build$ rbx -v t2.rb
rubinius 0.13.0-dev (1.8.7 e614007b 2009-11-06) [i686-pc-linux-gnu]
An exception occurred running t2.rb
    No method 'bytecode' on an instance of NilClass. (NoMethodError)

それぞれ個性があって面白いですね。

個人的には例外でもいいんじゃないかなと思いますが、1.9のinstance_evalでの
superや、JRubyの特異クラス定義でのsuperのように、変なレシーバでsuperが
呼ばれてしまうのはまずいんじゃないかと思います。

Updated by ujihisa (ujihisa .) over 2 years ago

  • Status changed from Open to Assigned
  • Assignee set to matz (Yukihiro Matsumoto)

Updated by mame (Yusuke Endoh) about 2 years ago

  • Assignee changed from matz (Yukihiro Matsumoto) to ko1 (Koichi Sasada)
遠藤です。

> instance_evalのブロック内でsuperを呼ぶと、instance_evalで変更された
> selfに対してsuperの呼び出しを行ってしまうようです。

再現しました。以下で SEGV することも確認しました。

  class MyArray < Array
    def reverse
      "foo".instance_eval do
        super
      end
    end
  end
  MyArray.new([1,2,3]).reverse

パッチも見ました。速度劣化は気になりますが、正しいと思います。


vm_search_superclass を追ってみたところ、recv が必要になるのは、
現在のコンテキストが include された module に所属するメソッドの
場合 (ICLASS) だけのようですので、その時まで recv の同定を遅延
させると、速度劣化も気にならなくなるかもと思います。

ただ、その辺の修正は [ruby-dev:40959] の修正の後にやったほうが
いい予感がするので、最適化は後にして、とりあえずこの問題は前田
さんのパッチで close するのがいいと思います。

-- 
Yusuke Endoh <mame@tsg.ne.jp>

Updated by ko1 (Koichi Sasada) about 2 years ago

パッチは全然見てないのですが,遠藤さんが良いと仰ってるので良いのではないかと思います.

Updated by mame (Yusuke Endoh) almost 2 years ago

  • Target version set to 2.0.0
遠藤です。

[Bug #2502] [Bug #3136] あたりで super の修正は後回しにしようということに
なり、r28043 でとりあえずの対策をしたので、1.9.x にします。

-- 
Yusuke Endoh <mame@tsg.ne.jp>

Updated by nahi (Hiroshi Nakamura) 11 months ago

  • Target version changed from 2.0.0 to 1.9.3

Updated by ko1 (Koichi Sasada) 11 months ago

  • Target version changed from 1.9.3 to 2.0.0
すみません,1.9.4 送りで....

Also available in: Atom PDF