# Proposal: integer conversion methods

**URL:** <https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355>\
**Category:** Uncategorized\
**Created:** [February 4, 2019, 6:57am UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355 "2019-02-04T06:57:10Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![canndrew](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/canndrew/32/1676_2.png) [@canndrew](https://internals.rust-lang.org/u/canndrew)\
**Post date:** [February 4, 2019, 6:57am UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/1 "2019-02-04T06:57:10Z")

</div>

A pain point I’ve always had with Rust is the lack of methods to convert between integer types. Yes there’s `as`, but `as` can fail when downcasting. Yes there’s `TryFrom`/`TryInto`, but `try_from` and `try_into` aren’t very descriptive since they don’t include the output type in the name and this makes code harder to read.

Can we just add the following inherent methods to the integer types?:

```rust
impl u8 {
    fn to_u16(self) -> u16;
    fn to_u32(self) -> u32;
    fn to_u64(self) -> u64;
    fn to_u128(self) -> u128;
    fn to_usize(self) -> usize;
    fn checked_to_i8(self) -> Option<i8>;
    fn saturating_to_i8(self) -> i8;
    fn wrapping_to_i8(self) -> i8;
    fn to_i16(self) -> i16;
    fn to_i32(self) -> i32;
    fn to_i64(self) -> i64;
    fn to_i128(self) -> i128;
    fn to_isize(self) -> isize;
}

impl u16 {
    fn checked_to_u8(self) -> Option<u8>;
    fn saturating_to_u8(self) -> u8;
    fn wrapping_to_u8(self) -> u8;
    fn to_u32(self) -> u32;
    fn to_u64(self) -> u64;
    fn to_u128(self) -> u128;
    fn to_usize(self) -> usize;
    fn checked_to_i8(self) -> Option<i8>;
    fn saturating_to_i8(self) -> i8;
    fn wrapping_to_i8(self) -> i8;
    fn checked_to_i16(self) -> Option<i16>;
    fn saturating_to_i16(self) -> i16;
    fn wrapping_to_i16(self) -> i16;
    fn to_i32(self) -> i32;
    fn to_i64(self) -> i64;
    fn to_i128(self) -> i128;
    fn to_isize(self) -> isize;
}

impl u32 {
    fn checked_to_u8(self) -> Option<u8>;
    fn saturating_to_u8(self) -> u8;
    fn wrapping_to_u8(self) -> u8;
    fn checked_to_u16(self) -> Option<u16>;
    fn saturating_to_u16(self) -> u16;
    fn wrapping_to_u16(self) -> u16;
    fn to_u64(self) -> u64;
    fn to_u128(self) -> u128;
    fn to_usize(self) -> usize;
    fn checked_to_i8(self) -> Option<i8>;
    fn saturating_to_i8(self) -> i8;
    fn wrapping_to_i8(self) -> i8;
    fn checked_to_i16(self) -> Option<i16>;
    fn saturating_to_i16(self) -> i16;
    fn wrapping_to_i16(self) -> i16;
    fn checked_to_i32(self) -> Option<i32>;
    fn saturating_to_i32(self) -> i32;
    fn wrapping_to_i32(self) -> i32;
    fn to_i64(self) -> i64;
    fn to_i128(self) -> i128;
    fn checked_to_isize(self) -> Option<isize>;
    fn saturating_to_isize(self) -> isize;
    fn wrapping_to_isize(self) -> isize;
}

impl u64 {
    fn checked_to_u8(self) -> Option<u8>;
    fn saturating_to_u8(self) -> u8;
    fn wrapping_to_u8(self) -> u8;
    fn checked_to_u16(self) -> Option<u16>;
    fn saturating_to_u16(self) -> u16;
    fn wrapping_to_u16(self) -> u16;
    fn checked_to_u32(self) -> Option<u32>;
    fn saturating_to_u32(self) -> u32;
    fn wrapping_to_u32(self) -> u32;
    fn to_u128(self) -> u128;
    fn checked_to_usize(self) -> Option<usize>;
    fn saturating_to_usize(self) -> usize;
    fn wrapping_to_usize(self) -> usize;
    fn checked_to_i8(self) -> Option<i8>;
    fn saturating_to_i8(self) -> i8;
    fn wrapping_to_i8(self) -> i8;
    fn checked_to_i16(self) -> Option<i16>;
    fn saturating_to_i16(self) -> i16;
    fn wrapping_to_i16(self) -> i16;
    fn checked_to_i32(self) -> Option<i32>;
    fn saturating_to_i32(self) -> i32;
    fn wrapping_to_i32(self) -> i32;
    fn checked_to_i64(self) -> Option<i64>;
    fn saturating_to_i64(self) -> i64;
    fn wrapping_to_i64(self) -> i64;
    fn to_i128(self) -> i128;
    fn checked_to_isize(self) -> Option<isize>;
    fn saturating_to_isize(self) -> isize;
    fn wrapping_to_isize(self) -> isize;
}

impl u128 {
    fn checked_to_u8(self) -> Option<u8>;
    fn saturating_to_u8(self) -> u8;
    fn wrapping_to_u8(self) -> u8;
    fn checked_to_u16(self) -> Option<u16>;
    fn saturating_to_u16(self) -> u16;
    fn wrapping_to_u16(self) -> u16;
    fn checked_to_u32(self) -> Option<u32>;
    fn saturating_to_u32(self) -> u32;
    fn wrapping_to_u32(self) -> u32;
    fn checked_to_u64(self) -> Option<u64>;
    fn saturating_to_u64(self) -> u64;
    fn wrapping_to_u64(self) -> u64;
    fn checked_to_usize(self) -> Option<usize>;
    fn saturating_to_usize(self) -> usize;
    fn wrapping_to_usize(self) -> usize;
    fn checked_to_i8(self) -> Option<i8>;
    fn saturating_to_i8(self) -> i8;
    fn wrapping_to_i8(self) -> i8;
    fn checked_to_i16(self) -> Option<i16>;
    fn saturating_to_i16(self) -> i16;
    fn wrapping_to_i16(self) -> i16;
    fn checked_to_i32(self) -> Option<i32>;
    fn saturating_to_i32(self) -> i32;
    fn wrapping_to_i32(self) -> i32;
    fn checked_to_i64(self) -> Option<i64>;
    fn saturating_to_i64(self) -> i64;
    fn wrapping_to_i64(self) -> i64;
    fn checked_to_i128(self) -> Option<i128>;
    fn saturating_to_i128(self) -> i128;
    fn wrapping_to_i128(self) -> i128;
    fn checked_to_isize(self) -> Option<isize>;
    fn saturating_to_isize(self) -> isize;
    fn wrapping_to_isize(self) -> isize;
}

impl usize {
    fn checked_to_u8(self) -> Option<u8>;
    fn saturating_to_u8(self) -> u8;
    fn wrapping_to_u8(self) -> u8;
    fn checked_to_u16(self) -> Option<u16>;
    fn saturating_to_u16(self) -> u16;
    fn wrapping_to_u16(self) -> u16;
    fn checked_to_u32(self) -> Option<u32>;
    fn saturating_to_u32(self) -> u32;
    fn wrapping_to_u32(self) -> u32;
    fn to_u64(self) -> u64;
    fn to_u128(self) -> u128;
    fn checked_to_i8(self) -> Option<i8>;
    fn saturating_to_i8(self) -> i8;
    fn wrapping_to_i8(self) -> i8;
    fn checked_to_i16(self) -> Option<i16>;
    fn saturating_to_i16(self) -> i16;
    fn wrapping_to_i16(self) -> i16;
    fn checked_to_i32(self) -> Option<i32>;
    fn saturating_to_i32(self) -> i32;
    fn wrapping_to_i32(self) -> i32;
    fn checked_to_i64(self) -> Option<i64>;
    fn saturating_to_i64(self) -> i64;
    fn wrapping_to_i64(self) -> i64;
    fn to_i128(self) -> i128;
    fn checked_to_isize(self) -> Option<isize>;
    fn saturating_to_isize(self) -> isize;
    fn wrapping_to_isize(self) -> isize;
}

impl i8 {
    fn checked_to_u8(self) -> Option<u8>;
    fn saturating_to_u8(self) -> u8;
    fn wrapping_to_u8(self) -> u8;
    fn checked_to_u16(self) -> Option<u16>;
    fn saturating_to_u16(self) -> u16;
    fn wrapping_to_u16(self) -> u16;
    fn checked_to_u32(self) -> Option<u32>;
    fn saturating_to_u32(self) -> u32;
    fn wrapping_to_u32(self) -> u32;
    fn checked_to_u64(self) -> Option<u64>;
    fn saturating_to_u64(self) -> u64;
    fn wrapping_to_u64(self) -> u64;
    fn checked_to_u128(self) -> Option<u128>;
    fn saturating_to_u128(self) -> u128;
    fn wrapping_to_u128(self) -> u128;
    fn checked_to_usize(self) -> Option<usize>;
    fn saturating_to_usize(self) -> usize;
    fn wrapping_to_usize(self) -> usize;
    fn to_i16(self) -> i16;
    fn to_i32(self) -> i32;
    fn to_i64(self) -> i64;
    fn to_i128(self) -> i128;
    fn to_isize(self) -> isize
}

impl i16 {
    fn checked_to_u8(self) -> Option<u8>;
    fn saturating_to_u8(self) -> u8;
    fn wrapping_to_u8(self) -> u8;
    fn checked_to_u16(self) -> Option<u16>;
    fn saturating_to_u16(self) -> u16;
    fn wrapping_to_u16(self) -> u16;
    fn checked_to_u32(self) -> Option<u32>;
    fn saturating_to_u32(self) -> u32;
    fn wrapping_to_u32(self) -> u32;
    fn checked_to_u64(self) -> Option<u64>;
    fn saturating_to_u64(self) -> u64;
    fn wrapping_to_u64(self) -> u64;
    fn checked_to_u128(self) -> Option<u128>;
    fn saturating_to_u128(self) -> u128;
    fn wrapping_to_u128(self) -> u128;
    fn checked_to_usize(self) -> Option<usize>;
    fn saturating_to_usize(self) -> usize;
    fn wrapping_to_usize(self) -> usize;
    fn checked_to_i8(self) -> Option<i8>;
    fn saturating_to_i8(self) -> i8;
    fn wrapping_to_i8(self) -> i8;
    fn to_i32(self) -> i32;
    fn to_i64(self) -> i64;
    fn to_i128(self) -> i128;
    fn to_isize(self) -> isize
}

impl i32 {
    fn checked_to_u8(self) -> Option<u8>;
    fn saturating_to_u8(self) -> u8;
    fn wrapping_to_u8(self) -> u8;
    fn checked_to_u16(self) -> Option<u16>;
    fn saturating_to_u16(self) -> u16;
    fn wrapping_to_u16(self) -> u16;
    fn checked_to_u32(self) -> Option<u32>;
    fn saturating_to_u32(self) -> u32;
    fn wrapping_to_u32(self) -> u32;
    fn checked_to_u64(self) -> Option<u64>;
    fn saturating_to_u64(self) -> u64;
    fn wrapping_to_u64(self) -> u64;
    fn checked_to_u128(self) -> Option<u128>;
    fn saturating_to_u128(self) -> u128;
    fn wrapping_to_u128(self) -> u128;
    fn checked_to_usize(self) -> Option<usize>;
    fn saturating_to_usize(self) -> usize;
    fn wrapping_to_usize(self) -> usize;
    fn checked_to_i8(self) -> Option<i8>;
    fn saturating_to_i8(self) -> i8;
    fn wrapping_to_i8(self) -> i8;
    fn checked_to_i16(self) -> Option<i16>;
    fn saturating_to_i16(self) -> i16;
    fn wrapping_to_i16(self) -> i16;
    fn to_i64(self) -> i64;
    fn to_i128(self) -> i128;
    fn to_isize(self) -> isize
}

impl i64 {
    fn checked_to_u8(self) -> Option<u8>;
    fn saturating_to_u8(self) -> u8;
    fn wrapping_to_u8(self) -> u8;
    fn checked_to_u16(self) -> Option<u16>;
    fn saturating_to_u16(self) -> u16;
    fn wrapping_to_u16(self) -> u16;
    fn checked_to_u32(self) -> Option<u32>;
    fn saturating_to_u32(self) -> u32;
    fn wrapping_to_u32(self) -> u32;
    fn checked_to_u64(self) -> Option<u64>;
    fn saturating_to_u64(self) -> u64;
    fn wrapping_to_u64(self) -> u64;
    fn checked_to_u128(self) -> Option<u128>;
    fn saturating_to_u128(self) -> u128;
    fn wrapping_to_u128(self) -> u128;
    fn checked_to_usize(self) -> Option<usize>;
    fn saturating_to_usize(self) -> usize;
    fn wrapping_to_usize(self) -> usize;
    fn checked_to_i8(self) -> Option<i8>;
    fn saturating_to_i8(self) -> i8;
    fn wrapping_to_i8(self) -> i8;
    fn checked_to_i16(self) -> Option<i16>;
    fn saturating_to_i16(self) -> i16;
    fn wrapping_to_i16(self) -> i16;
    fn checked_to_i32(self) -> Option<i32>;
    fn saturating_to_i32(self) -> i32;
    fn wrapping_to_i32(self) -> i32;
    fn to_i128(self) -> i128;
    fn checked_to_isize(self) -> Option<isize>;
    fn saturating_to_isize(self) -> isize;
    fn wrapping_to_isize(self) -> isize;
}

impl i128 {
    fn checked_to_u8(self) -> Option<u8>;
    fn saturating_to_u8(self) -> u8;
    fn wrapping_to_u8(self) -> u8;
    fn checked_to_u16(self) -> Option<u16>;
    fn saturating_to_u16(self) -> u16;
    fn wrapping_to_u16(self) -> u16;
    fn checked_to_u32(self) -> Option<u32>;
    fn saturating_to_u32(self) -> u32;
    fn wrapping_to_u32(self) -> u32;
    fn checked_to_u64(self) -> Option<u64>;
    fn saturating_to_u64(self) -> u64;
    fn wrapping_to_u64(self) -> u64;
    fn checked_to_u128(self) -> Option<u128>;
    fn saturating_to_u128(self) -> u128;
    fn wrapping_to_u128(self) -> u128;
    fn checked_to_usize(self) -> Option<usize>;
    fn saturating_to_usize(self) -> usize;
    fn wrapping_to_usize(self) -> usize;
    fn checked_to_i8(self) -> Option<i8>;
    fn saturating_to_i8(self) -> i8;
    fn wrapping_to_i8(self) -> i8;
    fn checked_to_i16(self) -> Option<i16>;
    fn saturating_to_i16(self) -> i16;
    fn wrapping_to_i16(self) -> i16;
    fn checked_to_i32(self) -> Option<i32>;
    fn saturating_to_i32(self) -> i32;
    fn wrapping_to_i32(self) -> i32;
    fn checked_to_i64(self) -> Option<i64>;
    fn saturating_to_i64(self) -> i64;
    fn wrapping_to_i64(self) -> i64;
    fn checked_to_isize(self) -> Option<isize>;
    fn saturating_to_isize(self) -> isize;
    fn wrapping_to_isize(self) -> isize;
}

impl isize {
    fn checked_to_u8(self) -> Option<u8>;
    fn saturating_to_u8(self) -> u8;
    fn wrapping_to_u8(self) -> u8;
    fn checked_to_u16(self) -> Option<u16>;
    fn saturating_to_u16(self) -> u16;
    fn wrapping_to_u16(self) -> u16;
    fn checked_to_u32(self) -> Option<u32>;
    fn saturating_to_u32(self) -> u32;
    fn wrapping_to_u32(self) -> u32;
    fn checked_to_u64(self) -> Option<u64>;
    fn saturating_to_u64(self) -> u64;
    fn wrapping_to_u64(self) -> u64;
    fn checked_to_u128(self) -> Option<u128>;
    fn saturating_to_u128(self) -> u128;
    fn wrapping_to_u128(self) -> u128;
    fn checked_to_usize(self) -> Option<usize>;
    fn saturating_to_usize(self) -> usize;
    fn wrapping_to_usize(self) -> usize;
    fn checked_to_i8(self) -> Option<i8>;
    fn saturating_to_i8(self) -> i8;
    fn wrapping_to_i8(self) -> i8;
    fn checked_to_i16(self) -> Option<i16>;
    fn saturating_to_i16(self) -> i16;
    fn wrapping_to_i16(self) -> i16;
    fn checked_to_i32(self) -> Option<i32>;
    fn saturating_to_i32(self) -> i32;
    fn wrapping_to_i32(self) -> i32;
    fn to_i64(self) -> i64;
    fn to_i128(self) -> i128;
}

```

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [February 4, 2019, 7:17am UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/2 "2019-02-04T07:17:07Z")

</div>

The sheer number of methods there (for every pair of types) seems like a case study in why `into` and `try_into` work more concisely. You can always choose to explicitly write the output type if you feel it’ll make your code more self-documenting.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [February 4, 2019, 7:19am UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/3 "2019-02-04T07:19:36Z")

</div>

It’d be nice if we could more easily type hint `.into` (that’s generalized type ascription). If you’re worried about clarity, though, just use `<uN>::from(<expr>)`.

---

<div class="post-metadata">

**Author:** ![canndrew](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/canndrew/32/1676_2.png) [@canndrew](https://internals.rust-lang.org/u/canndrew)\
**Post date:** [February 4, 2019, 7:54am UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/4 "2019-02-04T07:54:20Z")

</div>

> [@josh](#):
>
> The sheer number of methods there (for every pair of types) seems like a case study in why `into` and `try_into` work more concisely. You can always choose to explicitly write the output type if you feel it’ll make your code more self-documenting.

How is `.into()` significantly more concise than `.to_u16()`? `.into::<u16>()` is less concise, uglier, and more annoying to type than `.to_u16()`.

I think it's bad form to use `from`/`into` when you know the concrete types. Methods should have descriptive names that say what the code is doing. Just about any method could be replaced with `from`/`into` if we wanted, eg. we could add an `impl TryFrom<SocketAddr> for TcpStream` then deprecate `TcpStream::connect` since it's unnecessary. We wouldn't do that since `connect` is so much clearer than `from`, however I've seen actual code that uses `.into().into().into()` due to lack of explicit methods and it's just painful to decipher. `{Try,}{From,Into}` should be restricted to when you don't know the concrete types and so you're forced to use some generic, general-purpose trait, otherwise you should use something less ambiguous.

Also `TryFrom` doesn't give you the `checked`/`saturating`/`wrapping` distinction that I proposed and which is sometimes useful.

> [@CAD97](#):
>
> If you’re worried about clarity, though, just use `<uN>::from(<expr>)` .

I could, but methods would often be nicer.

---

<div class="post-metadata">

**Author:** ![canndrew](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/canndrew/32/1676_2.png) [@canndrew](https://internals.rust-lang.org/u/canndrew)\
**Post date:** [February 4, 2019, 8:05am UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/5 "2019-02-04T08:05:01Z")

</div>

The only downside I can see to adding these is that it adds to the documentation. But the int types already have lots of methods that someone exploring the documentation needs to scroll through.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [February 4, 2019, 11:58am UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/6 "2019-02-04T11:58:57Z")

</div>

> How is `.into()` significantly more concise than `.to_u16()`? `.into::<u16>()` is less concise, uglier, and more annoying to type than `.to_u16()`.

.into() is more concise, though, and works well if you're in a context where you already know you need a u16.

> I think it's bad form to use `from`/`into` when you know the concrete types.

I don't.

---

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [February 4, 2019, 2:24pm UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/7 "2019-02-04T14:24:30Z")

</div>

I think this is a great idea. I read `into` as “turn A into B, I don’t care how”… but when I’m casting integers, I _do_ care how. The `wrapping`, `checked`, and `saturated` variants are things I really want to state explicitly in my code. There is no single obvious way to cast between different number types (I regularly have to go look up Rust’s casting behavior, because I can never remember what it is).

Moreover, `into` is obnoxious for inference reasons: arithmetic is one place where I don’t trust inference to figure out the correct type.

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [February 4, 2019, 2:29pm UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/8 "2019-02-04T14:29:23Z")

</div>

> [@canndrew](#):
>
> How is `.into()` significantly more concise than `.to_u16()` ? `.into::<u16>()` is less concise, uglier, and more annoying to type than `.to_u16()` .

`n.to_u16()` is redundant when we already have `u16::from(n)`. Both convey the same information. The difference is using `From` leans on a trait, which to me is more idiomatic, and permits things like using generics or associated types with bounds for convertible types, something I just used the other day as it were for this specific case.

Furthermore:

```rust
u16::from(n)

```

...already has impls for: `bool`, `u8`, `NonZeroU16`

> **[u16 - Rust](https://doc.rust-lang.org/std/primitive.u16.html#impl-From%3Cbool%3E)**
>
> The 16-bit unsigned integer type.

```rust
u16::try_from(n)

```

...already has impls for: `i8`, `i16`, `i32`, `i64`, `i128`, `isize`, `u32`, `u64`, `u128`, `usize`

> **[u16 - Rust](https://doc.rust-lang.org/std/primitive.u16.html#impl-TryFrom%3Ci32%3E)**
>
> The 16-bit unsigned integer type.

What you are proposing is redundant, less idiomatic, and as @josh noted results in an explosion of complexity.

> [@](#):
>
> I think it’s bad form to use from/into when you know the concrete types. Methods should have descriptive names that say what the code is doing. Just about any method could be replaced with from/into if we wanted, eg. we could add an impl TryFrom for TcpStream then deprecate TcpStream::connect since it’s unnecessary.

This is a slippery slope argument. The usage of `From` / `TryFrom` mentioned here is specifically for the purpose of type conversions, which is exactly what you were originally asking about, exactly as these traits are intended to use, and many of these type conversions are _already impl'd for these types_.

No one is proposing they be used to things which have side effects or to create network packets. Yes, that would be bad, but it's also irrelevant for this use case.

---

<div class="post-metadata">

**Author:** ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)\
**Post date:** [February 4, 2019, 2:48pm UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/9 "2019-02-04T14:48:09Z")

</div>

> [@mcy](#):
>
> I read `into` as “turn A into B, I don’t care how”… but when I’m casting integers, I _do_ care how. The `wrapping` , `checked` , and `saturated` variants are things I really want to state explicitly in my code.

I would've expected this to be covered by From/Into impls between `Wrapped<u8>` and `u16` and all the other combinations, but apparently there are no such impls.

Is there any reason we couldn't add those impls, as an alternative to adding all of OP's inherent methods?

---

<div class="post-metadata">

**Author:** ![DanielKeep](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/danielkeep/32/1332_2.png) [@DanielKeep](https://internals.rust-lang.org/u/DanielKeep)\
**Post date:** [February 4, 2019, 3:22pm UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/10 "2019-02-04T15:22:11Z")

</div>

Just a note on potentially relevant prior art: the [`conv`](https://docs.rs/conv/0.3.3/conv/) crate ( **Disclaimer** : I wrote it) tried to address this by defining two extra conversion trait pairs: `Value{From,Into}` (for value-preserving conversions, which is mostly subsumed by current `Try{From,Into}`), and `Approx{From,Into}`. The `Approx*` traits also required the user specify an approximation scheme as a generic parameter (`DefaultApprox`, `Wrapping`, plus `RoundTo*` for float → integer).

All together, that gave you lossy casts (with `as`), checked casts (with `Value*`), wrapping casts (with `Approx*` + `Wrapping` scheme), and saturating casts (with `Value` + `saturate`/`unwrap_or_saturate` extension methods on the result).

---

<div class="post-metadata">

**Author:** ![Tom-Phinney](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tom-phinney/32/3299_2.png) [@Tom-Phinney](https://internals.rust-lang.org/u/Tom-Phinney)\
**Post date:** [February 4, 2019, 3:51pm UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/11 "2019-02-04T15:51:14Z")

</div>

Also as a note, the OP’s `impl`s for `usize` and `isize` are not forward-looking, and thus IMO are incomplete, because they do not account for `usize == u128`, which the RISC-V architecture supports as the logical endpoint of continuing growth in storage size. The missing `impl`s are:

```rust
impl usize {
    fn checked_to_u64(self) -> Option<u64>;
    fn saturating_to_u64(self) -> u64;
    fn wrapping_to_u64(self) -> u64;
 }

impl isize {
    fn checked_to_i64(self) -> Option<i64>;
    fn saturating_to_i64(self) -> i64;
    fn wrapping_to_i64(self) -> i64;
 }

```

and the following potentially-silently-truncating `impl`s, which presume that Rust will never support `usize` larger than `u64`, should be removed:

```rust
impl usize {
    fn to_u64(self) -> u64;
 }

impl isize {
    fn to_i64(self) -> i64;
}

```

---

<div class="post-metadata">

**Author:** ![ahmedcharles](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ahmedcharles/32/4041_2.png) [@ahmedcharles](https://internals.rust-lang.org/u/ahmedcharles)\
**Post date:** [February 4, 2019, 4:37pm UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/12 "2019-02-04T16:37:13Z")

</div>

For those who think that this is too many functions, they could all be replaced by two additional traits:

1. From/Into (existing, lossless conversion)
2. TryFrom/TryInto (existing, checking conversion)
3. TruncateFrom/TruncateInto (new, truncating/wrapping conversion)
4. SaturateFrom/SaturateInto (new, saturating conversion)

Bikeshedding aside, this separates the debate about adding lots of inherent methods from that about having a way to do truncating/saturating conversions without `as` being a foot gun.

Note: An amusing application for TruncateFrom would be converting from a `[u8]` into a `[u8; N]`.

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [February 4, 2019, 6:51pm UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/13 "2019-02-04T18:51:25Z")

</div>

It could also be done with three new types, (bikeshed names)

```rust
Saturating<T>(pub T);
Wrapping<T>(pub T);
Truncating<T>(pub T);

```

Then have have impls

```rust
From<Saturating<{integer}>> for {integer} { ... }
From<Wrapping<{integer}>> for {integer} { ... }
From<Truncating<{integer}>> for {integer} { ... }

```

for all pairs of integers, this way we can use the existing `From` machinery that we have, and have it documented separately.

* * *

With this we could also have the normal arithmetic operators setup to safely do the operations with the given protocol.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [February 4, 2019, 9:38pm UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/14 "2019-02-04T21:38:53Z")

</div>

Open RFC in this area:

> <https://github.com/rust-lang/rfcs/pull/2484>

I’ve been meaning to try and propose a subset of that to avoid the floating point questions, so just

```rust
trait IntegerFrom<T> {
    fn wrapping_from(_: T) -> Self;
    fn saturating_from(_: T) -> Self;
    fn checked_from(_: T) -> Option<Self>;
}
trait IntegerInto<T> {
    ... I bet you know ...
}

```

Aping the naming of all the inherent methods. (And yes, `checked_from` is just `try_from().ok()`, but I’d still have it there to follow the pattern.)

I really want this so that, like we have with `from`, we can propose clearer-intent method calls instead of `as` – especially `as _`.

---

<div class="post-metadata">

**Author:** ![Tom-Phinney](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tom-phinney/32/3299_2.png) [@Tom-Phinney](https://internals.rust-lang.org/u/Tom-Phinney)\
**Post date:** [February 4, 2019, 10:03pm UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/15 "2019-02-04T22:03:48Z")

</div>

I don’t mind using my own traits until consensus stabilizes, but I really don’t like using `fn` names that will differ from those of the eventual standardized trait. Can we get past the bikeshed naming phase and decide on the various `fn` names now, particular for those `fn`s usable with method syntax?

---

<div class="post-metadata">

**Author:** ![fintelia](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/fintelia/32/3558_2.png) [@fintelia](https://internals.rust-lang.org/u/fintelia)\
**Post date:** [February 5, 2019, 2:13am UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/16 "2019-02-05T02:13:03Z")

</div>

I’d really like to see more focus on reducing the amount of conversions necessary at all. Most of the time I know that the conversion I’m doing should never fail, but I still have to pick from among a whole bunch of different options. Typically I’m just dealing with small positive integers but still have to go through the motions of converting them between u32, u64, usize and sometimes even i64 all because different functions/libraries have different requirements.

One example where this is really all pointless is when indexing a vector. There’s no reason why I shouldn’t be able to use any unsigned integer type: there already has to be a bounds check, why should I need to convert to usize first?

---

<div class="post-metadata">

**Author:** ![canndrew](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/canndrew/32/1676_2.png) [@canndrew](https://internals.rust-lang.org/u/canndrew)\
**Post date:** [February 5, 2019, 2:45am UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/17 "2019-02-05T02:45:18Z")

</div>

I don’t think we need even more traits. I almost always know the exact integer types I’m dealing with and don’t need the genericness of a trait, I just need a way to convert from one integer type to the other concisely and descriptively.

`TryFromLossy` in particular just looks _waay_ too vague: “convert something into something else in a way that might lose information and could also fail”. The entire point of traits is to act as bounds on generic types. Why would I ever write `<T: TryFromLossy<Foo>>` without knowing anything about the nature of the conversion, why it could fail, or the implications of the lossyness? If you’re only ever calling your trait methods with concrete, non-generic types, then there’s no reason whatsoever to be using a trait at all. Your code would be clearer and more flexbile if you turned all the trait impls into inherent impls. In the case of `TryFromLossy` that clarity and flexibility means having method names that describe the kind of conversion being performed, and being able to have multiple different methods for different kinds of lossy-and-possibly-failing conversions.

Why are people averse to adding more inherent methods?

---

<div class="post-metadata">

**Author:** ![canndrew](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/canndrew/32/1676_2.png) [@canndrew](https://internals.rust-lang.org/u/canndrew)\
**Post date:** [February 5, 2019, 3:08am UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/18 "2019-02-05T03:08:59Z")

</div>

@bascule

I’m aware I can already perform most these conversions with `from` and friends. My gripe is that I’m often writing code with lots of fiddly little integer conversions, and compared to `.to_u16()`:

- `u16::from(x)` can’t be written as a method call
- `.into()` doesn’t say what it’s converting into
- `.into::<u16>()` is longer and uglier

I’m aware that most these inherent methods would be technically redundant, but I don’t think that matters and I certainly don’t think it’s more idiomatic to use a trait method where there are no generic types involved.

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [February 5, 2019, 3:22am UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/19 "2019-02-05T03:22:39Z")

</div>

> [@canndrew](#):
>
> My gripe is that I’m often writing code with lots of fiddly little integer conversions

Me too. Specifically I do cryptography, where I often want different semantics (truncation/overflow/wrapping/checked) for different circumstances.

> [@](#):
>
> ...compared to `.to_u16()`, `u16::from(x)` can’t be written as a method call

...but `into()` can...

> [@](#):
>
> `.into()` doesn’t say what it’s converting into

...so add an explicit type annotation if that makes you feel better?

> [@](#):
>
> `.into::<u16>()` is longer and uglier

...so use a type annotation instead of the turbofish?

As someone who cares deeply about language aesthetics, these seem like extremely minor syntactic nits which do not justify adding 310(!!!) new methods to the language which both duplicate and are incompatible with existing functionality, and invent a separate, parallel, bespoke language of method names instead of modeling the same concepts with types and traits.

Adding a small number of traits and/or trait impls which can interoperate with the existing types like [Wrapping](https://doc.rust-lang.org/std/num/struct.Wrapping.html) would make an awful lot more sense to me.

---

<div class="post-metadata">

**Author:** ![kennytm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kennytm/32/161_2.png) [@kennytm](https://internals.rust-lang.org/u/kennytm)\
**Post date:** [February 5, 2019, 6:12am UTC](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355/20 "2019-02-05T06:12:49Z")

</div>

> [@canndrew](#):
>
> `.into::<u16>()` is longer and uglier

Note that `x.into::<u16>()` is not a valid spelling (`fn into()` itself doesn't have generic parameters so you can't turbofish it). You need to write one of

```rust
let y: u16 = x.into();
// or
let y = Into::<u16>::into(x);

```

If RFC 2522 (type ascription) is accepted this would be written as

```rust
let y = x.into(): u16;
// vs.
let y = x.to_u16();

```

[Next page](https://internals.rust-lang.org/t/proposal-integer-conversion-methods/9355.md?page=2)
