Issue #14437 has been updated by nobu (Nobuyoshi Nakada).

Description updated

`==` and `!=` have never called `coerce`.
Only `+`, `-`, `<`, `>` and so on.

----------------------------------------
Bug #14437: Integer == doesn't work with coerce since 2.4 (and != since 1.9). Should it?
https://bugs.ruby-lang.org/issues/14437#change-70152

* Author: taw (Tomasz Wegrzanowski)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: 2.5.0
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
Here's extracted test sample:

~~~ruby
class Item
  def initialize(value)
    @value = value
  end

  def coerce(other)
    [Item.new(other), self]
  end

  def ==(other)
    Item.new("#{inspect} == #{other.inspect}")
  end

  def !=(other)
    Item.new("#{inspect} != #{other.inspect}")
  end

  def inspect
    "(#{@value})"
  end
end

a = Item.new("a")
p [RUBY_VERSION, 42 == a, 42 != a, a == 42, a == a, a != 42, a != a]
~~~

I'd expect it to print: `["2.x.x", ((a) == 42), ((a) != 42), ((a) == 42), ((a) == (a)), ((a) != 42), ((a) != (a))]`

What happens instead is:

~~~
["1.9.3", ((a) == 42), false, ((a) == 42), ((a) == (a)), ((a) != 42), ((a) != (a))]
["2.2.0", ((a) == 42), false, ((a) == 42), ((a) == (a)), ((a) != 42), ((a) != (a))]
["2.3.3", ((a) == 42), false, ((a) == 42), ((a) == (a)), ((a) != 42), ((a) != (a))]
["2.4.1", true, false, ((a) == 42), ((a) == (a)), ((a) != 42), ((a) != (a))]
["2.5.0", true, false, ((a) == 42), ((a) == (a)), ((a) != 42), ((a) != (a))]
~~~

So != never used coerce, and now == doesn't use coerce either.
Using Bignum value instead of 42 in this example breaks it even pre-2.4.

So, the question is:
* is using coerce like this not supported, and it was just an accident that it used to work? (and I should redefine Integer#== and Integer#!=)
* or is it meant to work, and it's a ruby bug?

For context, it's a problem for z3 gem, which builds big mathematical expressions like Z3.Int("a")+Z3.Int("b") == 4
and then uses Microsoft Z3 solver to solve them. Not being able to use == / != because of this issue would really reduce its usability.

Using coerce this way works just fine with +, -, *, >=, etc., it's just == and != which don't work.



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>