[ruby-core:125572] [Ruby Bug#22080] `Integer(obj, exception: false)` raises when `to_str` doesn't return String
Issue #22080 has been reported by Earlopain (Earlopain _). ---------------------------------------- Bug #22080: `Integer(obj, exception: false)` raises when `to_str` doesn't return String https://bugs.ruby-lang.org/issues/22080 * Author: Earlopain (Earlopain _) * Status: Open * ruby -v: ruby 4.1.0dev (2026-05-23T13:04:55Z master 6c6df00bbc) +PRISM [x86_64-linux] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- ```rb obj = Object.new def obj.to_str = 1 Integer(obj, exception: false) # can't convert Object to String (Object#to_str gives Integer) (TypeError) ``` But returning the wrong type from `to_int` is fine: ```rb obj = Object.new def obj.to_int = "1" Integer(obj, exception: false) # nil ``` Doc says this (https://docs.ruby-lang.org/en/master/Kernel.html#method-i-Integer):
With exception given as false, an exception of any kind is suppressed and nil is returned.
So it looks like it should not raise in both cases. Or more specifically, try `to_i` next, since that is what happens when `to_int` returns the wrong type. -- https://bugs.ruby-lang.org/
Issue #22080 has been updated by matz (Yukihiro Matsumoto). Thank you for the report. I see the asymmetry, but I think the diagnosis should be the other way around. The intent of `exception: false` is to suppress *conversion-failure* exceptions, such as `Integer("abc")` raising `ArgumentError`. It is not meant to suppress contract violations like `to_int` or `to_str` returning a value of the wrong type. Those are programming errors in the converter, not failures of the conversion itself. Returning `nil` for those would silently hide bugs. Under this principle, the current `to_str` behavior (raising `TypeError`) is correct. The current `to_int` behavior (returning `nil`) is the one that does not match. I'd like to align by making `to_int` also raise, and to update the documentation so it no longer says "an exception of any kind". If changing `to_int` turns out to break real-world code in practice, we can reconsider and align both to `nil` (with the documentation rewritten accordingly). But I'd like to try the principled direction first. Matz. ---------------------------------------- Bug #22080: `Integer(obj, exception: false)` raises when `to_str` doesn't return String https://bugs.ruby-lang.org/issues/22080#change-117563 * Author: Earlopain (Earlopain _) * Status: Open * ruby -v: ruby 4.1.0dev (2026-05-23T13:04:55Z master 6c6df00bbc) +PRISM [x86_64-linux] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- ```rb obj = Object.new def obj.to_str = 1 Integer(obj, exception: false) # can't convert Object to String (Object#to_str gives Integer) (TypeError) ``` But returning the wrong type from `to_int` is fine: ```rb obj = Object.new def obj.to_int = "1" Integer(obj, exception: false) # nil ``` Doc says this (https://docs.ruby-lang.org/en/master/Kernel.html#method-i-Integer):
With exception given as false, an exception of any kind is suppressed and nil is returned.
So it looks like it should not raise in both cases. Or more specifically, try `to_i` next, since that is what happens when `to_int` returns the wrong type. -- https://bugs.ruby-lang.org/
participants (2)
-
Earlopain (Earlopain _) -
matz (Yukihiro Matsumoto)