Skip to content

Numeric#to_int is missing: SystemCallError.new with a Complex errno raises TypeError where MRI truncates, or raises RangeError #631

Open

Description

@tannevaled

MRI's NUM2LONG reaches a non-Integer through rb_to_int, i.e. #to_int. Numeric#to_int is defined as to_i (numeric.c num_to_int), so every Numeric answers it:

$ ruby -e 'p Complex(2.9, 0).to_int'          #=> 2
$ ruby -e 'p Complex(2.9, 1).to_int'          #=> RangeError: can't convert 2.9+1i into Integer
$ ruby -e 'p Complex(2.9, 0).respond_to?(:to_int)'  #=> true
$ ruby -e 'p Complex.instance_methods(false).grep(/to_i/)'  #=> [:to_i]

rbgo has Complex#to_i with the right value and the right RangeError, but no to_int, because Numeric#to_int is not defined:

$ rbgo -e 'p Complex(2.9, 0).to_i'    #=> 2
$ rbgo -e 'p Complex(2.9, 1).to_i'    #=> RangeError: can't convert (2.9+1i) into Integer
$ rbgo -e 'p Complex(2.9, 0).to_int'  #=> NoMethodError: undefined method 'to_int' for an instance of Complex

Consequence, now that SystemCallError#initialize coerces its errno the way syserr_initialize does (#629):

  • SystemCallError.new('foo', Complex(2.9, 0)) is a TypeError where MRI builds Errno::ENOENT
  • SystemCallError.new('foo', Complex(2.9, 1)) is a TypeError where MRI raises RangeError: can't convert 2.9+1i into Integer

Cost: 2 examples in core/exception/system_call_error_spec.rb ("converts to Integer if errno is a Complex convertible to Integer", "raises RangeError if errno is a Complex not convertible to Integer"). Anything else that coerces through #to_int is affected the same way.

Fix belongs in Numeric (one alias of to_i), not at the call sites — the #629 branch deliberately did not work around it locally, because a second coercion rule would drift from the first.

Note the message also differs: MRI says can't convert 2.9+1i into Integer, rbgo can't convert (2.9+1i) into Integer (parenthesised).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions