对于发生此错误后的生命,我完全感到困惑:
#![feature(collections)]
use std::collections::BitVec;
use std::collections::HashSet;
fn main() {
let mut hs = HashSet::new();
let zeros : BitVec = BitVec::from_elem(10,false);
let ones : BitVec = BitVec::from_elem(10,true);
println!("{:?}\n{:?}",zeros,ones);
// let mut hs = HashSet::new(); // works only if move this line to #7
hs.insert(&zeros);
hs.insert(&ones);
println!("{:?}",hs);
}
这给了我错误:
<anon>:14:16: 14:21 error: `zeros` does not live long enough
<anon>:14 hs.insert(&zeros);
^~~~~
<anon>:7:33: 17:2 note: reference must be valid for the block suffix following statement 0 at 7:32...
<anon>:7 let mut hs = HashSet::new();
但是,如果我稍后在
hs
和zeros
之后声明ones
,则一切正常:#![feature(collections)]
use std::collections::BitVec;
use std::collections::HashSet;
fn main() {
// let mut hs = HashSet::new();
let zeros : BitVec = BitVec::from_elem(10,false);
let ones : BitVec = BitVec::from_elem(10,true);
println!("{:?}\n{:?}",zeros,ones);
let mut hs = HashSet::new(); // works only if move this line to #7
hs.insert(&zeros);
hs.insert(&ones);
println!("{:?}",hs);
}
输出:
0000000000
1111111111
{0000000000, 1111111111}
Program ended.
您可以尝试代码here。
--
我在IRC上问这个问题得到了以下答案:
最佳答案
hs
的类型是HashSet<&'ρ BitVec>
-但是'ρ
是什么?
错误消息对此进行了一些解释:
<anon>:7:33: 17:2 note: reference must be valid for the block suffix following statement 0 at 7:32...
<anon>:7 let mut hs = HashSet::new();
就是说,对于定义了
HashSet
的第7行之后的其余块,该引用必须是合法的。那就是
'ρ
的含义:第7行之后的块的其余部分。这样想:在创建
HashSet<&BitVec>
时,立即插入值是否合法?不,因为它们是对尚不存在的事物的引用。如果您插入的是
BitVec
而不是对它们的引用,则问题将消失,因为&'ρ BitVec
的生存期为'ρ
,BitVec
的生存期为'static
,因为它不包含非静态数据,因此插入hs.insert(BitVec::from_elem(10, false))
将是正好。现在,为什么编译器不允许早期的
hs
定义?推断类型时,它必须是合法的类型。如果要在hs
声明位于第7行时推断出“第13行之后”的生存期,则在声明该声明时将有一些不合法的内容。在这种特殊情况下,对T
调用中的HashSet<T>
的new
并没有执行任何操作,因此您可以说理论上编译器可以忽略这样的事实,即它正在处理的非法类型将在我们实际使用时变为合法,但是这将是彻头彻尾的邪恶和前后矛盾(对函数主体的更改可能会影响调用者),因此Rust禁止整个行为。