编译器建议我添加一个“静态生命周期",因为参数类型的生命周期可能不够长,但我认为这不是我想要的 [英] The compiler suggests I add a 'static lifetime because the parameter type may not live long enough, but I don't think that's what I want

查看:11
本文介绍了编译器建议我添加一个“静态生命周期",因为参数类型的生命周期可能不够长,但我认为这不是我想要的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现一些看起来像这个最小示例的东西:

I'm trying to implement something that looks like this minimal example:

trait Bar<T> {}

struct Foo<T> {
    data: Vec<Box<Bar<T>>>,
}

impl<T> Foo<T> {
    fn add<U: Bar<T>>(&mut self, x: U) {
        self.data.push(Box::new(x));
    }
}

由于 Rust 默认(据我所知)所有权传递,我的心智模型认为这应该可行.add 方法获取对象 x 的所有权并且能够将该对象移动到 Box 中,因为它知道完整的类型 U(而不仅仅是特征 Bar).一旦移动到 Box 中,盒子内项目的生命周期应该与盒子的实际生命周期相关联(例如,当 pop() 关闭向量时对象将被销毁).

Since Rust defaults to (as far as I can tell) pass-by-ownership, my mental model thinks this should work. The add method takes ownership of object x and is able to move this object into a Box because it knows the full type U (and not just trait Bar<T>). Once moved into a Box, the lifetime of the item inside the box should be tied to the actual lifetime of the box (e.g., when pop()ed off the vector the object will be destroyed).

然而,很明显,编译器不同意(而且我肯定比我知道的更多……),要求我考虑添加一个 'static 生命周期限定符 (E0310).我 99% 确定那不是我想要的,但我不确定我应该做什么.

Clearly, however, the compiler disagrees (and I'm sure knows a bit more than I...), asking me to consider adding a 'static lifetime qualifier (E0310). I am 99% sure that's not what I want, but I'm not exactly sure what I'm supposed to do.

为了澄清我的想法并帮助识别误解,我的心智模型来自 C++ 背景,是:

To clarify what I'm thinking and help identify misconceptions, my mental model, coming from a C++ background, is:

  • Box 本质上是 std::unique_ptr
  • 没有任何注释,如果Copy,则变量按值传递,否则为rvalue-reference
  • 加上引用注解,&大致是const&&mut大致是&
  • 默认生命周期是词法作用域
  • Box<T> is essentially std::unique_ptr<T>
  • Without any annotations, variables are passed by value if Copy and rvalue-reference otherwise
  • With a reference annotation, & is roughly const& and &mut is roughly &
  • The default lifetime is lexical scope

推荐答案

检查整个错误:

error[E0310]: the parameter type `U` may not live long enough
 --> src/main.rs:9:24
  |
8 |     fn add<U: Bar<T>>(&mut self, x: U) {
  |            -- help: consider adding an explicit lifetime bound `U: 'static`...
9 |         self.data.push(Box::new(x));
  |                        ^^^^^^^^^^^
  |
note: ...so that the type `U` will meet its required lifetime bounds
 --> src/main.rs:9:24
  |
9 |         self.data.push(Box::new(x));
  |                        ^^^^^^^^^^^

具体来说,编译器让您知道某些任意类型的U 可能包含引用,然后该引用可能变得无效:

Specifically, the compiler is letting you know that it's possible that some arbitrary type U might contain a reference, and that reference could then become invalid:

impl<'a, T> Bar<T> for &'a str {}

fn main() {
    let mut foo = Foo { data: vec![] };

    {
        let s = "oh no".to_string();
        foo.add(s.as_ref());
    }
}

那将是个坏消息.

您想要 'static 生命周期还是参数化生命周期取决于您的需要.'static 生命周期更易于使用,但有更多限制.因此,当您在结构体或类型别名中声明 trait 对象 时,这是默认设置:

Whether you want a 'static lifetime or a parameterized lifetime is up to your needs. The 'static lifetime is easier to use, but has more restrictions. Because of this, it's the default when you declare a trait object in a struct or a type alias:

struct Foo<T> {
    data: Vec<Box<dyn Bar<T>>>,
    // same as
    // data: Vec<Box<dyn Bar<T> + 'static>>,
} 

然而,当用作参数时,trait 对象使用 lifetime elision 并获得唯一的生命周期:

However, when used as an argument, a trait object uses lifetime elision and gets a unique lifetime:

fn foo(&self, x: Box<dyn Bar<T>>)
// same as
// fn foo<'a, 'b>(&'a self, x: Box<dyn Bar<T> + 'b>)

这两件事需要匹配起来.

These two things need to match up.

struct Foo<'a, T> {
    data: Vec<Box<dyn Bar<T> + 'a>>,
}

impl<'a, T> Foo<'a, T> {
    fn add<U>(&mut self, x: U)
    where
        U: Bar<T> + 'a,
    {
        self.data.push(Box::new(x));
    }
}

struct Foo<T> {
    data: Vec<Box<dyn Bar<T>>>,
}

impl<T> Foo<T> {
    fn add<U>(&mut self, x: U)
    where
        U: Bar<T> + 'static,
    {
        self.data.push(Box::new(x));
    }
}

这篇关于编译器建议我添加一个“静态生命周期",因为参数类型的生命周期可能不够长,但我认为这不是我想要的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆