9

I'm learning Rust and I've a question regarding how to pass a reference of a variable to a function and make a cascade call with it.

I'm facing the error indicated in the code below:

struct User {
    name: String,
    address: String
}

// Argument "user" is intentionally a reference to User struct;
//
fn func1(user: &User) {
    println!("func1: {}, {}", user.name, user.address);

    // error[E0507]: cannot move out of `*user` which is behind a shared reference
    //
    func2(*user);
}

// Argument "user" is intentionally an instance of User struct;
//
fn func2(user: User) {
    println!("func2: {}, {}", user.name, user.address);
}

fn main() {
    let user = User {
        name: String::from("George"),
        address: String::from("Main Street")
    };

    func1(&user);
}

Why can't I do that? What am I supposed to do?

I think cloning the User object is not a option. Imagine if instead of this simple structure we have a super structure that could occupy several MBytes?

Hamza Zubair
  • 1,232
  • 13
  • 21
nermind
  • 99
  • 1
  • 1
  • 4
  • because you can't move a value you don't own. "What I supposed to do?" not that, why not take both by reference or both by value ? Or the first one by value and the second one by reference. – Stargateur May 25 '20 at 03:14

1 Answers1

34

fn func1(user: &User) is a function that borrows an existing User object, promising not to modify it. fn func2(user: User) is a function that takes ownership of an object and never gives it back.

Rust is preventing you from doing something silly. Having func1 call func2 is like promising me you'll just borrow my class notes for a quick read and then passing it to a friend who then runs off and keeps them. There's no way you can give me back my original.

The solution is either

  1. Make func2 take a reference too. This is equivalent to making your friend promise to give back the notes to you. You can then return them to me.
  2. Clone the object before passing to func2. This is equivalent to you making a copy of the notes and letting your friend run off with your copy - then giving me back my original.
Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
  • 7
    Notes analogy really explains the concept clearly. Thanks. – Meet Sinojia Jul 27 '20 at 08:29
  • Please, I still don't understand something. When func1 is getting &User reference and calling func2 which asks for value, but in the context of func1 is only &User reference. My brain is thinking like - it should pass the &User as it is, because it's the bare bone value it has available. And if the func2 would ask for &User I would think in the context of func1 it would pass &&User to func2. So.. in Rust, the references are not context aware? When calling func2 it will dereference the &User "magically"? – František Heča Aug 11 '21 at 08:02