Why are there no trait bound for `T` on `Saturating<T>` and `Wrapping<T>`?

The following code can be compiled because there are no trait bound for T:

let _ = mem::size_of::<Saturating<bool>>();
let _ = mem::size_of::<Wrapping<char>>();

Note that impl Saturating<bool> and impl Wrapping<char> are not implemented so these are largely meaningless.

On the other hand, the following code cannot be compiled because it does not satisfy the trait bound ZeroablePrimitive:

let _ = mem::size_of::<NonZero<f64>>();

Why are there no trait bound which restrict a value ​​to numeric types for T on Saturating<T> and Wrapping<T>?

NonZero uses compiler magic #[rustc_nonnull_optimization_guaranteed] to let the zero value to be unused. This affects type layouts and could cause problems if you wrapped a type that needs to use zero values.

Saturating is purely a transparent wrapper. In Rust, structs usually don't have any type bounds unless necessary, because these bounds need to be repeated in many places. Bounds on impl are usually sufficient and don't spread to every use of the struct.

7 Likes