struct Struct {}
trait Trait {}
impl Trait for &Struct{}
fn read<T: Trait>(s: T) {}
fn write<T: Trait>(s: T) {}
fn main() {
let s = Struct{};
read(&s);
write(&s);
}
But if I can't figure out how to call read(s) and write(s) from a function which itself takes an s: T:
struct Struct {}
trait Trait {}
impl Trait for &Struct{}
fn read<T: Trait>(s: T) {}
fn write<T: Trait>(s: T) {}
fn process<T: Trait>(s: T) {
read(s); //can't use s as this will move, but can't use &s either
write(s);
}
fn main() {
let s = Struct{};
process(&s);
}
I'm guessing that by going through process, the compiler only knows that s: T, whereas before it knew that read and write were getting a &Struct. Is this right? And if so, what's the best way to fix it?
The main question is, what's the intended behavior? For example, if you know in advance that Trait will only ever be implemented on shared references, you can add a Copy bound to it, since shared references are always Copy:
struct Struct {}
// this change
trait Trait: Copy {}
impl Trait for &Struct {}
fn read<T: Trait>(s: T) {}
fn write<T: Trait>(s: T) {}
fn process<T: Trait>(s: T) {
read(s); // `s` is `Copy` due to trait bound, so it's copied and not moved
write(s); // and it is available here
}
fn main() {
let s = Struct {};
process(&s);
}
And the third possibility is that read does need the ownership, but does not need to really consume the value - it this case, you can modify its signature to return the thing it got:
fn read<T: Trait>(s: T) -> T { s }
fn write<T: Trait>(s: T) {}
fn process<T: Trait + Clone>(s: T) {
let s = read(s);
write(s);
}
Implement trait over reference is not a common pattern but sometimes useful. If it's not an intentional choice, it would be more idiomatic to change trait methods to take &self instead of self, and pass s: &T as suggested. If it's intentional but you know within the fn process the T is a reference actually, you can add T: Trait + Copy bound to tell the compiler the s can be used(copied) multiple times.