Project

General

Profile

Bug #15877

Incorrect constant lookup result in method on cloned class

Added by danielwaterworth (Daniel Waterworth) 7 months ago. Updated 4 months ago.

Status:
Closed
Priority:
Normal
Target version:
-
[ruby-core:92849]

Description

This behavior seems wrong to me:

class Foo
  def test
    TEST
  end
end

Bar1 = Foo.clone
Bar2 = Foo.clone

class Bar1
  TEST = 'bar-1'
end

class Bar2
  TEST = 'bar-2'
end

# If these two lines are reordered, 'bar-2' is produced each time
p [:bar1_method, Bar1.new.test] # outputs 'bar-1' (correct)
p [:bar2_method, Bar2.new.test] # outputs 'bar-1' (incorrect)

p [:bar1_const, Bar1::TEST] # outputs 'bar-1' (correct)
p [:bar2_const, Bar2::TEST] # outputs 'bar-2' (correct)

Possibly related to #9603, #7107

Associated revisions

Revision b004d3e8
Added by ko1 (Koichi Sasada) 4 months ago

solve "duplicate :raise event" [Bug #15877]

Without this patch, "raise" event invoked twice when raise an
exception in "load"ed script.
This patch by danielwaterworth (Daniel Waterworth).
[Bug #15877]

Revision 76bd0714
Added by nobu (Nobuyoshi Nakada) 4 months ago

solve "duplicate :raise event" in require too [Bug #15877]

Revision 71efad1e
Added by ko1 (Koichi Sasada) 4 months ago

introduce RCLASS_CLONED flag for inline cache.

Methods on duplicated class/module refer same constant inline
cache (IC). Constant access lookup should be done for cloned
class/modules but inline cache doesn't check it.
To check it, this patch introduce new RCLASS_CLONED flag which
are set when if class/module is cloned (both orig and dst).
[Bug #15877]

History

Updated by danielwaterworth (Daniel Waterworth) 7 months ago

Running with RubyVM::InstructionSequence.compile_option = {inline_const_cache: false} produces the correct result.

#2

Updated by danielwaterworth (Daniel Waterworth) 7 months ago

  • Description updated (diff)

Updated by sag (Stephen Gregory) 7 months ago

I tested this on 2.5, 2.4 and the behavior is the same there. Also this applies to subclasses as well. The first class READ determines the values for all of them.

class Unrelated
    TEST='UNRELATED'
    def test
      TEST
    end
end

class Foo
  def test
     TEST
   end
end

Bar2 = Foo.clone
Bar1 = Foo.clone


class Bar1
  TEST = 'bar-1'
end
class Bar2
  TEST = 'bar-2'
end
class Bar3 < Foo
  TEST = 'bar-3'
end

puts "Bar2 #{Bar2.new.test}"  # Bar2 bar-2
puts "Bar1 #{Bar1.new.test}"   # Bar1 bar-2
puts "Bar3 #{Bar3.new.test}"  # Bar3 bar-2
puts "Foo #{Foo.new.test}"     # Foo bar-2
puts "Unrelated #{Unrelated.new.test}"  #Unrelated UNRELATED

Interestingly if Bar3 is read first then you get:

sample/array_second.rb:12:in `test': uninitialized constant Foo::TEST (NameError)
    from sample/array_second.rb:30:in `<main>'

Updated by ko1 (Koichi Sasada) 5 months ago

  • Assignee set to ko1 (Koichi Sasada)
  • Status changed from Open to Assigned

oops!

#5

Updated by ko1 (Koichi Sasada) 4 months ago

  • Status changed from Assigned to Closed

Applied in changeset git|b004d3e8300ba803d4a499148fa4fc6a690149e6.


solve "duplicate :raise event" [Bug #15877]

Without this patch, "raise" event invoked twice when raise an
exception in "load"ed script.
This patch by danielwaterworth (Daniel Waterworth).
[Bug #15877]

Updated by nagachika (Tomoyuki Chikanaga) 4 months ago

  • Backport changed from 2.4: UNKNOWN, 2.5: UNKNOWN, 2.6: UNKNOWN to 2.4: UNKNOWN, 2.5: UNKNOWN, 2.6: REQUIRED
  • Status changed from Closed to Assigned

Re-open. This ticket has been closed accidentally by b004d3e8.
I'll correct commit link.

#7

Updated by nobu (Nobuyoshi Nakada) 4 months ago

  • Status changed from Assigned to Closed

Applied in changeset git|76bd0714cf1140ffd64bf564446c76c54f2c4870.


solve "duplicate :raise event" in require too [Bug #15877]

Updated by nobu (Nobuyoshi Nakada) 4 months ago

  • Status changed from Closed to Open

I copied the wrong commit log, sorry.

#9

Updated by ko1 (Koichi Sasada) 4 months ago

  • Status changed from Open to Closed

Applied in changeset git|71efad1ed391ee0c5398a76306fdbaaadd4dc52e.


introduce RCLASS_CLONED flag for inline cache.

Methods on duplicated class/module refer same constant inline
cache (IC). Constant access lookup should be done for cloned
class/modules but inline cache doesn't check it.
To check it, this patch introduce new RCLASS_CLONED flag which
are set when if class/module is cloned (both orig and dst).
[Bug #15877]

Updated by ko1 (Koichi Sasada) 4 months ago

solve "duplicate :raise event" [Bug #15877]

sorry my mistake :p

Also available in: Atom PDF