zhongjn
zhongjn

Reputation: 11

Why impl RangeBounds<T> for Range<&T> requires T to be sized?

https://doc.rust-lang.org/src/core/ops/range.rs.html#979-986

impl<T> RangeBounds<T> for Range<&T> {
    fn start_bound(&self) -> Bound<&T> {
        Included(self.start)
    }
    fn end_bound(&self) -> Bound<&T> {
        Excluded(self.end)
    }
}

As you can see, T is not marked with ?Sized, which is preventing me from passing a Range<&[u8]> into an argument requires impl RangeBounds<[u8]>.

Are there some design considerations behind it? If this is intended, which is the proper way to pass a range of [u8]?

Upvotes: 1

Views: 1299

Answers (1)

trent
trent

Reputation: 28025

It's rather unfortunate, but adding the T: ?Sized bound breaks type inference in code like btreemap.range("from".."to") because the compiler can't choose between T = str and T = &str, both of which satisfy the bounds on range.

Some discussion of this has taken place on PR #64327. As far as I know there are no plans to relax the bounds on these impls in the future.

Instead of a Range<T>, you can use a tuple of Bound<T>s; for example, instead of takes_range("from".."to"), you can write the following instead:

use std::ops::Bound;
takes_range((Bound::Included("from"), Bound::Excluded("to"))

This will work because (Bound<&T>, Bound<&T>) does implement RangeBounds<T> even when T is !Sized.

Upvotes: 2

Related Questions