Rust default i32 or i64

Viewed 566

I have From implementations to create my type, but something weird happens:

impl From<i64> for Object {
    #[inline]
    fn from(i: i64) -> Self {
        Object {
            i: ((((i << 16) as usize) >> 13) + NAN_VALUE as usize - 1 + classSmallInteger) as i64,
        }
    }
}
impl From<u64> for Object {
    #[inline]
    fn from(u: u64) -> Self {
        Object {
            i: (((u as usize) << 16 >> 13) + NAN_VALUE as usize - 1 + classSmallInteger) as i64,
        }
    }
}
impl From<i32> for Object {
    #[inline]
    fn from(i: i32) -> Self {
        Object {
            i: ((((i << 16) as usize) >> 13) + NAN_VALUE as usize - 1 + classSmallInteger) as i64,
        }
    }
}

I originally had just the first one, and Object::from(42) worked fine. Then I wanted to add a conversion from u64, so I added the second definition. Then Object::from(42_u64) worked, but all the places where I had literals like 42 turned into i32s, and I got errors, so I added the third case, and Object::from(42) worked again, but was being interpreted as i32, and still anything like 1<<35 gave overflow errors, because the 1 was being interpreted as i32.

I don't understand why adding the second definition suddenly made all my constants default to i32, whereas they had previously been i64.

Is there a place to change the default to be i64?

1 Answers

As @LambdaFairy and @Stargateur pointed out, this addition of the second definition makes the integer constants inference ambiguous. Previously they were inferred to be i64, but once the ambiguity enters the scene, they fall back to i32 as per RFC212.

It would be nice to be told by the compiler that the inference was ambiguous, but at least I understand now.

Related