Should autoconvert on narrowing const operation

I try to implement a function foo() -> u8 for bitoperations. Therefore I wrote:

let v: u16 = 454545;
v & 0b111

Note that the last operation will limit the values to something narrower (3) than 8 bits. Also both values in the last operation are unsigned. Also, the narrowing bits are const and thus can be determined at compile time.

Rust complains:

error[E0308]: mismatched types

    |         let v: u16 = 454545;
    |         v & 0b111
    |         ^^^^^^^^^ expected `u8`, found `u16`
    |
help: you can convert a `u16` to a `u8` and panic if the converted value doesn't fit
    |
    |         (v & 0b111).try_into().unwrap()
    |         +         +++++++++++++++++++++

It would be great IMO if Rust could infer from the operation, that this bit and is safe and thus does a auto-convert. Not sure whether this also could apply to other scenarios.

The trouble with this automatic conversion is that it can mess up generic code: what happens if I call f(v & 0b111) when f is a generic function that receives both u8 or u16?

Anyway rather than the (v & 0b111).try_into().unwrap() that was suggested, I think you should write just (v & 0b111) as u8.

1 Like

It seems like there could be a separate operation specifically for this

impl u16 {
  fn narrow_bitand(self, rhs: u8) -> u8;
}

That avoids any having to look at values, simply by the types and operations semantics it guarantees the output is in range. (It could also be done via just impl BitAnd<u8> for u16, but that's maybe a bit too magic and likely to cause inference issues).

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.