It is not strictly true that "items from traits can only be used if the trait is in scope"

take this simple program.

use std::io;

fn main() {
    <io::Stdout as io::Write>::write(&mut io::stdout(), b"hello").unwrap();
}

this form is actually useful in niche situations, such as if you already have a different Write trait in scope.

I think even just this will work

use std::io;

fn main() {
    io::Write::write(&mut io::stdout(), b"hello").unwrap();
}
2 Likes

indeed it does, the longer form isn't required for items callable as methods since rust can look at the type of the self argument to know what definition to dispatch on.

io::Write this expression brings the trait into the scope for the expression.

it does not. io::Write::write(&mut io::stdout(), { io::stdout().write(b"foo"); b"bar" }) will fail to compile due to Write not being in scope.

1 Like

I meant more in the expression that evaluates to which function to call, not inside the whole expression. to me the usage OP showed still counts as putting the trait in-scope