The syntax <Type as Trait>::Item is the fully-qualified syntax used to explicitly refer to an associated Item of a Trait on a Type. This is not terribly common to write out yourself, but you may need to if there is an ambiguity in what Item means for a Type.
Consider this modified example using Self::Hash where the current trait and supertrait both have a Hash associated type:
trait Core<Item> {
type Hash;
}
trait Queue<Item>: Core<Item> {
type Hash;
fn validate(
&self,
hash: Self::Hash
) -> bool;
}
error[E0221]: ambiguous associated type `Hash` in bounds of `Self`
--> src/lib.rs:9:15
|
2 | type Hash;
| ---------- ambiguous `Hash` from `Core<Item>`
...
6 | type Hash;
| ---------- ambiguous `Hash` from `Queue<Item>`
...
9 | hash: Self::Hash
| ^^^^^^^^^^ ambiguous associated type `Hash`
|
help: use fully qualified syntax to disambiguate
|
9 | hash: <Self as Queue<Item>>::Hash
| ~~~~~~~~~~~~~~~~~~~~~~~
help: use fully qualified syntax to disambiguate
|
9 | hash: <Self as Core<Item>>::Hash
| ~~~~~~~~~~~~~~~~~~~~~~
In this case, it is ambiguous what Self::Hash means, so the compiler requires that you fully-qualify what trait to use.
You may also see this syntax used in generated documentation. As an example, take the str::rmatches function. The original signature is written like so:
pub fn rmatches<'a, P>(&'a self, pat: P) -> RMatches<'a, P>
where
P: Pattern<'a, Searcher: ReverseSearcher<'a>>
But it shows up in the documentation like this:
pub fn rmatches<'a, P>(&'a self, pat: P) -> RMatches<'a, P>
where
P: Pattern<'a>,
<P as Pattern<'a>>::Searcher: ReverseSearcher<'a>,
Not exactly sure why this is; perhaps the designers thought disambiguation was a good idea by default, it was simpler this way, or if it was just better for generating links. Either way, its something you'll come across so its better to learn it and not get confused later.
In your particular example, I don't see why Item::Hash would need to be qualified, but perhaps there is more at play than what is shown, could simply be a fluke, or maybe its just an artifact caused by a previous version of the code.
Also, incidentally, does the syntax : Core<Item> mean that the Queue trait requires all implementors to also implement the Core trait? Or does it mean something else? And why would you do that? Who cares about Core? If somebody needs the Core trait, can't they just say so?
Yes, this is constraining the Queue<Item> trait that any implementation must also implement Core<Item>. Core<Item> is also called a supertrait with this usage.
This snippet is a bit too reduced to definitively say why that would be desired, but consider something like DoubleEndedIterator which has Iterator as a supertrait since it makes no sense for something to be a double-ended iterator but not be an iterator. So its often used in similar scenarios where it makes no sense to use use the subtrait independently.
But your instincts are good; if a trait can reasonably be used without the supertrait, then it shouldn't.