为什么Vec.sort()似乎需要静态生命周期?
这是我遇到的问题的一个大大简化的示例,但是给定了trait Thingwhich implementsOrd和struct 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,并将该对象添加到HashMap的Vec使用给定密钥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包含静态寿命的项目吗?如果是为什么?
有没有好的解决方法?
回答
您只Ord为dyn 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之外。