[ruby-core:109855] [Ruby master Bug#18998] Kernel#Integer does not convert SimpleDelegator object expectly
From:
"byroot (Jean Boussier)" <noreply@...>
Date:
2022-09-08 19:35:08 UTC
List:
ruby-core #109855
Issue #18998 has been updated by byroot (Jean Boussier).
So this behavior isn't documented, so it's hard to say wether it's correct:
> Integer(arg, base=0, exception: true) → integer or nil
Converts arg to an Integer. Numeric types are converted directly (with floating point numbers being truncated). base (0, or between 2 and 36) is a base for integer string representation. If arg is a String, when base is omitted or equals zero, radix indicators (0, 0b, and 0x) are honored. In any case, strings should consist only of one or more digits, except for that a sign, one underscore between two digits, and leading/trailing spaces are optional. This behavior is different from that of String#to_i. Non string values will be converted by first trying to_int, then to_i.
> Passing nil raises a TypeError, while passing a String that does not conform with numeric representation raises an ArgumentError. This behavior can be altered by passing exception: false, in this case a not convertible value will return nil.
However the intent of the implementation is fairly clear:
```
static VALUE
rb_convert_to_integer(VALUE val, int base, int raise_exception)
{
VALUE tmp;
// snip
if (RB_FLOAT_TYPE_P(val)) {
double f = RFLOAT_VALUE(val);
if (!raise_exception && !isfinite(f)) return Qnil;
if (FIXABLE(f)) return LONG2FIX((long)f);
return rb_dbl2big(f);
}
else if (RB_INTEGER_TYPE_P(val)) {
return val;
}
else if (RB_TYPE_P(val, T_STRING)) {
return rb_str_convert_to_inum(val, base, TRUE, raise_exception);
}
else if (NIL_P(val)) {
if (!raise_exception) return Qnil;
rb_raise(rb_eTypeError, "can't convert nil into Integer");
}
tmp = rb_protect(rb_check_to_int, val, NULL);
if (RB_INTEGER_TYPE_P(tmp)) return tmp;
rb_set_errinfo(Qnil);
if (!raise_exception) {
VALUE result = rb_protect(rb_check_to_i, val, NULL);
rb_set_errinfo(Qnil);
return result;
}
return rb_to_integer(val, "to_i", idTo_i);
}
```
If passed an object that is neither a direct string nor a native numeric, `Integer` first tries to invoke `to_int`, then fallback to invoke `to_i`.
I suppose a case could be made to first try to call `to_str`.
----------------------------------------
Bug #18998: Kernel#Integer does not convert SimpleDelegator object expectly
https://bugs.ruby-lang.org/issues/18998#change-99092
* Author: taichi730 (Taichi Ishitani)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
Kernel#Integer method doens not convert a SimpleDelegator object of which value is a String.
This is an sample code.
``` ruby
require 'delegate'
p Integer(SimpleDelegator.new('0x10'))
```
I expect Kernel#Integer to convert the input value as a String and the expected returned value is `16`.
Hoever the actual returned value is `0` so it's seemed that `#to_i` method is just called.
```
taichi@LAPTOP-TVTKLNFD:temp
$ cat test.rb
require 'delegate'
p Integer(SimpleDelegator.new('0x10'))
taichi@LAPTOP-TVTKLNFD:temp
$ ruby test.rb
0
```
Which is the correct behavior?
--
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>