2

How can I keep ownership of a value after passing it to a function that takes a impl Trait as a parameter? I've tried both passing the parameter as a reference and without the & but none of them worked.

trait Noise{
    fn make_noise(&self);
    fn call_by_name(&self);
}

struct Person {
    name: String,
}

impl Noise for Person{
    fn make_noise(&self){
        println!("Hello");
    }

    fn call_by_name(&self) {
        println!("Hey, {:?}, how are you doing?", self.name)
    }
}

fn talk(noisy: impl Noise){
    noisy.make_noise();
}

fn main() {
    let john_person = Person { name: String::from("John") };
    talk(john_person); 
    john_person.call_by_name(); // ERROR WHEN CALLING THE FUNCTION.
}
kmdreko
  • 42,554
  • 6
  • 57
  • 106
EscFox
  • 23
  • 3

1 Answers1

3

You should make fn talk take trait object by reference rather than by value:

trait Noise {
    fn make_noise(&self);
    fn call_by_name(&self);
}

struct Person {
    name: String,
}

impl Noise for Person {
    fn make_noise(&self) {
        println!("Hello");
    }

    fn call_by_name(&self) {
        println!("Hey, {:?}, how are you doing?", self.name)
    }
}

fn talk(noisy: &impl Noise) {  // <- used &impl Noise
    noisy.make_noise();
}

fn main() {
    let john_person = Person {
        name: String::from("John"),
    };
    talk(&john_person);           // call by reference, not move
    john_person.call_by_name();
}

Otherwise, john_person is moved to function talk. That means you can not access it anymore.

If you pass it by reference, it is borrowed until the end of function.

  • The answer is good, but there is a bit of a wording issue. In Rust, everything is passed by value, even if what you are passing is a reference. So, instead of saying "passing by reference" (which means something else), you can just say "passing a reference". – jthulhu Dec 05 '22 at 07:36
  • 1
    @jthulhu I don't get why do we need to classify everything as pass by value. Of course if you are passing the reference, you are copying the reference and that is the case in every language I can think of. But that does not make it everything pass by value, since it is a conceptual thing that helps you understand and differentiate between copying the whole struct as opposed to copying the address of struct. I heart some people call Java is always pass-by-value with similar reasoning but IMO that does not make much sense and does not really help. – Özgür Murat Sağdıçoğlu Dec 05 '22 at 08:38