“Temporary value dropped while borrowed” 在使用 unwrap() 后出现的错误。

huangapple go评论87阅读模式
英文:

"Temporary value dropped while borrowed" error after using unwrap()

问题

在以下代码中,有时我只需要get_keymaps()生成的第一个Keymap。所以我想我可以使用first()。但是,我发现它返回了一个Option<&T>,所以我不得不使用unwrap()来获取内部的值。

#[derive(Debug, Default)]
pub struct Keymap {
    pub key: char,
    pub command: String,
    pub description: String,
    pub prompt: Option<String>,
}

impl Keymap {
    pub fn new<S: AsRef<str>>(key: char, command: S) -> Self {
        let command = command.as_ref().to_owned();
        let description = command.clone();

        Self {
            key,
            command,
            description,
            ..Default::default()
        }
    }
}

fn get_keymaps<'a>() -> Vec<Keymap> {
    vec![Keymap::new('t', "echo 'test'")]
}

fn handle_keymap(keymap: &Keymap) {
    println!("Do something with {:?}", keymap);
}

fn main() {
    let keymap = get_keymaps().first().unwrap();
    handle_keymap(keymap);
}

但现在我得到了以下错误:

error[E0716]: temporary value dropped while borrowed
   --> src/main.rs:33:18
    |
33  |     let keymap = get_keymaps().first().unwrap();
    |                  ^^^^^^^^^^^^^                 - 临时值在此语句结束时被释放
    |                  |
    |                  在使用时创建了一个临时值,但在仍在使用时被释放
34  |     handle_keymap(keymap);
    |                   ------ 后面使用了借用

我不太理解为什么临时值会被释放。我不太确定它是什么意思。我不知道如何修复它。

英文:

In the following code, sometimes I only need the first Keymap produced by get_keymaps(). So I figured I could use first(). However, I found out it returns an Option&lt;&amp;T&gt;, so I had to use unwrap() to get the value inside.

#[derive(Debug, Default)]
pub struct Keymap {
    pub key: char,
    pub command: String,
    pub description: String,
    pub prompt: Option&lt;String&gt;,
}

impl Keymap {
    pub fn new&lt;S: AsRef&lt;str&gt;&gt;(key: char, command: S) -&gt; Self {
        let command = command.as_ref().to_owned();
        let description = command.clone();

        Self {
            key,
            command,
            description,
            ..Default::default()
        }
    }
}

fn get_keymaps&lt;&#39;a&gt;() -&gt; Vec&lt;Keymap&gt; {
    vec![Keymap::new(&#39;t&#39;, &quot;echo &#39;test&#39;&quot;)]
}

fn handle_keymap(keymap: &amp;Keymap) {
    println!(&quot;Do something with {:?}&quot;, keymap);
}

fn main() {
    let keymap = get_keymaps().first().unwrap();
    handle_keymap(keymap);
}

Rust Playground

But now I'm getting the following error:

error[E0716]: temporary value dropped while borrowed
  --&gt; src/main.rs:33:18
   |
33 |     let keymap = get_keymaps().first().unwrap();
   |                  ^^^^^^^^^^^^^                 - temporary value is freed at the end of this statement
   |                  |
   |                  creates a temporary value which is freed while still in use
34 |     handle_keymap(keymap);
   |                   ------ borrow later used here

I don't quite understand why a temporary value was freed. I'm not very sure what it means. And I don't know how to fix it.

答案1

得分: 2

你可以想象这样的情况:

let keymap = get_keymaps().first().unwrap();

实际上看起来是这样的:

let keymap = {
    let temporary = get_keymaps();
    temporary.first().unwrap()
};

first 的调用从 temporary 借用,但 temporary 在块末尾,也就是赋值语句结束时被丢弃。但当你后面想要使用由 first 创建的引用时,它会强制 temporary 超越那个使用,导致编译错误。通过将赋值移到 temporary 的赋值之外,你可以创建一个足够长寿的值(正如编译器消息所说):

let longer_lived_value = get_keymaps();
let keymap = longer_lived_value.first().unwrap();

请注意,同样的事情不适用于对 unwrap 的调用。这是因为与 first 不同,unwrap 接受值引用,而 unwrap 接受值本身,拥有临时值的所有权,而不是借用它。

英文:

You can imagine that something like

let keymap = get_keymaps().first().unwrap();

actually looks like this:

let keymap = {
    let temporary = get_keymaps();
    temporary.first().unwrap()
};

The call to first borrows from temporary but temporary gets dropped at the end of the block, i.e. the assignment statement. But when you want to use the reference created by first later, it forces temporary to outlive that use causing the compile error. By hoisting the assignment to temporary out of the assignment to keymap, you can create a value that lives long enough (exactly like the compiler message says):

let longer_lived_value = get_keymaps();
let keymap = longer_lived_value.first().unwrap();

Note that the same thing doesn't apply to the call to unwrap. That's because unlike first, which takes self by reference, unwrap takes self by value, taking ownership of the temporary instead of borrowing from it.

huangapple
  • 本文由 发表于 2023年7月10日 22:52:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76654942.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定