【问题标题】:how to annotate trait implemetation which returns Self, has specified lifetime?如何注释返回 Self 的特征实现,已指定生命周期?
【发布时间】:2026-02-15 10:20:02
【问题描述】:

标题似乎与 Lifetime parameter for `Self` in trait signature 相似,但我创建了这个新帖子,因为我认为根本原因不同。

我有一个像下面这样的特质

trait T<'a> {
    fn new(y: &'a Y) -> Self where Self: Sized;
    fn do_something(&self);
}

并想编写接受类型 X(实现 trait T)和 Y 引用的泛型函数,然后创建 dyn Trait T。

fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>> 

我的幼稚实现是这样的

fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>> {
    return Box::new(I::new(y)) as Box<dyn T<'a>>;
}

然后我得到了这个错误。

error[E0310]: the parameter type `I` may not live long enough

但是参数类型I 有约束T&lt;'a&gt;,我不明白为什么这并没有告诉rustcI::new(y) 在执行步骤从这个函数出去之后是活动的。

我怀疑这是I:new() 返回Self 发生的,它没有生命周期注释。但我也找不到给 Self 终身注释的方法。

这是导致错误的完整示例。

struct Y {
    z: i32
}

struct X<'a> {
    y: &'a Y
}

trait T<'a> {
    fn new(y: &'a Y) -> Self where Self: Sized;
    fn do_something(&self);
}

impl<'a> T<'a> for X<'a> {
    fn new(y: &'a Y) -> X<'a> {
        return X::<'a> {
            y: y
        }
    }
    fn do_something(&self) {
        println!("{}", self.y.z)
    }
}

fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>> {
    // error: the parameter type `I` may not live long enough
    return Box::new(I::new(y)) as Box<dyn T<'a>>;
}

fn main() {
    let y = Y { z: 123 };
    {
        let t = create_t_from_i::<X>(&y);
        t.do_something()
    }
}

如果我删除 T::new 的定义并将 X::new 作为函数指针提供给 create_t_from_i,代码似乎可以工作(需要使用 T + 'a 而不是 T)。但是与第一个示例有什么本质区别?

struct Y {
    z: i32
}

struct X<'a> {
    y: &'a Y
}

trait T {
    fn do_something(&self);
}

impl<'a> X<'a> {
    fn new(y: &'a Y) -> X<'a> {
        return X::<'a> {
            y: y
        }
    }
}
impl<'a> T for X<'a> {
    fn do_something(&self) {
        println!("{}", self.y.z)
    }
}

fn create_t_from_i<'a, I: T + 'a>(ctor: fn (y: &'a Y) -> I, y: &'a Y) -> Box<dyn T + 'a> {
    // if passing constructor function directly and using annotation I: T + 'a, rustc does not complain. 
    let i = ctor(y);
    return Box::new(i) as Box<dyn T + 'a>;
}

fn main() {
    let y = Y { z: 123 };
    {
        let t = create_t_from_i::<X>(X::new, &y);
        t.do_something()
    }
}

有人知道为什么会发生这种情况以及如何让“rustc”开心吗?

问候。

【问题讨论】:

    标签: rust


    【解决方案1】:
    fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>> 
    

    隐含地与

    相同
    fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn 'static + T<'a>> 
    

    这反过来意味着I 还必须具有静态生命周期才能将其存储在返回的框中(即您需要I: 'static 绑定)。

    为了解决这个问题,您可以为I 的生命周期添加另一个生命周期参数,并在返回的盒装特征中使用它。无论I 的实际生命周期是多少,这都会起作用:

    fn create_t_from_i<'a, 'b, I: 'b + T<'a>>(y: &'a Y) -> Box<dyn 'b + T<'a>> 
    //                     ^^^^^^^^^                               ^^^^
    

    Playground example

    【讨论】:

      【解决方案2】:

      任何 trait 对象都有一个生命周期注解,这将隐含为 'static。 因此,您的功能是:

      fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn 'static + T<'a>> 
      

      解决方案是显式注释特征对象的生命周期:

      fn create_t_from_i<'a, I: 'a + T<'a>>(y: &'a Y) -> Box<dyn 'a + T<'a>> 
      

      【讨论】:

        最近更新 更多