Скорее всего, это хрестоматийный случай, когда я не понимаю некоторых технических особенностей средства проверки заимствований, но было бы неплохо, если бы кто-нибудь мог прояснить это для меня.
У меня есть этот (невероятно упрощенный) фрагмент кода, который отлично компилируется.
pub struct Example(pub Vec<String>);
impl Example {
pub fn iter(&self) -> impl Iterator<Item=&String> {
self.0.iter()
}
}
pub fn some_condition(_: &str) -> bool {
// This is not important.
return false;
}
pub fn foo() -> bool {
let example = Example(vec!("foo".to_owned(), "bar".to_owned()));
let mut tmp = example.iter();
tmp.all(|x| some_condition(x))
}
pub fn main() {
println!("{}", foo());
}
Однако первое, что я попробовал (что, на мой взгляд, должно быть эквивалентно приведенному выше), - это полностью исключить временную переменную tmp
, как показано ниже.
pub fn foo() -> bool {
let example = Example(vec!("foo".to_owned(), "bar".to_owned()));
example.iter().all(|x| some_condition(x))
}
Но эта версия выдает следующую ошибку.
error[E0597]: `example` does not live long enough
--> so_temporary.rs:23:3
|
23 | example.iter().all(|x| some_condition(x))
| ^^^^^^^-------
| |
| borrowed value does not live long enough
| a temporary with access to the borrow is created here ...
24 | }
| -
| |
| `example` dropped here while still borrowed
| ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `impl std::iter::Iterator`
|
= note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
Теперь, очевидно, примечание в конце ошибки - отличное предложение, и поэтому я ввел временное средство для устранения проблемы. Но я не понимаю почему решает проблему. Чем отличается время жизни моей tmp
переменной от example.iter()
, встроенной непосредственно в выражение, из-за чего один работает, а другой - нет?
std
, не касаясь компилятора. play.rust-lang.org/ - person Peter Hall   schedule 30.01.2021impl Iterator + '_
, иimpl Iterator<Item = &i32>
, используемые в позиции возврата функции, будут разрешены в конкретный типstd::slice::Iter<'_, i32>
и будут вести себя идентично конкретному типу во всех сценариях, без каких-либо дополнительных хаков. или обходные пути. - person pretzelhammer   schedule 31.01.2021