This works because there can only be one implementation of Testable for any given type, and so X::T is fully determined for any given type X. This, in turn, means that the associated type T needs to be a fully-specified type; for references, that include a lifetime annotation.
Consider what would happen if the lifetime were unknown. How is the compiler supposed to know what lifetime parameter it should substitute? Since the associated type in itself isn't constrained in any way, there is no way for the compiler to infer the lifetime in the way it could if the type were actually used in a piece of code.
For example, what is the following piece of code supposed to mean?
trait GetValue {
type T;
fn get_value(&self) -> T;
}
struct Foo {
string: String
}
impl GetValue for Foo {
type T = &str;
fn get_value(&self) -> Self::T {
&self.string
}
}
fn main() {
let string: &'static str = Foo.get_value();
}
If there are no lifetime annotations, then how is the compiler supposed to know that the code above is invalid? There's nothing that would tell it that the returned string reference is tied to the lifetime of self or that it's otherwise not valid for the 'static lifetime.
Your confusion might be that you think that Rust generics are like C macros or C++ templates. They aren't. When you write an associated type, the compiler doesn't, can't, simply copy-paste its definition syntactically at the use site. (That would be disastrous, because it would change the meaning of the trait based on the interaction of lifetime elision and the concrete trait definition/impl for each specific type). Thus, the following declarations aren't equivalent:
impl Foo {
// desugars to: fn get_value<'a>(&'a self) -> &'a str
fn get_value(&self) -> &str { ... }
}
impl GetValue for Foo {
type T = &'b str; // NB: 'b has to come from somewhere, too!
// desugars to fn get_value<'a>(&'a self) -> &'b str;
fn get_value(&self) -> Self::T { ... }
}