Taking a range as a struct field

There are multiple Range types. Some Range types implement Iterator. I want to take all Range types that implement Iterator as a struct field.

This is my approach:

pub trait RangeBoundsExt<T: PartialOrd<T>>: Iterator<Item = T> {
    // some methods
}

impl<T: PartialOrd<T>> RangeBoundsExt<T> for std::ops::Range<T> {}

impl<T: PartialOrd<T>> RangeBoundsExt<T> for std::ops::RangeFrom<T> {}

impl<T: PartialOrd<T>> RangeBoundsExt<T> for std::ops::RangeInclusive<T> {}

pub struct Foo<T> {
    range: Box<dyn RangeBoundsExt<T>>
}

Playground

But I am getting this error:

  Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `T: std::iter::Step` is not satisfied
 --> src/lib.rs:7:24
  |
7 | impl<T: PartialOrd<T>> RangeBoundsExt<T> for std::ops::Range<T> {}
  |                        ^^^^^^^^^^^^^^^^^ the trait `std::iter::Step` is not implemented for `T`
  |
  = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::ops::Range<T>`
help: consider further restricting this bound
  |
7 | impl<T: PartialOrd<T> + std::iter::Step> RangeBoundsExt<T> for std::ops::Range<T> {}
  |                       ^^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `T: std::iter::Step` is not satisfied
 --> src/lib.rs:9:24
  |
9 | impl<T: PartialOrd<T>> RangeBoundsExt<T> for std::ops::RangeFrom<T> {}
  |                        ^^^^^^^^^^^^^^^^^ the trait `std::iter::Step` is not implemented for `T`
  |
  = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::ops::RangeFrom<T>`
help: consider further restricting this bound
  |
9 | impl<T: PartialOrd<T> + std::iter::Step> RangeBoundsExt<T> for std::ops::RangeFrom<T> {}
  |                       ^^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `T: std::iter::Step` is not satisfied
  --> src/lib.rs:11:24
   |
11 | impl<T: PartialOrd<T>> RangeBoundsExt<T> for std::ops::RangeInclusive<T> {}
   |                        ^^^^^^^^^^^^^^^^^ the trait `std::iter::Step` is not implemented for `T`
   |
   = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::ops::RangeInclusive<T>`
help: consider further restricting this bound
   |
11 | impl<T: PartialOrd<T> + std::iter::Step> RangeBoundsExt<T> for std::ops::RangeInclusive<T> {}
   |                       ^^^^^^^^^^^^^^^^^

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.

Upvotes: 1

Views: 1029

Answers (1)

Aplet123
Aplet123

Reputation: 35512

Range does not guarantee an Iterator implementation. It only provides one if the type implements Step. Likewise, RangeTo does not guarantee a lack of an Iterator implementation. It simply just doesn't provide one by default. To fix your error, you simply have to require that there is an iterator definition for the range:

// note the additional 'where' requirement
impl<T: PartialOrd<T>> RangeBoundsExt<T> for std::ops::Range<T> where
    std::ops::Range<T>: Iterator<Item = T>
{
}

impl<T: PartialOrd<T>> RangeBoundsExt<T> for std::ops::RangeFrom<T> where
    std::ops::RangeFrom<T>: Iterator<Item = T>
{
}

impl<T: PartialOrd<T>> RangeBoundsExt<T> for std::ops::RangeInclusive<T> where
    std::ops::RangeInclusive<T>: Iterator<Item = T>
{
}

Upvotes: 1

Related Questions