Description
All range types except RangeInclusive
can be used in const generics:
#![feature(const_generics)]
struct A<const R: Range<usize>>;
struct B<const R: RangeTo<usize>>;
struct C<const R: RangeFrom<usize>>;
struct D<const R: RangeToInclusive<usize>>;
struct E<const R: RangeFull<usize>>;
This compiles (on nightly), while the following does not:
#![feature(const_generics)]
struct S<const R: RangeInclusive<usize>>;
This is because RangeInclusive
does not implement StructuralPartialEq
and StructuralEq
(#63438). RangeInclusive
has fields start
and end
similar to the other range types, but also has an extra field: exhausted: bool
(#68835). This was recently changed from a field is_empty: Option<bool>
. This extra field tracks state for iteration and was added to address performance issues (#45222).
The old implementation with is_empty
had semantic equality, however the new implementation with exhausted
has structural equality:
impl<Idx: PartialEq> PartialEq for RangeInclusive<Idx> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.start == other.start && self.end == other.end && self.exhausted == other.exhausted
}
}
from range.rs
I believe this means we can either manually add implementations for StructuralPartialEq
and StructuralEq
, or just derive PartialEq
and Eq
, which will allow RangeInclusive
to also be used in const generics and remove the inconsistency with other range types.