Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Let me takes this opportunity to explain that among the many contraints of rust, it is the undertalked one about the absurd no cast promotion from smaller integer (e.g. a char) to a bigger integer that made me quit and save my sanity. Having to make explicit casts a dozen times per functions for basic manipulations of numbers on a grid (and the index type mismatch) is an insult to the developer intelligence. It seems some people are resilient and are able to write nonsensical parts of code repeatedly but for me, I can't tolerate it.


I don’t mind a few “as usize” casts because usually you can cast once and be done with it. But the cast that kills me is this one:

How do you add an unsigned and a signed number together in rust, in a way which is fast (no branches in release mode), correct and which panics in debug mode in the right places (if the addition over- or under-flows)? Nearly a year in to rust and I’m still stumped!


https://rust.godbolt.org/z/e377o5148 is the first thing I thought of.

You didn't specify sizes, or if you wanted the result to be signed or unsigned, but "assume two's compliment wrapping in release and panic in debug on over/underflow" is the default behavior of +.


That fails the "panics in debug mode in the right places" requirement:

https://play.rust-lang.org/?version=stable&mode=debug&editio...


Oh duh, yeah, my bad. I was tweaking stuff around and lost that property. And seems like TryInto doesn't compile away entirely. Boo.

You can write your own debug_assert! though: https://play.rust-lang.org/?version=stable&mode=debug&editio...

not as nice, but it does work. If you were doing this a lot you could macro it up, impl as a method on all the various types you want... a pain, but it is possible.


Ah. I should have specified - I want to do this with usize / isize so the trick of using a larger integer type wouldn’t work reliably. I can use wrapping_add, but how do you detect overflow in a debug_assert statement?


So, I'm kind of surprised, but using u128 seems to do the trick: https://rust.godbolt.org/z/G63d7qoTW

I was kinda worried the release case would end up being worse, but it seems okay to me. Does that work for you?

> how do you detect overflow in a debug_assert statement?

compare to usize::MAX cast up to the larger number.


Huh! I was expecting adding u128 integers to be slower because of the cast; but it looks like llvm is (correctly) realising the upcast + downcast has no effect and replacing it with a single u64 add in release mode.

It also will happily vectorize and all the rest:

https://rust.godbolt.org/z/hn888ezj4

I want to do some additional testing to check if it also optimizes correctly for wasm and in 32 bit contexts, but generally I'm shocked that works so well. Thanks!


Right? LLVM feels like magic sometimes. You're welcome! And yeah it's certainly a bit non-obvious.


Considering all the type casting bugs prevalent in other languages, I would have more trust in the compiler than programmers at this point. You can always pick javascript of course, which happily returns you what ever it feels like. Frankly this explicit casting makes the next developer's life easier.


completely off topic, a smaller type to a larger type can never be an issue.


When the invisible conversion happens changes the end result. It can still be very tricky.


E.g on function parameters. It's always pass by copy, there can't be an issue.




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: