Primitive type bound

Code [cut down example]:

fn as_T(x: u64) -> T {
    x as T
}

Error:

error[E0605]: non-primitive cast: `u64` as `T`

Now, I only want to implement this for T in u32, u64, so my T is primitive. Can we have a primitive type bound for generic programming? Of course "primitive" is probably not well enough defined for this anyway, so traits are the obvious solution.

The compiler recommends usage of From, but of course From doesn't support lossy conversions like u64 → u32, and I'm fairly sure there isn't an equivalent which does support this in the standard library. Of course I could roll my own but I'd much prefer a convenient solution.

Should we have a From equivalent allowing lossy conversions in the standard library? Probably not, it's messy having multiple similar traits. Are there any other good solutions? (Sure, roll another crate. But that's just as messy.)

Look at std::convert::TryFrom, which is currently experimental but will likely be stabilized soon. You’ll need to decide on how to handle conversion errors.

fn as_T<T: From<u64>>(x: u64) -> T {
   x.into()
}

In other cases where there isn't a trait that fits, invent your own and implement it for the couple of types you want.

3 Likes

Considering in this case I wanted to throw away any bits in the high part when down-sizing, neither solution helps avoid having to roll my own traits. Meh.

You can make the function take a closure that gets called in the error case, allowing the caller to decide how to handle it (such as discarding the high 32 bits). You can then wire up the closure to a helper function so that you don’t have to repeat the same closure body on each call.

But your own dedicated trait for this is a good solution too.

@dhardy it may be helpful:
num-traits

Please don't bump old threads.

1 Like