Repository: rust
Issue: narrowing_rem, narrowing_and
Labels: T-libs-api,C-feature-request

To remove some unsafe "as" casts and keep the code safe (lossless) and nice, sometimes I'd like to use a rem+cast. So what do you think about adding this to the stdlib?

```rust
trait NarrowRem<Out> {
    fn narrowing_rem(&self, den: Out) -> Out;
}

impl NarrowRem<u8> for u16 {
    fn narrowing_rem(&self, den: u8) -> u8 { (*self % u16::from(den)) as u8 }
}
impl NarrowRem<u8> for u32 {
    fn narrowing_rem(&self, den: u8) -> u8 { (*self % u32::from(den)) as u8 }
}
impl NarrowRem<u16> for u32 {
    fn narrowing_rem(&self, den: u16) -> u16 { (*self % u32::from(den)) as u16 }
}
impl NarrowRem<u8> for u64 {
    fn narrowing_rem(&self, den: u8) -> u8 { (*self % u64::from(den)) as u8 }
}
impl NarrowRem<u16> for u64 {
    fn narrowing_rem(&self, den: u16) -> u16 { (*self % u64::from(den)) as u16 }
}
impl NarrowRem<u32> for u64 {
    fn narrowing_rem(&self, den: u32) -> u32 { (*self % u64::from(den)) as u32 }
}
impl NarrowRem<u8> for u128 {
    fn narrowing_rem(&self, den: u8) -> u8 { (*self % u128::from(den)) as u8 }
}
impl NarrowRem<u16> for u128 {
    fn narrowing_rem(&self, den: u16) -> u16 { (*self % u128::from(den)) as u16 }
}
impl NarrowRem<u32> for u128 {
    fn narrowing_rem(&self, den: u32) -> u32 { (*self % u128::from(den)) as u32 }
}
impl NarrowRem<u64> for u128 {
    fn narrowing_rem(&self, den: u64) -> u64 { (*self % u128::from(den)) as u64 }
}

impl NarrowRem<i8> for i16 {
    fn narrowing_rem(&self, den: i8) -> i8 { (*self % i16::from(den)) as i8 }
}
impl NarrowRem<i8> for i32 {
    fn narrowing_rem(&self, den: i8) -> i8 { (*self % i32::from(den)) as i8 }
}
impl NarrowRem<i16> for i32 {
    fn narrowing_rem(&self, den: i16) -> i16 { (*self % i32::from(den)) as i16 }
}
impl NarrowRem<i8> for i64 {
    fn narrowing_rem(&self, den: i8) -> i8 { (*self % i64::from(den)) as i8 }
}
impl NarrowRem<i16> for i64 {
    fn narrowing_rem(&self, den: i16) -> i16 { (*self % i64::from(den)) as i16 }
}
impl NarrowRem<i32> for i64 {
    fn narrowing_rem(&self, den: i32) -> i32 { (*self % i64::from(den)) as i32 }
}
impl NarrowRem<i8> for i128 {
    fn narrowing_rem(&self, den: i8) -> i8 { (*self % i128::from(den)) as i8 }
}
impl NarrowRem<i16> for i128 {
    fn narrowing_rem(&self, den: i16) -> i16 { (*self % i128::from(den)) as i16 }
}
impl NarrowRem<i32> for i128 {
    fn narrowing_rem(&self, den: i32) -> i32 { (*self % i128::from(den)) as i32 }
}
impl NarrowRem<i64> for i128 {
    fn narrowing_rem(&self, den: i64) -> i64 { (*self % i128::from(den)) as i64 }
}

impl NarrowRem<u8> for usize {
    fn narrowing_rem(&self, den: u8) -> u8 { (*self % usize::from(den)) as u8 }
}
impl NarrowRem<u16> for usize {
    fn narrowing_rem(&self, den: u16) -> u16 { (*self % usize::from(den)) as u16 }
}

impl NarrowRem<i8> for isize {
    fn narrowing_rem(&self, den: i8) -> i8 { (*self % isize::from(den)) as i8 }
}
impl NarrowRem<i16> for isize {
    fn narrowing_rem(&self, den: i16) -> i16 { (*self % isize::from(den)) as i16 }
}
```
An example usage:

```rust
fn main() {
    let _x: u8 = 152_u64.narrowing_rem(51_u8);
}
```

D language performs this lossless cast operation automatically and transparently (while it doesn't perform lossy casts silently):

```
uint foo(in ulong x) { // Error: cannot implicitly convert
    return x;
}
uint bar(in ulong x) { // OK
    return x % 1000;
}
void main() {}
```