From<&V> 特征约束的生命周期问题

Geo*_*rge 6 lifetime rust

尽管该V实例已被拥有,但以下代码仍会产生以下生命周期错误。

use std::collections::hash_map::HashMap;
use std::cmp::Eq;
use std::hash::Hash;

trait Set<V> {
    fn set(&mut self, value: V) -> Option<V>;
}

impl<'a, K: Eq + Hash + From<&'a V>, V: 'a> Set<V> for HashMap<K, V> {
    fn set(&mut self, v: V) -> Option<V> {
        let k = K::from(&v);
        self.insert(k, v)
    }
}
Run Code Online (Sandbox Code Playgroud)

由此产生的错误...

   |
9  | impl<'a, K: Eq + Hash + From<&'a V>, V: 'a> Set<V> for HashMap<K, V> {
   |      -- lifetime `'a` defined here
10 |     fn set(&mut self, v: V) -> Option<V> {
11 |         let k = K::from(&v);
   |                 --------^^-
   |                 |       |
   |                 |       borrowed value does not live long enough
   |                 argument requires that `v` is borrowed for `'a`
12 |         self.insert(k, v)
13 |     }
   |     - `v` dropped here while still borrowed

error[E0505]: cannot move out of `v` because it is borrowed
  --> src/lib.rs:12:24
   |
9  | impl<'a, K: Eq + Hash + From<&'a V>, V: 'a> Set<V> for HashMap<K, V> {
   |      -- lifetime `'a` defined here
10 |     fn set(&mut self, v: V) -> Option<V> {
11 |         let k = K::from(&v);
   |                 -----------
   |                 |       |
   |                 |       borrow of `v` occurs here
   |                 argument requires that `v` is borrowed for `'a`
12 |         self.insert(k, v)
   |                        ^ move out of `v` occurs here
Run Code Online (Sandbox Code Playgroud)

kmd*_*eko 5

使用由 表示的更高等级特征界限for<'a>

impl<K: Eq + Hash + for<'a> From<&'a V>, V> Set<V> for HashMap<K, V> {
    fn set(&mut self, v: V) -> Option<V> {
        self.insert(K::from(&v), v)
    }
}
Run Code Online (Sandbox Code Playgroud)

看到它在操场上工作。

作为普通的泛型参数,生命周期'a由调用者确定,这将比调用set()本身的生命周期长。然而, 的生命周期v仅在函数体本地,这意味着'a用于调用的任何生命周期都K::from()可以比 中可能包含的内容更长久V。仅仅因为v它是一个拥有的值并不意味着它没有与之相关的生命周期,它毕竟是通用的。编译器已经尽力了,但它的建议并不是你想要的。

使用for<'a> From<&'a V>约束意味着该调用将在任何K::from()生命周期内有效,包括 的短函数局部生命周期。v