In rust the (useful) trait implementations on `Range<T>` only exist for `T: Step`.
Sure you can create other `Range<T>`'s but you can't use them for anything useful. (Ok, if they are PartialOrd you still can use `contains` and `is_empty`).
The article makes it look like a lot of problems comes from rust being too generic over the range type but that's not the case (expect for contains requiring a reference, but then BigNum's are a thing too).
I.e. the only reason why you can create a `Range<Vec<Mutex<Rc<String>>>>` is because it doesn't hurt anyone to allow me to do so. But I won't be able to use that rang for anything. It won't implement `is_empty`/`contains` nor will it be Iterable. Heck it doesn't even implement `Clone`. But non of the implementations around iterability, is_empty, contains etc. get in practice any problem because of this type being valid.
Instead the mentioned problems come mainly from:
- start <= end not being enforceable at type level as a fallible range constructor would have a horrible UX.
- Range<usize> if used for indexing treating things like 5..0 as "out of bounds" while for iterating it's just an "empty" sequence (which is not nice but a very reasonable decisions generally improving usability in practice due to how the range types are normally used in rust but confusing for some less common use case).
- The person somehow being hung up on the exact definition of "out of bounds" not being clear enough defined in the function documentation of a experimental nightly API which is perma-unstable, i.e. we are basically speaking about internal (but visible) implementation details of the standard library...
In rust the (useful) trait implementations on `Range<T>` only exist for `T: Step`.
Sure you can create other `Range<T>`'s but you can't use them for anything useful. (Ok, if they are PartialOrd you still can use `contains` and `is_empty`).
The article makes it look like a lot of problems comes from rust being too generic over the range type but that's not the case (expect for contains requiring a reference, but then BigNum's are a thing too).
I.e. the only reason why you can create a `Range<Vec<Mutex<Rc<String>>>>` is because it doesn't hurt anyone to allow me to do so. But I won't be able to use that rang for anything. It won't implement `is_empty`/`contains` nor will it be Iterable. Heck it doesn't even implement `Clone`. But non of the implementations around iterability, is_empty, contains etc. get in practice any problem because of this type being valid.
Instead the mentioned problems come mainly from:
- start <= end not being enforceable at type level as a fallible range constructor would have a horrible UX.
- Range<usize> if used for indexing treating things like 5..0 as "out of bounds" while for iterating it's just an "empty" sequence (which is not nice but a very reasonable decisions generally improving usability in practice due to how the range types are normally used in rust but confusing for some less common use case).
- The person somehow being hung up on the exact definition of "out of bounds" not being clear enough defined in the function documentation of a experimental nightly API which is perma-unstable, i.e. we are basically speaking about internal (but visible) implementation details of the standard library...