The trait object vs. impl Trait
(i.e., dynamic vs. static existential) is a red herring. Your problem is that you are using .iter()
where you actually need .into_iter()
(which would return a reference to a local), and you are trying to use lifetime elision in the return type when there are more than one reference parameters (in which case the compiler simply can't figure out which argument to tie the return type to).
Here's the correct diff:
diff --git a/rs/src/mgen.rs b/rs/src/mgen.rs
index a584098..94af17e 100644
--- a/rs/src/mgen.rs
+++ b/rs/src/mgen.rs
@@ -90,29 +90,26 @@ pub fn moves(
};
let bm_board = bm_white | bm_black;
- // concat faster than flat_map collect
- itertools::concat(
- board
- .iter()
- .enumerate()
- .filter(|(_, &p)| p != NIL && p.colour == colour)
- //.flat_map(|(frm, &p)| match p {
- .map(|(frm, &p)| match p {
- N1 | N2 => knight_moves(board, frm, bm_own),
- K1 | K2 => king_moves(board, frm, bm_own, bm_board, end_game, can_castle, colour),
- P1 | P2 => pawn_moves(board, frm, last, bm_opp, bm_board, colour),
- R1 | R2 => ray_moves(board, frm, BM_ROOK_MOVES[frm], bm_board, bm_own),
- B1 | B2 => ray_moves(board, frm, BM_BISHOP_MOVES[frm], bm_board, bm_own),
- Q1 | Q2 => ray_moves(board, frm, BM_QUEEN_MOVES[frm], bm_board, bm_own),
- _ => Vec::new(),
- }), //.collect()
- )
+ board
+ .iter()
+ .enumerate()
+ .filter(|(_, &p)| p != NIL && p.colour == colour)
+ .flat_map(|(frm, &p)| match p {
+ N1 | N2 => knight_moves(board, frm, bm_own),
+ K1 | K2 => king_moves(board, frm, bm_own, bm_board, end_game, can_castle, colour),
+ P1 | P2 => pawn_moves(board, frm, last, bm_opp, bm_board, colour),
+ R1 | R2 => ray_moves(board, frm, BM_ROOK_MOVES[frm], bm_board, bm_own),
+ B1 | B2 => ray_moves(board, frm, BM_BISHOP_MOVES[frm], bm_board, bm_own),
+ Q1 | Q2 => ray_moves(board, frm, BM_QUEEN_MOVES[frm], bm_board, bm_own),
+ _ => Box::new(core::iter::empty()),
+ })
+ .collect()
}
-fn knight_moves(board: &[Piece; 64], frm: usize, bm_own: u64) -> Vec<Move> {
- bm2vec(BM_KNIGHT_MOVES[frm] & !bm_own)
- .iter()
- .map(|&to| Move {
+fn knight_moves(board: &[Piece; 64], frm: usize, bm_own: u64) -> Box<dyn Iterator<Item = Move> + '_> {
+ Box::new(bm2vec(BM_KNIGHT_MOVES[frm] & !bm_own)
+ .into_iter()
+ .map(move |to| Move {
frm,
to,
castle: false,
@@ -120,17 +117,16 @@ fn knight_moves(board: &[Piece; 64], frm: usize, bm_own: u64) -> Vec<Move> {
kill: (board[to], to),
val: pval(board[frm], to) - pval(board[frm], frm) - pval(board[to], to),
hash: phashkey(board[frm], to) ^ phashkey(board[frm], frm) ^ phashkey(board[to], to),
- })
- .collect::<Vec<Move>>()
+ }))
}
-fn ray_moves(board: &[Piece; 64], frm: usize, moves: u64, bm_board: u64, bm_own: u64) -> Vec<Move> {
+fn ray_moves(board: &[Piece; 64], frm: usize, moves: u64, bm_board: u64, bm_own: u64) -> Box<dyn Iterator<Item = Move> + '_> {
let bl: u64 = bm2vec(moves & bm_board)
.iter()
.fold(0, |a, i| a | BM_BLOCKED[frm][*i]);
- bm2vec(moves & !bl & !bm_own)
- .iter()
- .map(|&to| Move {
+ Box::new(bm2vec(moves & !bl & !bm_own)
+ .into_iter()
+ .map(move |to| Move {
frm,
to,
castle: false,
@@ -138,19 +134,18 @@ fn ray_moves(board: &[Piece; 64], frm: usize, moves: u64, bm_board: u64, bm_own:
kill: (board[to], to),
val: pval(board[frm], to) - pval(board[frm], frm) - pval(board[to], to),
hash: phashkey(board[frm], to) ^ phashkey(board[frm], frm) ^ phashkey(board[to], to),
- })
- .collect::<Vec<Move>>()
+ }))
}
-fn pawn_moves(
- board: &[Piece; 64],
+fn pawn_moves<'a>(
+ board: &'a [Piece; 64],
frm: usize,
- last: Option<&Move>,
+ last: Option<&'a Move>,
bm_opp: u64,
bm_board: u64,
colour: bool,
-) -> Vec<Move> {
- let mut l = bm2vec(match colour {
+) -> Box<dyn Iterator<Item = Move> + 'a> {
+ let iter = bm2vec(match colour {
WHITE => {
(BM_PAWN_CAPTURES[0][frm] & bm_opp)
| (BM_PAWN_STEP1[0][frm] & !bm_board)
@@ -163,8 +158,8 @@ fn pawn_moves(
| ((BM_PAWN_STEP1[1][frm] & !bm_board) >> 1) & (BM_PAWN_STEP2[1][frm] & !bm_board)
}
})
- .iter()
- .map(|&to| Move {
+ .into_iter()
+ .map(move |to| Move {
frm,
to,
castle: false,
@@ -172,8 +167,7 @@ fn pawn_moves(
kill: (board[to], to),
val: pval(board[frm], to) - pval(board[frm], frm) - pval(board[to], to),
hash: phashkey(board[frm], to) ^ phashkey(board[frm], frm) ^ phashkey(board[to], to),
- })
- .collect::<Vec<Move>>();
+ });
// en passant
if let Some(m) = last {
@@ -185,10 +179,10 @@ fn pawn_moves(
(1, m.frm + 1)
};
- l.extend(
+ return Box::new(iter.chain(
bm2vec(BM_PAWN_CAPTURES[cidx][frm] & 1 << idx)
- .iter()
- .map(|&to| Move {
+ .into_iter()
+ .map(move |to| Move {
frm,
to,
castle: false,
@@ -199,22 +193,22 @@ fn pawn_moves(
^ phashkey(board[frm], frm)
^ phashkey(board[to], to),
})
- .collect::<Vec<Move>>(),
- );
+ ));
}
}
- l
+
+ Box::new(iter)
}
-fn king_moves(
- board: &[Piece; 64],
+fn king_moves<'a>(
+ board: &'a [Piece; 64],
frm: usize,
bm_own_pieces: u64,
bm_board: u64,
end_game: bool,
- can_castle: &[bool; 4],
+ can_castle: &'a [bool; 4],
colour: bool,
-) -> Vec<Move> {
+) -> Box<dyn Iterator<Item = Move> + 'a> {
// change king valuation in end_game
let p = match (colour, end_game) {
(WHITE, false) => K1,
@@ -242,9 +236,9 @@ fn king_moves(
K2, R2, 55, 63, 39,),
];
- bm2vec(BM_KING_MOVES[frm] & !bm_own_pieces)
- .iter()
- .map(|&to| Move {
+ Box::new(bm2vec(BM_KING_MOVES[frm] & !bm_own_pieces)
+ .into_iter()
+ .map(move |to| Move {
frm,
to,
castle: false,
@@ -254,22 +248,21 @@ fn king_moves(
hash: phashkey(board[frm], to) ^ phashkey(board[frm], frm) ^ phashkey(board[to], to),
})
.chain(
- cc2.iter()
- .filter(|(c, _, _, _, _, _)| *c)
- .map(|(_, k, r, to, rfrm, rto)| Move {
+ cc2.into_iter()
+ .filter(|&(c, _, _, _, _, _)| c)
+ .map(move |(_, k, r, to, rfrm, rto)| Move {
frm,
- to: *to,
+ to: to,
castle: true,
transform: (NIL, NIL),
- kill: (NIL, *to),
- val: pval(p, *to) - pval(p, frm) + pval(*r, *rto) - pval(*r, *rfrm),
- hash: phashkey(*k, *to)
- ^ phashkey(*k, frm)
- ^ phashkey(*r, *rto)
- ^ phashkey(*r, *rfrm),
+ kill: (NIL, to),
+ val: pval(p, to) - pval(p, frm) + pval(r, rto) - pval(r, rfrm),
+ hash: phashkey(k, to)
+ ^ phashkey(k, frm)
+ ^ phashkey(r, rto)
+ ^ phashkey(r, rfrm),
}),
- )
- .collect::<Vec<Move>>()
+ ))
}
fn transform(to: usize, colour: bool) -> (Piece, Piece) {