2016-07-28 42 views
3

为什么Rust编译器发出一个错误,要求我限制下列结构中泛型参数的生存期?Rust编译器为什么要求我限制泛型类型参数的生存期(错误E0309)?

pub struct NewType<'a, T> { 
    x: &'a T, 
} 
error[E0309]: the parameter type `T` may not live long enough 
--> src/main.rs:2:5 
    | 
2 |  x: &'a T, 
    |  ^^^^^^^^ 
    | 
    = help: consider adding an explicit lifetime bound `T: 'a`... 
note: ...so that the reference type `&'a T` does not outlive the data it points at 
--> src/main.rs:2:5 
    | 
2 |  x: &'a T, 
    |  ^^^^^^^^ 

我可以通过改变

pub struct NewType<'a, T> 
where 
    T: 'a, 
{ 
    x: &'a T, 
} 

我不明白为什么它是必要的T: 'a部件添加到结构定义修复它。我想不到T中包含的数据可能会超过对T的引用。 x的引用需要超过NewType结构,如果T是另一个结构,那么它需要符合它包含的任何引用的相同条件。

是否有一个具体的例子,这种类型的注释是必要的,或者是锈编译器只是迂腐?

+0

这会让你更加困惑于相关的类型。你必须绑定 :: Associated:'a *即使你已经绑定了T的一生,这对我来说并没有什么意义。 – LinearZoetrope

回答

5

什么T: 'a的意思是,在T任何引用必须活得比'a

这意味着,你不能这样做:

let mut o: Option<&str> = Some("foo"); 
let mut nt = NewType { x: &o }; // o has a reference to &'static str, ok. 

{ 
    let s = "bar".to_string(); 
    let o2: Option<&str> = Some(&s); 
    nt.x = &o2; 
} 

这将是危险的,因为nt将有块后悬挂参考s。在这种情况下,它会抱怨o2没有足够长的时间。

我不能想办法,你可以有一个&'a参考的东西包含短寿命参考,并明确了编译器知道以某种方式这个(因为它告诉你添加的约束)。不过,我认为在某些方面阐明限制是有帮助的,因为它使得借用检查器不那么神奇:只需从类型声明和函数签名就可以推断它,而无需查看字段如何定义(通常是实现这些细节不在文档中)或者如何实现一个函数。

+0

我同意明确表示绝不是坏事。我经常会问“源码是否超出了目的地”的问题,并且在这种情况下,编写示例很难,因为我知道编译器会拒绝它。感谢这个简单而清晰的例子。 – Novus

相关问题