# Lossy conversion trait (\`as\`)

**URL:** <https://internals.rust-lang.org/t/lossy-conversion-trait-as/7672>\
**Category:** libs\
**Created:** [May 30, 2018, 5:11pm UTC](https://internals.rust-lang.org/t/lossy-conversion-trait-as/7672 "2018-05-30T17:11:55Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![dhardy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhardy/32/2399_2.png) [@dhardy](https://internals.rust-lang.org/u/dhardy)\
**Post date:** [May 30, 2018, 5:11pm UTC](https://internals.rust-lang.org/t/lossy-conversion-trait-as/7672/1 "2018-05-30T17:11:55Z")

</div>

Could we have a trait over what the `as` cast does, maybe?

I want to write `fn foo<FP: From<f64>+..>(...) -> FP` with `f32` and `f64` implementations, however `f32` does not implement `From<f64>`. I don’t care if there is some loss of precision (actually, this is expected), and want to be able to write `f64` constants and use other functions with only `f64` implementations.

There are two obvious ways Rust could support this:

1. `impl From<f64> for f32` — which goes against the trend of not allowing lossy conversions, but I think _usually_ this is not a problem since lower precision is expected with `f32` and the range is still huge with explicit +/-inf.
2. A new trait for lossy conversions

Of course I can roll my own trait if this doesn’t deserve a common solution, but may be worth discussing (especially the first suggestion).

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [May 30, 2018, 5:15pm UTC](https://internals.rust-lang.org/t/lossy-conversion-trait-as/7672/2 "2018-05-30T17:15:43Z")

</div>

num-traits has [`AsPrimitive`](https://docs.rs/num-traits/0.2.4/num_traits/cast/trait.AsPrimitive.html) for this.

---

<div class="post-metadata">

**Author:** ![eugene2k](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eugene2k/32/3525_2.png) [@eugene2k](https://internals.rust-lang.org/u/eugene2k)\
**Post date:** [May 31, 2018, 9:23am UTC](https://internals.rust-lang.org/t/lossy-conversion-trait-as/7672/3 "2018-05-31T09:23:37Z")

</div>

You can also roll your own type that wraps around f32

---

<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:** [June 1, 2018, 4:13pm UTC](https://internals.rust-lang.org/t/lossy-conversion-trait-as/7672/4 "2018-06-01T16:13:59Z")

</div>

> [@dhardy](#):
>
> Could we have a trait over what the `as` cast does, maybe?

I'm strongly against one that's just "whatever `as` does", since I find it an unfortunate mess of conversions right now -- some coercions, some extensions, some truncations, ...

I _would_ like a more principled lossy trait, maybe `WrappingFrom`, but that has traditionally been the domain of `num-traits`, not `core`.

---

<div class="post-metadata">

**Author:** ![dhardy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhardy/32/2399_2.png) [@dhardy](https://internals.rust-lang.org/u/dhardy)\
**Post date:** [June 22, 2018, 10:16am UTC](https://internals.rust-lang.org/t/lossy-conversion-trait-as/7672/5 "2018-06-22T10:16:36Z")

</div>

To bring this up again from a slightly different perspective, the documentation on the `From` trait specifies:

> Simple and safe type conversions in to Self

and

> Note: this trait must not fail. If the conversion can fail, use TryFrom or a dedicated method which returns an Option or a Result\<T, E\>.

but does not mention anything about the _accuracy_ of the returned result (put another way: `i64 → f64` is "safe" but inexact).

Obviously for some uses inexact conversions are _not safe_, but one does not usually use floating-point types to represent pointers or expect them to always be exact in any case, so this point may not be relevant (at least for target types regarded as "lossy").

So **should `From` support inexact conversions**?

I'm not particularly biased either way (though eventually getting some kind of lossy conversion trait would be nice), but we need to decide because _currently SIMD types do implement lossy conversions via_ `From`, e.g. `From<u64x4> for f32x4`. (Then again, there also appear to be fallible conversions like `From<f32x4> for i8x4`, which are definitely not safe.)

---

<div class="post-metadata">

**Author:** ![dhardy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhardy/32/2399_2.png) [@dhardy](https://internals.rust-lang.org/u/dhardy)\
**Post date:** [June 22, 2018, 10:21am UTC](https://internals.rust-lang.org/t/lossy-conversion-trait-as/7672/6 "2018-06-22T10:21:45Z")

</div>

Perhaps the best answer is that `From` should not allow lossy conversions, but we should add `LossyFrom` (which also allows things like `LossyFrom<f64> for f32` which may overflow to `f32::INFINITY`).

(`WrappingFrom` isn't quite right for loss of precision conversions, as `u64 → f64`.)

Note that cases like `f64 → u64` are still not satisfied, but that's what `TryFrom` is for.

> [@scottmcm](#):
>
> I’m strongly against one that’s just “whatever `as` does”

I completely agree, it is more reminiscent of C conventions than Rust. It would be nice to make `as` redundant and eventually remove it from the language.

---

<div class="post-metadata">

**Author:** ![dhardy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhardy/32/2399_2.png) [@dhardy](https://internals.rust-lang.org/u/dhardy)\
**Post date:** [June 22, 2018, 2:45pm UTC](https://internals.rust-lang.org/t/lossy-conversion-trait-as/7672/7 "2018-06-22T14:45:24Z")

</div>

RFC: [https://github.com/rust-lang/rfcs/pull/2484](https://github.com/rust-lang/rfcs/pull/2484)

---

<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:** [June 22, 2018, 4:52pm UTC](https://internals.rust-lang.org/t/lossy-conversion-trait-as/7672/8 "2018-06-22T16:52:33Z")

</div>

> [@Lossy conversion trait (\`as\`)](https://internals.rust-lang.org/t/lossy-conversion-trait-as/7672/7):
>
> RFC: [https://github.com/rust-lang/rfcs/pull/2484](https://github.com/rust-lang/rfcs/pull/2484)

I like the idea of being more explicit about classes of conversion. This RFC enumerates five traits: `From`, `TryFrom`, `FromLossy`, `TryFromLossy`, and `TruncateFrom`. The RFC proposes to add `FromLossy` and `TryFromLossy` traits to the existing `From` and the long-awaited but not-yet-stabilized `TryFrom` traits.

The RFC does not address the fifth listed trait, `TruncateFrom`, which is the class of conversions I use the most, often to convert from a `usize` iterator index to a (usually smaller) known-size storage representation (e.g., `u8`, `u32`). I've attempted to implement this trait for the various uN -\> uM conversions, but haven't yet found a way to do so efficiently other than through the current `as` conversion.

To me the RFC will feel incomplete until it also addresses this very common lossy conversion of unsigned integers. Thus I'd like to request that those with more understanding propose a way to include this fifth trait in the RFC.

**Note** : There are other uncommon lossy conversions – iN -\> iM truncation and iN sign transmutation – listed in the RFC's Related Problems section. I see no need to address either of those at this time.

---

<div class="post-metadata">

**Author:** ![dhardy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhardy/32/2399_2.png) [@dhardy](https://internals.rust-lang.org/u/dhardy)\
**Post date:** [June 23, 2018, 7:52am UTC](https://internals.rust-lang.org/t/lossy-conversion-trait-as/7672/9 "2018-06-23T07:52:23Z")

</div>

@Tom-Phinney are you talking about checked or unchecked conversions to/from `usize`? [https://github.com/rust-lang/rust/issues/49415](https://github.com/rust-lang/rust/issues/49415) addresses checked conversion to and from `usize`/`isize`. `TruncateFrom` could support unchecked conversions to/from `usize` I _suppose_ even though many of the conversions (e.g. `usize` → `u64`) are not actually truncations (on current platforms).

I have to ask, what is the use-case? E.g. if it is serialisation of program data involving `usize` counters then probably checked conversions are more appropriate.

---

<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:** [June 23, 2018, 2:47pm UTC](https://internals.rust-lang.org/t/lossy-conversion-trait-as/7672/10 "2018-06-23T14:47:46Z")

</div>

I was not talking about conversions from `usize`, either checked or unchecked; truncation from `u64` to `u32` is probably my most frequent use case.

However, it’s easy for nominally-truncating conversions from `usize` to occur when processing modest-length slices in a loop, e.g., where the loop’s `usize` slice index of an element of interest has statically-known high-order zero bits truncated so that the index can be stored as a `u8`, `u16`, or `u32` in a field of a different replicated data structure.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:30am UTC](https://internals.rust-lang.org/t/lossy-conversion-trait-as/7672/11 "2019-03-25T08:30:20Z")

</div>

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