# Ranged integers for performance

**URL:** <https://internals.rust-lang.org/t/ranged-integers-for-performance/17128>\
**Category:** language design\
**Created:** [August 4, 2022, 12:53pm UTC](https://internals.rust-lang.org/t/ranged-integers-for-performance/17128 "2022-08-04T12:53:53Z")\
**Posts on this page:** 1\
**Showing post:** 3

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [August 4, 2022, 1:56pm UTC](https://internals.rust-lang.org/t/ranged-integers-for-performance/17128/3 "2022-08-04T13:56:10Z")

</div>

AFAIK this has already been discussed a couple of times, but no definite design has been produced yet. See for example:

> [@More on ranged integers](https://internals.rust-lang.org/t/more-on-ranged-integers/8614):
>
> Beside ranged integrals Ada has ranged floating point value with optional precision, modular integers, and other built-in things. I think the most useful types are the integers with a range. Ada gives run-time errors if you go past the range of such specified integers, I’ve found the detailes semantics explained at page 26 here: [https://hal.inria.fr/hal-01238376/document](https://hal.inria.fr/hal-01238376/document) Signed integer types are usually defined using a range, e.g.: type Int\_10 is range 1 .. 10; Here, Int\_10 represents the …

> [@Pre-RFC: Arbitrary bit-width integers](https://internals.rust-lang.org/t/pre-rfc-arbitrary-bit-width-integers/15603/36):
>
> struct Foo; is also isomorphic to (), but is useful enough that it even has its own dedicated syntax. I think it's useful for the same kinds of generic reasons that () is useful, and for the same kinds of reasons that [\_; 0] exists as a type. For example, u0 is the perfect always-in-bounds type for indexing a [T; 0] , the same way that u8 is the perfect always-in-bounds type for indexing a [T; 256]. +1 I'd much rather have Integer\<0..10\> for indexing a [T; 10], for example. Though there m…

> <https://github.com/rust-lang/rfcs/issues/671>
>
> \<a href="https://github.com/BryanQuigley"\>\<img src="https://avatars.githubuserco…ntent.com/u/702754?v=3" align="left" width="96" height="96" hspace="10"\>\</img\>\</a\> \*\*Issue by \[BryanQuigley\](https://github.com/BryanQuigley)\*\*
> \_Saturday Dec 13, 2014 at 03:46 GMT\_
> 
> \_For earlier discussion, see https://github.com/rust-lang/rust/issues/19801\_
> 
> \_This issue was labelled with: A-an-interesting-project, E-hard in the Rust repository\_
> 
> \---
> 
> It seems like a natural extension of how variables (immutable by default, mutable if specified) are defined to allow the programmer to dictate a specific range of allowed values for an integer. If I know a value is only valid between 0-1000 the sooner I declare that the better it is for catching bugs, off by one errors, and more...  
> 
> I'm not sure what exact syntax would work, maybe:
> 
> \`\`\` rust
> let mut(0,1000) x = 0i;
> \`\`\`
> 
> x is only valid from 0-1000 inclusive.
> 
> (Apologies if this is already possible, I've been parsing the docs trying to learn Rust.)

The problems start to appear when you want to do operations on that type. If you add `1` to a `usize[.. N]` should you get a `usize[1 .. N+1]`? Or an `Option<usize[.. N]>`? Maybe just an `usize`? Keeping track of these invariants also quickly becomes quite a lot of work for the compiler and for who needs to implement the feature.

ps: Regarding your specific piece of code, it can be optimized with this weird trick:

```diff
fn permutations_array<T, const N: usize>
                     (data: &[T; N]) -> impl Iterator<Item=[&T; N]> {
    from_generator(move || {
        if N == 0 { return; }
- let mut perm = from_fn(|i| i);
- yield perm.map(|i| &data[i]); //1
+ let mut perm = from_fn(|i| &data[i]);
+ yield perm; //1

        loop {
            let mut i = N - 1;
- while perm[i - 1] >= perm[i] {
+ while perm[i - 1] as *const _ >= perm[i] as *const _ {
                i -= 1;
                if i < 1 { return; }
            }
            let mut j = N;
- while perm[j - 1] <= perm[i - 1] { j -= 1; }
+ while perm[j - 1] as *const _ <= perm[i - 1] as *const _ { j -= 1; }
            perm.swap(i - 1, j - 1);
            i += 1;
            j = N;
            perm[i - 1 .. j].reverse();
- yield perm.map(|i| &data[i]); //2
+ yield perm; //2
        }
    })
}

```

Or, alternatively, you could define something like this, limiting the `unsafe` to a very small interface (which is the very point of `unsafe`!):

```rust
mod bounded {
    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
    pub struct Bounded<const N: usize>(usize);
    
    impl<const N: usize> Bounded<N> {
        pub fn new(n: usize) -> Self {
            assert!(n < N);
            Self(n)
        }
        pub fn into_usize(&self) -> usize {
            let n = self.0;
            if !(n < N) {
                unsafe { std::hint::unreachable_unchecked() };
            }
            n
        }
    }
}

```

---

_[View the full topic](https://internals.rust-lang.org/t/ranged-integers-for-performance/17128)._
