Proposal: integer conversion methods


#21

It would be helpful to have a couple code samples with a lot of casts in them. It is really hard to judge the ergonomics of any of these options looking at only a single conversion…

Edit: One possible example from my own code.


#22

Here’s a simple example that shows the reduced readability (vs as):

use core::num::Wrapping;
impl crypto_support for u32 {
  // Define arithmetic operator on u32s for 32b x 32b -> 32b pseudo-modulo
  // multiply that approximates multiplication modulo G(x) ≈ x.pow(32) + 1
  #[inline(always)]
  fn mul_mod_gx(self, rhs: &Self) -> Self {
    let t: u64 = self as u64 * rhs as u64;     // 32b x 32b -> 64b multiply
    (t as u32).wrapping_sub((t >> 32) as u32)  // subtract MS half from LS half
  }

versus

    (t.to_wrapping_u32()).wrapping_sub((t >> 32).to_wrapping_u32())

#23

That situation looks not like a cast problem to me, but instead like

where it would be (using my current favourite proposal)

let (low, high) = self.mul_with_carry(*rhs, 0);
low.wrapping_sub(high)

And that snippit is a great example of why as scares me:

That’s casting &_ to u64, which feels to me like it could be a ptr2int cast. I assume it’s not, and it’s doing what you wanted, but it’s really quite hard to be sure.


#24

This was offered only as an example. In actual use the inputs are wrapped u32s (w32s). I’m fully aware that Rust’s references and unsafe raw pointers are not simply integers (unlike in many other languages).

Some architectures implement 32b x 32b -> 64b multiply in one instruction, others implement it in two related instructions (one generating the low-order 32b and the other the high-order 32b of the 64b result), while still others can’t generate the high-order 32b in hardware at all. It’s low-level differences such as that which drive much crypto to be written in assembly.

Addendum: I should have pointed out that LLVM does not provide the needed n x n -> 2n multiply, even though most architectures support it.


#25

(I still think we should allow implicit widening, that is, coerce for example u8 to u16.)


#26

… or anything not larger to usize for indexing.


#27

Am I off base in thinking all of these conversion functions can be accomplished with a single macro?