#252 Jul 11, 2026

252. Wrapping<T> — Modular Arithmetic Without the .wrapping_add() Noise

Hash functions, checksums, and PRNGs want arithmetic mod 2^n — but writing .wrapping_mul() on every single operation buries the math. std::num::Wrapping<T> puts the semantics in the type so you can use plain operators again.

Method-call soup

In wrap-heavy code every operation needs the method form, or debug builds panic on overflow:

1
2
3
4
5
6
7
8
fn fnv1a(data: &[u8]) -> u32 {
    let mut h: u32 = 0x811c9dc5;
    for &b in data {
        h ^= b as u32;
        h = h.wrapping_mul(0x01000193);
    }
    h
}

One call is fine. But real hash/PRNG code chains them — x.wrapping_mul(a).wrapping_add(c) — and the actual formula disappears under the method names. Forget one and a debug build panics while release silently wraps.

Wrapping moves the choice into the type

Wrap the values once; every operator on them wraps from then on:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
use std::num::Wrapping;

fn fnv1a(data: &[u8]) -> u32 {
    let mut h = Wrapping(0x811c9dc5_u32);
    for &b in data {
        h ^= Wrapping(b as u32);
        h *= Wrapping(0x01000193);
    }
    h.0
}

*, +, -, <<, the assign forms, even unary - — all defined to wrap, in every build profile. .0 unwraps back to the plain integer at the boundary.

1
2
3
4
5
use std::num::Wrapping;

let x = Wrapping(u32::MAX);
assert_eq!(x + Wrapping(1), Wrapping(0));
assert_eq!(-Wrapping(1_u32), Wrapping(u32::MAX));

Declare intent once, not per call

The win is the same one Saturating<T> gives you (bite 167): overflow behavior is a property of the data, declared once, instead of a per-callsite decision you can fumble. The type keeps you honest, too — you can’t accidentally mix a wrapping value into checked arithmetic without an explicit .0.

Stable since Rust 1.0, Copy, zero-cost: Wrapping<u32> compiles to exactly the same instructions as the wrapping_* calls. If a function is more math than method names, wrap the inputs and let the operators speak.

← Previous 251. include_str! — Ship the File Inside the Binary, Skip the Runtime Read Next → 253. overflowing_add — Wrap, But Know It Happened