英文:
map function : cannot move out of ... which is behind a mutable reference
问题
我正在按照这个教程,并遇到了关于map
函数的一些有趣内容。这里是一个关于问题的玩具模型。
#[derive(Debug)]
pub struct Word(String);
pub fn main(){
let words = "wwww";
let mut word = Word(words.to_string());
let mut o2 = Some(&word);
let ref2 = &mut o2;
let new = ref2.map(|w|{
"nnnnn"
});
println!("{:?}", new);
println!("{:?}", o2);
}
输出如下所预测:
Some("nnnnn")
Some(Word("wwww"))
然而,如果我更改这一行:
let mut o2 = Some(&word);
为:
let mut o2 = Some(&mut word);
这是错误消息:
error[E0507]: cannot move out of `*ref2` which is behind a mutable reference
--> src/main.rs:10:15
|
10 | let new = ref2.map(|w|{
| _________________^____-
| | _______________|
| | |
11 | | | "nnnnn"
12 | | | });
| | | ^
| |_|______|
| | `*ref2` moved due to this method call
| |______help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
| move occurs because `*ref2` has type `Option<&mut Word>`, which does not implement the `Copy` trait
|
note: this function takes ownership of the receiver `self`, which moves `*ref2`
--> /home/wh/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:919:28
|
919 | pub const fn map<U, F>(self, f: F) -> Option<U>
|
似乎当`o2`是一个包装器的普通引用时,
```rust
o2 = Some(&word)
map
函数并不会真正尝试拥有o2
。
但是,一旦它是一个可变引用的包装器,
o2 = Some(&mut word)
map
函数突然想要拥有o2
。
因此,Option
内部的数据类型可以影响map
函数的行为,背后的原因是什么呢?
英文:
I'm following this tutorial
and came across something really interesting about the map function.
Here is a toy model of the problem.
#[derive(Debug)]
pub struct Word(String);
pub fn main(){
let words = "wwww";
let mut word = Word(words.to_string());
let mut o2 = Some(&word);
let ref2 = &mut o2;
let new = ref2.map(|w|{
"nnnnn"
});
println!("{:?}", new);
println!("{:?}", o2);
}
The output is as predicted :
Some("nnnnn")
Some(Word("wwww"))
However, if I change this line
let mut o2 = Some(&word);
to
let mut o2 = Some(&mut word);
here is the error message:
error[E0507]: cannot move out of `*ref2` which is behind a mutable reference
--> src/main.rs:10:15
|
10 | let new = ref2.map(|w|{
| _________________^____-
| | _______________|
| | |
11 | | | "nnnnn"
12 | | | });
| | | ^
| |_|______|
| | `*ref2` moved due to this method call
| |______help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
| move occurs because `*ref2` has type `Option<&mut Word>`, which does not implement the `Copy` trait
|
note: this function takes ownership of the receiver `self`, which moves `*ref2`
--> /home/wh/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:919:28
|
919 | pub const fn map<U, F>(self, f: F) -> Option<U>
|
It seems like when o2 is a wrapper of some normal reference,
o2 = Some(&word),
the map function wouldn't really try to take ownership of o2,
But, once, it is a wrapper of some mutable reference,
o2 = Some(&mut word),
the map function suddenly wants to take ownership o2.
So the data type inside an Option could affect the behaviour of the map function,
What is the reasoning behind this?
答案1
得分: 2
让我们看一下 map
的签名:
pub fn map<U, F>(self, f: F) -> Option<U>
where
F: FnOnce(T) -> U
在这里 self
是 Option<T>
,这就导致了你的问题。
在语句 let mut o2 = Some(&word);
中,o2
的类型是 Option<&Word>
。因此,当你对其调用 map
时,泛型会特化为 map(self, f: FnOnce(&Word) -> &str) -> Option<&str>
。只存在不可变引用,并且所有不可变引用都实现了 Copy
。
但是在语句 let mut o2 = Some(&mut word);
中,o2
的类型是 Option<&mut Word>
,并且 map
会特化为 map(self, f: FnOnce(&mut Word) -> &str) -> Option<&str>
。可变引用没有 Copy
的实现。
据我理解,不可变引用会被复制,map
执行时就好像没发生任何特殊情况。但如果使用可变引用,就需要它的所有权,因为它无法被复制。
英文:
Let's take a look at map
's signature:
pub fn map<U, F>(self, f: F) -> Option<U>
where
F: FnOnce(T) -> U
Here self
is Option<T>
, which causes your problem.
In statement let mut o2 = Some(&word);
, the type of o2
is Option<&Word>
. Thus, when you call map
on it, the generic specializes to map(self, f: FnOnce(&Word) -> &str) -> Option<&str>
. Only immutable references exist, and Copy
is implemented for all immutable references.
But in statement let mut o2 = Some(&mut word);
, the type of o2
is Option<&mut Word>
and map
specializes to map(self, f: FnOnce(&mut Word) -> &str) -> Option<&str>
. Mutable references have no Copy
implementation.
To my understanding, the immutable reference is copied, and map
execute as if nothing special happened. But if a mutable reference is used, its ownership is needed since it cannot be copied.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论