impl Trait isn't a type: semantically it means "some concrete type that happens to implement Trait". In argument position, as in your original say_hello_twice function, it is just syntactic sugar for a generic—the desugared equivalent being as follows:
fn say_hello_twice<T: SayHello>(this: T) -> String { ... }
It isn't permitted in Rust, so it doesn't actually have any defined meaning, but what might you have intended by using impl Trait as the nominal type of an implementation block? By analogy to the above, perhaps it would be something like this:
impl<T: SayHello> T { ... }
However, this isn't allowed either: such an implementation would apply to all types that implement SayHello: including any that are defined in downstream crates—and inherent implementations can only be defined in the same crate as the type itself, to prevent name conflicts/ambiguity.
If you want instead to define a method that is available on all implementations of SayHello, you have a few choices:
Define it in the SayHello trait, with a default implementation:
trait SayHello {
fn say_hello(self) -> String;
fn say_hello_twice(self) -> String {
let said_hello = self.say_hello();
said_hello.clone() + " " + &said_hello
}
}
This has the advantage that it is just a normal, readily-available method on SayHello. However, implementors can choose to override the definition—which may or may not be desirable.
Define an extension trait that is blanket implemented:
trait SayHelloTwice {
fn say_hello_twice(self) -> String;
}
impl<T: SayHello> SayHelloTwice for T {
fn say_hello_twice(self) -> String {
let said_hello = self.say_hello();
said_hello.clone() + " " + &said_hello
}
}
This has the advantage that implementations of SayHello cannot provide any other definition of SayHelloTwice::say_hello_twice. However, users must bring SayHelloTwice into scope—which is slightly less ergonomic.
It is possible to use dyn Trait as the nominal type of an inherent implementation block (from within the crate that defines Trait):
impl dyn SayHello {
fn say_hello_twice(&self) -> String {
let said_hello = self.say_hello_borrowed();
said_hello.clone() + " " + &said_hello
}
}
However, users would have to be working with trait objects (&dyn SayHello, Box<dyn SayHello>, etc) which involves runtime indirection and may not be what you are after; moreover, because dyn Trait is unsized, you cannot take self by value (hence using &self and say_hello_borrowed above).