Hello everyone.
In my journey to learn Rust, I am stuck trying to understand why this makes sense, instead of this.
I am hoping someone would be kind enough to explain the why and what is really going on here.
To reiterate:
- by using
return x;
(with the semicolon) in that playground example, wherex
ispossible.drain().filter(is_valid_position).collect()
, there are no compilation errors due to compiler knowing that the lifetime ofpossible.drain()
ends on that same line, which means it ends before the lifetime ofpossible
(which is at end of function). Note: an equivalent toreturn x;
, at least in this case, would belet a=x; return a
(semicolon afterreturn a
is irrelevant here). - however, in the other case: by using
x
or, what I understand to be its equivalent,return x
(without semicolons), the compiler complainserror[E0597]: possible does not live long enough
seemingly becausepossible.drain()
andpossible
both have lifetimes which end at the same place which is at function end, as I understand it. In which case I have to ask why doesn't this apply thennote: values in a scope are dropped in the opposite order they are created
? Shouldn't the compiler know to do that ? Maybe I'm missing critical information about this. Please help me understand this.
Just in case playground or gist aren't available in the future, or for other reasons, here is that example code, duplicated here:
use std::collections::HashSet;
type Position = (usize, usize);
const SIZE: usize = 19;
fn is_valid_position(p: &Position) -> bool {
let x = p.0;
let y = p.1;
x < SIZE && y < SIZE
}
fn get_neighbours(x: usize, y: usize) -> HashSet<Position> {
let mut possible: HashSet<Position> = HashSet::new();
possible.insert((x.wrapping_sub(1), y));
possible.insert((x + 1, y));
possible.insert((x, y.wrapping_sub(1)));
possible.insert((x, y + 1));
possible.drain().filter(is_valid_position).collect()
}
fn main() {
println!("{:?}", get_neighbours(0, 1))
}
Cheers!