Closed
Description
I tried this code:
fn main() {
let mut range = 0..=0;
assert!(!range.is_empty());
assert!(range.contains(&0));
range.next();
assert!(range.is_empty());
assert!(!range.contains(&0));
}
I expected to see this happen: all assertions pass.
Instead, this happened: the last assertion fails.
Meta
The behavior is the same across stable 1.47.0
, 1.48.0-beta.2
, and 1.49.0-nightly (2020-10-13 adef9da30f1ecbfeb813)
.
Analysis
The implementation of is_empty
includes a check for the exhausted flag:
pub fn is_empty(&self) -> bool {
self.exhausted || !(self.start <= self.end)
}
But contains
only looks at the raw bounds:
pub fn contains<U>(&self, item: &U) -> bool
where
Idx: PartialOrd<U>,
U: ?Sized + PartialOrd<Idx>,
{
<Self as RangeBounds<Idx>>::contains(self, item)
}
It would be easy to insert !self.exhausted && ...
in there, as long as we're OK with the behavior change, which I consider a bug fix. I think the exhausted state of start/end is unspecified, so nobody should be depending on contains
being true
then.