Has anyone else needed to conditionally return different types of ranges?

I’m writing a function that returns multiple types of ranges (std::ops::Range, std::ops::RangeFull etc.) At first I tried returning impl std::ops::RangeBounds<T> but that doesn’t work. After doing some reading I understand why.

I know I could use a Box<dyn RangeBounds<T>>, but in my particular case the ranges are going to be used right away and I’m writing this function to speed up a search, (after profiling!) so using the stack seems preferable. This answer to a stackoverflow question about returning different kinds of types suggests creating an enum that implements the trait in question. So I can go ahead and do that for something like this:

enum AnyRange<T> {
    Range(Range<T>),
    RangeFrom(RangeFrom<T>),
    RangeFull,
    RangeInclusive(RangeInclusive<T>),
    RangeTo(RangeTo<T>),
    RangeToInclusive(RangeToInclusive<T>),
}

But, I’m left wondering if anyone else has run into a reason to return different kinds of ranges before. And if so, I’m wondering whether it would make sense to include something like AnyRange in the standard library. Although I suppose it should probably be opaque to leave the door open for a future exclusive lower-bound syntax.

The standard library is very conservative, because once something is added, we basically have to support it forever. (Not literally, but removing things is hard.)

I would use the enum you suggest. If you think it might be generally useful, the sort of thing that might eventually make it into the standard library, post it as a standalone crate and see if people use it.

How about using (Bound<T>, Bound<T>)? That even implements RangeBounds<T>.

4 Likes

I had thought about that type but I had assumed that the trait wasn’t implemented for it. And I wanted to be able to use the syntax in tests etc. But since it is, that’s definitely less code than making my own enum!