Just to clarify, the ..user1
syntax is not copy or clone, but move. The ownership is transferred. With bool
or other primitive types, they implement Copy
, which is why when transferring ownership, they clone their data instead of being moved
In Rust, you cannot transfer the ownership of something and automatically have it move back. It is always the responsibility of the owner to move itself to somewhere else.
In your code example, when you initialize user2
, the ownership of username
is transferred, so user1.username
is no longer accessible. Thus from now on, you no longer have access to the entire user1
, which is why you got the error value used here after partial move
when trying to move its entirety to drop()
. And it is now the responsibility of user2
to move the username
it owns back to user1
before user2
is dropped.
If you want to temporarily let user2
have access to what user1
holds, what you need is borrow.
struct User {
active: bool,
username: String
}
fn main() {
let user1 = User {
active: true,
username: "someusername123".to_string(),
};
let user_ref = &user1; // user_ref borrows user1, but user1 still owns the data
drop(user_ref); // Here only the borrow is dropped
drop(user1); // Here the data is moved into drop()
}
If you also want to distinguish user_ref
from user1
, you can create a separate type that is a reference of User
type
struct User {
active: bool,
username: String
}
struct UserRef<'a> {
active: bool,
username: &'a String,
}
impl User {
fn as_user_ref<'a>(&'a self) -> UserRef<'a> {
UserRef {
active: false,
username: &self.username,
}
}
}
fn main() {
let user1 = User {
active: true,
username: "someusername123".to_string(),
};
let user_ref = user1.as_user_ref(); // user_ref is type UserRef<'a>
drop(user_ref); // Here UserRef is dropped, but because it holds &String,
// nothing happens to the data
drop(user1); // Here the data is moved into drop()
}
Or if what you want is just to copy user1, and the two variables are not related, just derive the Clone
trait.
#[derive(Clone)]
struct User {
active: bool,
username: String
}
impl User {
fn clone_inactive(&self) -> User {
let mut user = self.clone();
user.active = false;
user
}
}
fn main() {
let user1 = User {
active: true,
username: "someusername123".to_string(),
};
let user2 = user1.clone_inactive(); // user1 is cloned, there are now 2 String
drop(user2); // The String owned by user2 is dropped
drop(user1); // The String owned by user1 is dropped
}