Project

General

Profile

Actions

Bug #12864

closed

Regression comparing Integer (Fixnum) to Comparable (2.4.0-preview2)

Added by timocp (Tim Peters) over 7 years ago. Updated over 7 years ago.

Status:
Closed
Assignee:
-
Target version:
-
[ruby-core:77713]

Description

If you have a class including Comparable and expecting to be compared to Integer, equality test doesn't work anymore. This worked in 2.3.1.

Example:

class MyInteger
  include Comparable
  
  def initialize(i)
    @i = i.to_i
  end
  attr_reader :i

  def <=>(other)
    @i <=> (other.is_a?(MyInteger) ? other.i : other)
  end
end

[5, 2**62, 2**61].each do |i|
  puts MyInteger.new(i) == i
  puts i == MyInteger.new(i)
end

Output in 2.3.1 and expected output:

true
true
true
true
true
true

Output in 2.4.0-preview2:

true
false
true
true
true
../test5.rb:16:in `==': invalid inspect_tbl pair_list for :== in #<Thread:0x000000014afaf0 run> (TypeError)
        from ../test5.rb:16:in `block in <main>'
        from ../test5.rb:14:in `each'
        from ../test5.rb:14:in `<main>'

As shown, if the MyInteger version is the left hand side of ==, the comparison works as expected.

If the Integer is on the left hand side, then the problem depends on its size:

  • If it is big enough that it is actually a Bignum (<= -(2**62-1) or >= 2**62) then it compares true as expected
  • If it is a smallish fixnum (between -(2**61) and 2**61-1) then it incorrectly compares false
  • For large fixnums not covered above (eg 2**61) the comparison raises a TypeError.

This does NOT affect other Comparable methods. Eg, less than/greater than. 3 < MyInteger.new(4) works, as long as coerce is defined. The examples above never try to call coerce.

A workaround is to define == on our class. If this is done the above tests all print true:

def MyInteger
  def ==(other)
    @i == (other.is_a?(MyInteger) ? other.i : other)
  end
end

However this shouldn't be necessary since Comparable is adding an equality method.

Using bisect, I am pretty sure this regression was introduced in r55891.

Actions #1

Updated by nobu (Nobuyoshi Nakada) over 7 years ago

  • Status changed from Open to Closed

Applied in changeset r56474.


numeric.c: fix up r55891

  • numeric.c (num_funcall1): check recursion by inverse pair, to
    fix fake infinite recursion. [ruby-core:77713] [Bug #12864]
Actions

Also available in: Atom PDF

Like0
Like0