生锈中明显的生命周期错误

rag*_*oth 4 enums lifetime object-lifetime rust

我有一个我想要使用的生锈枚举,但是我收到了错误;

error: explicit lifetime bound required
numeric(Num),
        ~~~
Run Code Online (Sandbox Code Playgroud)

有问题的枚举:

enum expr{
   numeric(Num),
   symbol(String),
}
Run Code Online (Sandbox Code Playgroud)

我不认为我明白这里借的是什么.我的意图是Num或String与包含expr的生命周期相同,允许我从函数返回它们.

Vla*_*eev 8

错误消息有点误导.Num是一个特征,它是一个动态大小的类型,所以如果没有某种间接(引用或a Box),你就不能拥有它的值.这样做的原因是简单的; 只问自己一个问题:expr枚举值必须有多大(以字节为单位)?它肯定至少和它一样大String,但是呢Num?任意类型都可以实现这个特性,所以为了声音expr必须具有无限大小!

因此,您只能使用某种指针作为类型使用traits:&NumBox<Num>.指针始终具有固定大小,并且特征对象是"胖"指针,在其中保留其他信息以帮助进行方法调度.

特征通常也用作泛型类型参数的边界.因为泛型是单形的,所以它们在编译的代码中变成静态类型,因此它们的大小总是静态地知道并且它们不需要指针.使用泛型应该是默认方法,只有在您知道泛型不适合您的原因时才应切换到特征对象.

这些是您的类型定义的可能变体.使用泛型:

enum Expr<N: Num> {
    Numeric(N),
    Symbol(String)
}
Run Code Online (Sandbox Code Playgroud)

Trait对象通过引用:

enum Expr<'a> {  // '
    Numeric(&'a Num + 'a),
    Symbol(String)
}
Run Code Online (Sandbox Code Playgroud)

带框的特征对象:

enum Expr {
    Numeric(Box<Num + 'static>),  // ' // I used 'static because numbers usually don't contain references inside them
    Symbol(String)
}
Run Code Online (Sandbox Code Playgroud)

您可以在官方指南中阅读有关泛型和特征的更多信息,但目前它缺乏有关特征对象的信息.如果你不明白,请问.

更新

'a

enum Expr<'a> {  // '
    Numeric(&'a Num + 'a),
    Symbol(String)
}
Run Code Online (Sandbox Code Playgroud)

是一个终身参数.它定义了Numeric变量的引用和特征对象内部的生命周期.&'a Num + 'a是一种类型,你可以读作"引用后面的特征对象,它至少'a与其中的引用一样长,并且至少与它一样长'a".也就是说,首先,您指定'a为参考生命周期:&'a,其次,您指定特征对象内部的生命周期:Num + 'a.后者是必需的,因为traits可以针对任何类型实现,包括其中包含引用的类型,因此您需要将这些引用的最小生命周期也放入trait对象类型,否则借用检查将无法与trait对象一起正常工作.

Box情况非常相似.Box<Num + 'static>是"堆分配的盒子里面的特征对象,里面有引用,至少和它一样长'static".该Box类型是堆分配的拥有数据的智能指针.因为它拥有它拥有的数据,所以它不需要像引用那样的生命周期参数.但是,trait对象仍然可以在其中包含引用,这就是为什么Num + 'a仍然使用; 我只是选择使用'static生命周期而不是添加另一个生命周期参数.这是因为数字类型通常很简单,并且内部没有引用,它等同于'static绑定.当然,如果需要,您可以自由添加生命周期参数.

请注意,所有这些变体都是正确的:

&'a SomeTrait + 'a
&'a SomeTrait + 'static
Box<SomeTrait + 'a>  // '
Box<SomeTrait + 'static>
Run Code Online (Sandbox Code Playgroud)

即使这是正确的,使用'a'b作为不同的生命周期参数:

&'a SomeTrait + 'b
Run Code Online (Sandbox Code Playgroud)

虽然这很少有用,因为它'b必须至少与其长度一样长'a(否则特性对象的内部可能会在它本身仍处于活动状态时失效),所以你也可以使用它&'a SomeTrait + 'a.