为什么Vec.sort()似乎需要静态生命周期?

这是我遇到的问题的一个大大简化的示例,但是给定了trait Thingwhich implementsOrdstruct Objectwhich implements Thing,我有以下结构:

pub struct MyStruct<'a> {
    my_things: HashMap<i32, Vec<Box<dyn Thing + 'a>>>
}

impl<'a> MyStruct<'a> {
    pub fn new() -> MyStruct<'a> {
        MyStruct {
            my_things: HashMap::new()
        }
    }
    
    pub fn add_object(&mut self, key: i32, obj: Object) {
        if !self.my_things.contains_key(&key) {
            self.my_things.insert(key, Vec::new());
        }
        
        let new_thing: Box<dyn Thing> = Box::new(obj);
        let things = self.my_things.get_mut(&key).unwrap();
        
        things.push(new_thing);
        things.sort();
    }
}

它本质上需要一个密钥和Object,并将该对象添加到HashMapVec使用给定密钥s。我知道这不是执行此操作的最佳方法,但我想让它更简单以进行说明。

编译器在调用 时抱怨things.sort()以下错误:

error[E0308]: mismatched types
  --> src/main.rs:58:16
   |
58 |         things.sort();
   |                ^^^^ lifetime mismatch
   |
   = note: expected trait `Ord`
              found trait `Ord`
note: the lifetime `'a` as defined on the impl at 42:6...
  --> src/main.rs:42:6
   |
42 | impl<'a> MyStruct<'a> {
   |      ^^
   = note: ...does not necessarily outlive the static lifetime

游乐场链接

如果我删除'a此示例中的所有生命周期,代码将被编译。但是对于我的实际用例,我需要允许非静态生命周期。

有人可以解释这里发生了什么吗?是否sort()真的需要Vec包含静态寿命的项目吗?如果是为什么?

有没有好的解决方法?

回答

您只Orddyn Thing + 'static. 的'static,如果你没有明确指定绑定任何其他寿命势必寿命推断。要实现Ordnon- 'static dyn Things,您需要'a在您的实现中引入和使用通用生命周期参数,例如。更新编译示例:

use std::collections::HashMap;
use std::cmp;

pub trait Thing {
    fn priority(&self) -> i32;
}

impl<'a> PartialEq for dyn Thing + 'a { // 'a added here
    fn eq(&self, other: &Self) -> bool {
        self.priority() == other.priority()
    }
}

impl<'a> PartialOrd for dyn Thing + 'a { // 'a added here
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        self.priority().partial_cmp(&other.priority())
    }
}

impl<'a> Eq for dyn Thing + 'a {} // 'a added here

impl<'a> Ord for dyn Thing + 'a { // 'a added here
    fn cmp(&self, other: &Self) -> cmp::Ordering{
        self.priority().cmp(&other.priority())
    }
}

pub struct Object {
    priority: i32,
}

impl Thing for Object {
    fn priority(&self) -> i32 {
        self.priority
    }
}

pub struct MyStruct<'a> {
    my_things: HashMap<i32, Vec<Box<dyn Thing + 'a>>>
}

impl<'a> MyStruct<'a> {
    pub fn new() -> MyStruct<'a> {
        MyStruct {
            my_things: HashMap::new()
        }
    }
    
    pub fn add_object(&mut self, key: i32, obj: Object) {
        if !self.my_things.contains_key(&key) {
            self.my_things.insert(key, Vec::new());
        }
        
        let new_thing: Box<dyn Thing> = Box::new(obj);
        let things = self.my_things.get_mut(&key).unwrap();
        
        things.push(new_thing);
        things.sort();
    }
}

fn main() {
    let _test = MyStruct::new();
}

操场


来自Rust Reference(重点是我的)的Lifetime Elision章节的Default Trait Object Lifetimes部分

如果特征对象用作泛型类型的类型参数,则首先使用包含类型来尝试推断边界。

  • 如果包含类型有唯一的绑定,那么这是默认值
  • 如果包含类型有多个边界,则必须指定显式边界

如果这些规则都不适用,则使用特征的边界:

  • 如果特征是用单个生命周期界限定义的,则使用该界限。
  • 如果 'static 用于任何生命周期界限,则使用 'static。
  • 如果 trait 没有生命周期界限,那么生命周期是在表达式中推断出来的,并且在表达式'static之外。

以上是为什么Vec.sort()似乎需要静态生命周期?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>