Предположим следующий надуманный пример:
struct Board {
squares: Vec<i32>,
}
struct Point<'a> {
board: &'a Board,
x: i32,
y: i32,
}
impl<'a> Point<'a> {
pub fn neighbors(&self) -> impl Iterator<Item = Point<'a>> {
[(0, -1), (-1, 0), (1, 0), (1, 0)]
.iter().map(|(dx, dy)| Point {
board: self.board,
x: self.x + dx,
y: self.y + dy,
})
}
}
Это не компилируется, потому что из того, что я понимаю, время жизни точек, созданных в лямбда-выражениях, неверно:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:14:25
|
14 | .iter().map(|(dx, dy)| Point {
| _________________________^
15 | | board: self.board,
16 | | x: self.x + dx,
17 | | y: self.y + dy,
18 | | })
| |_____________^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 12:5...
--> src/main.rs:12:5
|
12 | / pub fn neighbors(&self) -> impl Iterator<Item = Point<'a>> {
13 | | [(0, -1), (-1, 0), (1, 0), (1, 0)]
14 | | .iter().map(|(dx, dy)| Point {
15 | | board: self.board,
... |
18 | | })
19 | | }
| |_____^
= note: ...so that the types are compatible:
expected &&Point<'_>
found &&Point<'a>
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 11:1...
--> src/main.rs:11:1
|
11 | impl<'a> Point<'a> {
| ^^^^^^^^^^^^^^^^^^
note: ...so that return value is valid for the call
--> src/main.rs:12:32
|
12 | pub fn neighbors(&self) -> impl Iterator<Item = Point<'a>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Я немного растерялся относительно того, почему это так, потому что кажется, что жизни здесь имеют смысл. Время жизни Point
обусловлено временем жизни ссылки на Board
. Таким образом, Point<'a>
имеет ссылку на доску с временем жизни 'a
, поэтому он должен иметь возможность создавать больше Point<'a>
s, поскольку их ссылки на доски будут иметь одинаковое время жизни ('a
).
Но, если я уберу лямбду, это сработает:
impl<'a> Point<'a> {
pub fn neighbors(&self) -> [Point<'a>; 4] {
[
Point { board: self.board, x: self.x , y: self.y - 1},
Point { board: self.board, x: self.x - 1, y: self.y },
Point { board: self.board, x: self.x + 1, y: self.y },
Point { board: self.board, x: self.x , y: self.y + 1},
]
}
}
Итак, я подозреваю, что проблема заключается в том, что лямбда может быть запущена после того, как закончится время жизни 'a
. Но значит ли это, что я не могу лениво выдавать эти очки?
tl; dr Как сделать так, чтобы средство проверки заимствований было удовлетворено методом, который лениво создает новые структуры, время жизни которых связано со структурой, создающей их?