繁体   English   中英

在 Rust 中,当对作为通用参数传递的值进行装箱时,为什么需要“静态”生命周期限制?

[英]In Rust, when boxing a value passed as a generic argument, why is a `'static` lifetime bound required?

我正在尝试编写一个构造函数 function ,它采用一个通过参数实现某些特征的通用值,然后将其装箱(重点是然后用这些框初始化某些东西,但以下示例已简化):

struct Struct {}

trait Trait {}

impl Trait for Struct {}

fn f(arg: impl Trait) -> Box<dyn Trait> {
    Box::new(arg)
}

fn main() {
    let x = Struct {};
    f(x);
}

在这里,编译器抱怨arg可能活得不够长。 这对我来说非常有意义,因为对arg的唯一要求是impl Trait ,这意味着它实际上可能是实现该特征的引用,在这种情况下它不能被安全地装箱。

让我感到困惑的是以下解决方案,添加了一个'static绑定:

fn f(arg: impl Trait + 'static) -> Box<dyn Trait> {
    Box::new(arg)
}

现在,它当然可以工作,但原则上我们现在被限制为传递具有'static生命周期”的值。 然而,编译器让我可以毫无问题地传入x

这是我的问题,更具体地说:

  1. x没有生命周期,驻留在堆栈上吗? 为什么当arg具有'static生命周期限制”时可以将其传递给f 这些界限是否只涉及引用的生命周期?
  2. 这个解决方案一般有效吗,还是我会面临编译器拒绝我的堆栈分配 arguments 的情况?
  3. 有没有更好的方式来表达“任何在类型不是引用的情况下实现Trait的类型?

请注意,1) 主要由为什么 Rust 需要此变量的“静态”生命周期来回答? 但我很困惑这是否是拳击 arguments 的惯用方式。


编辑:

现在我理解得更好了,我想知道在填充结构的情况下修复编译器错误的惯用解决方案是什么:

struct OtherStruct {
    x: Box<dyn Trait>,
}

impl OtherStruct {
    fn new(arg: impl Trait) -> Self { // Does not compile
        Self { x: Box::new(arg) }
    }
}

到目前为止,我看到的唯一解决方案是 1)向OtherStruct添加一个生命周期参数(不是那么好),添加一个绑定到arg 'static生命周期(我不确定这是否可以?)

你在这里有几个误解。

x 没有生命周期,驻留在堆栈上吗? 为什么当 arg 具有“静态生命周期限制”时可以将其传递给 f? 这些界限是否只涉及引用的生命周期?

当你在做f(x)时,因为你没有引用x ,你正在将x的值移动到 function 中,这会改变它的生命周期。 如果您在调用f(x)后再次尝试使用x , Rust 将无法编译您的代码并告诉您这一点。

至于+ 'static bound... Box<dyn Trait>Box<dyn Trait + 'static>的简写,这就是编译器给你一个错误的原因。 类型系统需要知道盒子内部实现的生命周期,以便它可以检查它。 如果你愿意,你可以明确地给盒子一个不同的生命周期:

fn f<'a>(arg: impl Trait + 'a) -> Box<dyn Trait + 'a> {
    Box::new(arg)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM