There’s two aspects here, better demonstrated if we split up the .as_ref()
and the .map(…)
step
fn main() {
let greet: Option<String> = Some("hi".to_string());
let as_ref = greet.as_ref();
let mapped = as_ref.map(|e| e);
dbg!(&mapped, &as_ref, &greet); // all 3 still exist
}
The reason why greet
still exists is because the .as_ref
method only takes a &self
argument of the original Option
, and from that produces a new option (of type Option<&String>
in this case). Even if that newly produced value was moved, it wouldn’t do anything to the original Option
. The reason why even as_ref
, too, still exists despite the call to map
is because Option<&String>
implements Copy
.
The original Option
is notable not entirely out of the game here. It’s still borrowed. Since the map
ped operation kept the reference as a reference, both as_ref
and mapped
are still considered to borrow from greet
, and something like
fn main() {
let greet: Option<String> = Some("hi".to_string());
let as_ref = greet.as_ref();
let mapped = as_ref.map(|e|e);
drop(greet);
dbg!(&mapped);
}
thus fails (same thing for trying dbg!(as_ref)
instead).
error[E0505]: cannot move out of `greet` because it is borrowed
--> src/main.rs:7:10
|
4 | let as_ref = greet.as_ref();
| -------------- borrow of `greet` occurs here
...
7 | drop(greet);
| ^^^^^ move out of `greet` occurs here
8 | dbg!(&mapped);
| ------- borrow later used here
If on the other hand the mapped operation would create an owned value, e.g. something like .map(|e| e.len())
, then mapped
would become completely independent of the original greet
. E.g. this compiles fine
fn main() {
let greet: Option<String> = Some("hi".to_string());
let as_ref = greet.as_ref();
let mapped = as_ref.map(|e| e.len());
drop(greet);
dbg!(&mapped); // but using `&as_ref` here instead would still error
}