rust - 实现 Deref 特征时无法为生命周期参数推断出合适的生命周期

标签 rust

我正在尝试为枚举实现Deref:

use std::rc::Rc;
use std::ops::Deref;

pub trait tObject {
    fn name(&self) -> String;
    fn span(&self) -> u32;
}

pub struct t1 {
    pub name: String,
    pub bd: Option<String>,
    pub span: u32,
    pub label: Option<String>
}

pub struct t2 {
    pub name: String,
    pub vrf: Option<String>,
    pub span: u32,
    pub label: Option<String>,
    pub svi: u32
}

pub struct t3 {
    pub name: String,
    pub span: u32,
    pub label: Option<String>
}

impl tObject for t1 {
    fn name(&self) -> String {self.name.clone()}
    fn span(&self) -> u32 {self.span.clone()}
}

impl tObject for t2 {
    fn name(&self) -> String {self.name.clone()}
    fn span(&self) -> u32 {self.span.clone()}
}

impl tObject for t3 {
    fn name(&self) -> String {self.name.clone()}
    fn span(&self) -> u32 {self.span.clone()}
}

pub enum TType {
    t1(Rc<t1>),
    t2(Rc<t2>),
    t3(Rc<t3>)
}

impl Deref for TType {
    type Target = tObject;
    fn deref<'a>(&'a self) -> &'a tObject {
        match *self {
            TType::t1(ref x) => x as &t1,
            TType::t2(ref x) => x as &t2,
            TType::t3(ref x) => x as &t3
        }
    }
}

fn main() {
    let mut t1s: Vec<Rc<t1>> = Vec::new();
    let mut t2s: Vec<Rc<t2>> = Vec::new();
    let mut t3s: Vec<Rc<t3>> = Vec::new();

    let t_iter: Box<Iterator<Item=TType>> = Box::new(t1s.iter().map(|x| TType::t1(x.clone())).chain(
                                                t2s.iter().map(|x| TType::t2(x.clone())).chain(
                                                t3s.iter().map(|x| TType::t3(x.clone())))));
}

编译器报错:

rustc 1.15.1 (021bd294c 2017-02-08)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting     requirements
  --> <anon>:53:5
   |
53 |       fn deref<'a>(&'a self) -> &'a tObject {
   |  _____^ starting here...
54 | |         match *self {
55 | |             TType::t1(ref x) => x as &t1,
56 | |             TType::t2(ref x) => x as &t2,
57 | |             TType::t3(ref x) => x as &t3
58 | |         }
59 | |     }
   | |_____^ ...ending here
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 53:42...
  --> <anon>:53:43
   |
53 |       fn deref<'a>(&'a self) -> &'a tObject {
   |  ___________________________________________^ starting here...
54 | |         match *self {
55 | |             TType::t1(ref x) => x as &t1,
56 | |             TType::t2(ref x) => x as &t2,
57 | |             TType::t3(ref x) => x as &t3
58 | |         }
59 | |     }
   | |_____^ ...ending here
note: ...so that method type is compatible with trait (expected fn(&TType) -> &tObject + 'static, found     fn(&TType) -> &tObject)
  --> <anon>:53:5
   |
53 |       fn deref<'a>(&'a self) -> &'a tObject {
   |  _____^ starting here...
54 | |         match *self {
55 | |             TType::t1(ref x) => x as &t1,
56 | |             TType::t2(ref x) => x as &t2,
57 | |             TType::t3(ref x) => x as &t3
58 | |         }
59 | |     }
   | |_____^ ...ending here
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that method type is compatible with trait (expected fn(&TType) -> &tObject + 'static, found     fn(&TType) -> &tObject)
  --> <anon>:53:5
   |
53 |       fn deref<'a>(&'a self) -> &'a tObject {
   |  _____^ starting here...
54 | |         match *self {
55 | |             TType::t1(ref x) => x as &t1,
56 | |             TType::t2(ref x) => x as &t2,
57 | |             TType::t3(ref x) => x as &t3
58 | |         }
59 | |     }
   | |_____^ ...ending here   

如果我将返回类型设为 deref Self::Target 而不是 tObject,它可以正常编译。我不明白这种行为。

最佳答案

这是一个MCVE .程序员使用这些来帮助缩小问题的范围。例如,此 MCVE 排除了由于使用 enumRc、特征中的任何方法或结构中的任何字段而导致的任何情况.这使我们能够专注于重要的事情:

use std::ops::Deref;

pub trait Trait {}

pub struct S {}
impl Trait for S {}

pub struct Container(S);

impl Deref for Container {
    type Target = Trait;

    // fn deref(&self) -> &Trait { // Fails!
    fn deref(&self) -> &Self::Target { // Works!
        &self.0
    }
}

从代码中,我们可以凭直觉知道,不知何故,TraitSelf::Target 不是 相同的类型。在这里查看类型有点棘手,但是这段代码将类型打印为编译器错误:

fn deref(&self) -> &Self::Target {
    let a: Self::Target;
    &self.0
}
error[E0277]: the trait bound `Trait + 'static: std::marker::Sized` is not satisfied

我们实际上并不关心错误,但我们发现了类型:Trait + 'static。让我们看看如果我们尝试类似的事情会发生什么:

fn deref(&self) -> &(Trait + 'static) {
    &self.0
}

这编译。

如果您不熟悉此语法,有很多关于它的问题。这里有一些:

关于rust - 实现 Deref 特征时无法为生命周期参数推断出合适的生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42309597/

相关文章:

rust - 在闭包中借用可变引用来对向量进行排序

rust - 为什么我得到 FromIterator<&T>` is not Implemented for Vec<T>?

rust - 原始指针的数据消失

string - 为什么不鼓励接受对String(&String),Vec(&Vec)或Box(&Box)的引用作为函数参数?

循环中的 Rust 生命周期问题

string - 如何在 Rust 中将字符串的字符串转换为字符串的数组/向量

rust - 即使显式也无法推断值类型

macros - 使用宏的输出作为另一个宏的参数

asynchronous - 如何在 Rust 中竞赛 future 集合?

rust - 为什么 map 和 map_err 捕获同一个变量?