On page 297 of Programming Rust you can find the following
impl HashMap<K, V> where K: Eq + Hash
{
fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
where K: Borrow<Q>,
Q: Eq + Hash
}
I've seen this before where ?Sized
is written by itself, and the rest of trait bounds are on a different line? Is this a convention? As I understand it, the above is effectively the same as the following?
impl HashMap<K, V> where K: Eq + Hash
{
fn get<Q>(&self, key: &Q) -> Option<&V>
where K: Borrow<Q>,
Q: Eq + Hash + ?Sized
}
Why is ?Sized
split off? You can see this in a similar example on page 295,
...
where T: AsRef<U>
T: ?Sized, U: ?Sized
...
That is pure convention, and it is not set in stone, but it does have some merit.
The special syntax ?Sized
lets the compiler remove this bound if it is not appropriate (when monomorphizing). As such, it does make sense, somewhat, to split it and put it in the generic definition rather than the where
clause for ease of readability and to separate the fact that, unlike the others, it isn't a strict, rigid marker.
Some libraries out there go even further and list all the markers in the generic definition, and all traits in the where
clause.
As stated in the comments and found by @PeterHall through the commit log, prior to rust 1.15, ?Sized
was only available as a trait requirement in the type definition. This PR changed this to the behavior we have today.