From: eregontp@... Date: 2016-05-03T11:36:04+00:00 Subject: [ruby-core:75327] [Ruby trunk Bug#12337] inconsistency between Fixnum#coerce and Bignum#coerce Issue #12337 has been updated by Benoit Daloze. Akira Tanaka wrote: > Bignum.coerce(Fixnum) is used to implement fixnum binop bignum. > (binop is binary operator such as +, -, etc.) > > x binop y is implemented as follows if x's class doesn't know y's class. > [...] > However matz also use it for builtin numeric classes: Fixnum, Bignum and Float. Thanks for the clarification. In the specific case of Fixnum binop Bignum, I expect all Fixnum methods already know about Bignum and do not call coerce, isn't it? I tried locally to raise an error when Fixnum.coerce(Bignum) is called and got only 1 failure in test-all (due to rb_num_coerce_cmp called by ruby_num_interval_step_size(#size) on an Enumerator from Numerc#step with a Bignum step). That said, I think your patch is an improvement until #12005 is merged. ---------------------------------------- Bug #12337: inconsistency between Fixnum#coerce and Bignum#coerce https://bugs.ruby-lang.org/issues/12337#change-58457 * Author: Akira Tanaka * Status: Open * Priority: Normal * Assignee: * ruby -v: ruby 2.4.0dev (2016-05-01 trunk 54866) [x86_64-linux] * Backport: 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN ---------------------------------------- I found 1.coerce(2.0) is [2.0, 1.0] but (2**100).coerce(2.0) raises TypeError ``` % ./ruby -ve 'p 1.coerce(2.0)' ruby 2.4.0dev (2016-05-01 trunk 54866) [x86_64-linux] [2.0, 1.0] % ./ruby -ve 'p (2**100).coerce(2.0)' ruby 2.4.0dev (2016-05-01 trunk 54866) [x86_64-linux] -e:1:in `coerce': can't coerce Float to Bignum (TypeError) from -e:1:in `
' ``` This is a documented behavior. ``` % ri Bignum.coerce|cat = Bignum.coerce (from ruby core) ------------------------------------------------------------------------------ big.coerce(numeric) -> array ------------------------------------------------------------------------------ Returns an array with both a numeric and a big represented as Bignum objects. This is achieved by converting numeric to a Bignum. A TypeError is raised if the numeric is not a Fixnum or Bignum type. (0x3FFFFFFFFFFFFFFF+1).coerce(42) #=> [42, 4611686018427387904] ``` But I think this is bad bahavior. Fixnum and Bignum should work seamlessly. For example, this exposes the platform is 32-bit or 64-bit. 2**40 is Fixnum on 32-bit environment and Bignum on 64-bit environment. So, (2**40).coerce(2.0) behaves differently: returns an array on 64-bit and raises TypeError on 32-bit platform. ``` 32bit-platform% ./ruby -ve 'p (2**40).coerce(2.0)' ruby 2.4.0dev (2016-05-01 trunk 54866) [x86_64-linux] [2.0, 1099511627776.0] 64bit-platform% ./ruby -ve 'p (2**40).coerce(2.0)' ruby 2.4.0dev (2016-05-01 trunk 54864) [i686-linux] -e:1:in `coerce': can't coerce Float to Bignum (TypeError) from -e:1:in `
' ``` I think the behavior of Bignum#coerce should be changed to match Fixnum#coerce (actually defined at Numeric). ---Files-------------------------------- int-coerce.patch (2.37 KB) -- https://bugs.ruby-lang.org/ Unsubscribe: