I tried this code: [playground]
#![feature(iter_advance_by)]
fn main() {
_ = (-128i8..127).advance_by(200);
}
I expected to see this happen: No UB.
Instead, this happened: UB, confirmed by Miri. Step::forward_unchecked(-128i8, 200usize) is called, which does (-128i8).unchecked_add(200usize as i8), or (-128i8).unchecked_add(-56i8).
The implementation of advance_by is correct here, and Step::forward_unchecked(-128i8, 200usize) should be safe to call. The implementation that does a wrapping as cast from usize to iN before doing the unchecked math is the incorrect code here. Signed integers should switch to just using wrapping or unsigned math, whichever gets better codegen out of LLVM. We do have wrapping_add_unsigned and checked_add_unsigned methods now, but no unchecked_add_unsigned.
Meta
rustc --version:
rustc 1.78.0-nightly (2024-03-12 a165f1f65015b1bd4afd)
I tried this code: [playground]
I expected to see this happen: No UB.
Instead, this happened: UB, confirmed by Miri.
Step::forward_unchecked(-128i8, 200usize)is called, which does(-128i8).unchecked_add(200usize as i8), or(-128i8).unchecked_add(-56i8).The implementation of
advance_byis correct here, andStep::forward_unchecked(-128i8, 200usize)should be safe to call. The implementation that does a wrappingascast fromusizetoiNbefore doing the unchecked math is the incorrect code here. Signed integers should switch to just using wrapping or unsigned math, whichever gets better codegen out of LLVM. We do havewrapping_add_unsignedandchecked_add_unsignedmethods now, but nounchecked_add_unsigned.Meta
rustc --version: