# On Casts and Checked-Overflow

**URL:** <https://internals.rust-lang.org/t/on-casts-and-checked-overflow/1710>\
**Category:** bikeshed (deprecated)\
**Created:** [March 12, 2015, 4:42pm UTC](https://internals.rust-lang.org/t/on-casts-and-checked-overflow/1710 "2015-03-12T16:42:16Z")\
**Posts on this page:** 1\
**Showing post:** 15

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [March 18, 2015, 1:45pm UTC](https://internals.rust-lang.org/t/on-casts-and-checked-overflow/1710/15 "2015-03-18T13:45:55Z")

</div>

I initially leaned towards the strict interpretation as well, but after the discussion at the meeting, I am starting to feel conflicted. The major points made there were:

1. Bitcasting is far more common in practice (unsubstantiated, but see below), so this could be annoying.
2. Subtle rules may be more confusing than helpful. Probably `as` should either be infallible (as today) or strict.

I tried to do a brief survey of rustc to uncover the kinds of places we use `as`. This is not a super thorough survey and in particular I didn’t count instances (and we’d want to look at more than `rustc`, ideally). But in any case here is a listing of what I saw. These are reasons to use `as`, somewhat sorted by frequency of occurrence (but like I said, I didn’t count).

1. To convert between `usize` and `u32`, usually for indices whose length is believed to be bounded to `u32`. In this case, I think that the “width oriented” approach is probably best. That is, you’d prefer a panic if converting from `usize` to `u32` throws away some high-order bits when debugging.
2. To convert from `u32` to `i32`, for example in trans when converting offsets for use with a GEP statement. Here, strict is preferred.
3. To upcast, in which case any interpretation is fine.
4. Constant evaluation sometimes goes back and forth between i64/u64. I think in this case strict is preferred.
5. To convert from `i32` to `u32` in binary encoding. Here, width, loose, or truncating is preferred.
6. To select individual bytes (`(x >> 16) as u8`). Truncating is preferred.

One thing I did _not_ see was a converting from `i32` to `u32` where we wanted to ensure that the value was not negative at that time. This probably does come up, but I don’t think I saw a case of that.

Anyway, here are some further concerns:

1. If we keep `as` as it is, which I think is reasonable, then it does raise the question of whether we will offer stricter versions. If so, will they be tied to methods? It is perhaps inconsistent to say that `+` is strict by default but `as` uses a method. But there is clearly utility for at least _some_ kind of checking to ensure we don’t throw away bits.
2. If we convert `as`, it may be annoying.

This is connected to an existing mildly open question on how to make it more ergonomic to use wrapping operations. I am personally leaning towards something like C#'s checked blocks. Basically allowing you to say that you want wrapping semantics within a particular fn or block (but not module, I’d prefer to keep the annotation local). This would cause all lexically enclosed `+` operations to map to a `WrappingAdd` trait – and would also affect primitive operations. I’ve been meaning to write a separate post sketching this out. Anyway, having a convenient way to switch the interpretation of `as` may make the default stricter interpretation more appealing, though I feel like `as` is a bit different than `+` in that a series of wrapping operations often come together, but `as` conversions are frequently isolated (citation needed).

Overall, I feel conflicted! Usually when I feel conflicted, I lean towards the more conservative option, which suggests keeping `as` as infallible. Perhaps data is the key to making this decision.

---

_[View the full topic](https://internals.rust-lang.org/t/on-casts-and-checked-overflow/1710)._
