Open
Description
It could be nice to have std::iter::Step for the NonZeroX numbers, so in this code instead of having about 1000 unwrap:
fn main() {
use std::num::NonZeroUsize;
let nz = |x| NonZeroUsize::new(x).unwrap();
for i in 1 .. 1_000 {
println!("{:?}", nz(i));
}
}
You only need two:
fn main() {
use std::num::NonZeroUsize;
let nz = |x| NonZeroUsize::new(x).unwrap();
for i in nz(1) .. nz(1_000) {
println!("{:?}", i);
}
}
If also a const-generics-based constructor is added to stdlib then the number of run-time unwraps goes to zero (the two panics become compile-time):
fn main() {
use std::num::nonzero_usize;
for i in nonzero_usize::<1>() .. nonzero_usize::<1_000>() {
println!("{:?}", i);
}
}
A further improvement should come from const generics of arbitrary type (currently not allowed):
fn main() {
use std::num::nonzero;
for i in nonzero::<1_usize>() .. nonzero::<1_000>() {
println!("{:?}", i);
}
}
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
jonas-schievink commentedon Jun 8, 2020
There's not really a point in calling
.unwrap()
less, the optimizer will get rid of all the calls anywaysleonardo-m commentedon Jun 8, 2020
The less unwraps you have, the less you have to think (or in more reliable coding to prove) about possible ways for them to fire at run-time and ruin your execution.
leonardo-m commentedon Jan 1, 2021
I'd like also the .step_by(usize).
I think this isn't always true (I've seen such cases in my code, where the inliner wasn't able to get rid of all the unwrap calls), if you have iterators chains, like (where pred computes a division by the input argument):
The compiler is not always able (or willing) to inline everything, so predicates and other lambdas get called by values that are nonzero, but the functions lose the information about the input argument being nonzero.
But if you have a range of NonZero values the type system can't lose this information and new improvements like #79134 give you some extra performance in non-inlined functions:
jalil-salame commentedon Apr 24, 2023
This is also being discussed in the libs-team: rust-lang/libs-team#130.
SOF3 commentedon Sep 6, 2023
@leonardo-m it's reasonable that the compiler cannot optimize after you have mapped the integer, right?
leonardo-m commentedon Feb 16, 2025
Calling
nonzero::<1_usize>()
is nicer than leaving a unwrap in the code that needs inspection and that the compiler will optimize away. But currently you can't write generic functions like that, and you need specialized ones likenonzero_usize::<1>()
, that while still better than using the normal constructor + unwrap, look a bit less appealing. Now Issue #127534 seems to address the range iteration, so I leave this issue open for now just for the unwrap-less constructor.[-][ER] NonZeroX Step and better constructors[/-][+][ER] NonZero const generic constructor[/+]