定数をネストで参照しなかったので無限ループが発生した

以前、自作Gemでこんなコードを書いてたら、SystemStackErrorが発生しました。

module Exfuz
  class Queue
    def initialize
      @data = Queue.new
    end
  end
end

queue = Exfuz::Queue.new

4行目に代入するオブジェクトのクラスQueueThread::Queueのつもりで書いてました。QueueThread::Queueエイリアスなので。

実行すると、エラーが発生しました。エラーメッセージは以下が出ます。

initialize': stack level too deep (SystemStackError)
        from (irb):42:in `new'
        from (irb):42:in `initialize'
        from (irb):42:in `new'
        from (irb):42:in `initialize'
        from (irb):42:in `new'
        from (irb):42:in `initialize'
        from (irb):42:in `new'
        from (irb):42:in `initialize'
         ... 11381 levels...

原因は、ネストしたクラス内部で::演算子を使わず直接参照を用いたためです。Exfuz::Queue内部でのQueueExfuz::Queueとなります。そうなると初期化が繰り返され、SystemStackErrorが発生しました。

解決策としては、Thread::Queueで参照すること。もしくは、エイリアスQueueとして参照するなら左辺無しの::Queueで参照します。左辺無しの::はObjectクラスで定義された定数です。

参考文献

docs.ruby-lang.org