I think I got it sorted out. Luckily everything builds just fine after pushing through a handful of errors.
Original Error
Ok. Here is the full error I saw when I tried to build your crate.
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/game.rs:42:31
|
42 | player.add_card(self.deck.draw_white().unwrap())?;
| ^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 39:2...
--> src/game.rs:39:2
|
39 | pub fn deal_hands(&self) -> Result<(), Box<dyn std::error::Error>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/game.rs:42:21
|
42 | player.add_card(self.deck.draw_white().unwrap())?;
| ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'c` as defined on the impl at 20:6...
--> src/game.rs:20:6
|
20 | impl<'c> Game<'c> {
| ^^
note: ...so that the types are compatible
--> src/game.rs:42:12
|
42 | player.add_card(self.deck.draw_white().unwrap())?;
| ^^^^^^^^
= note: expected `&mut Player<'_>`
found `&mut Player<'c>`
It looks like the problem is actually with deal_hands()
. Rather than allowing the lifetime of &self
to be elided, you need to specify the lifetime as &'c mut self
. (The mut
is because you are mutating self.players
.) I’m not totally sure why Rust doesn’t elide the lifetime of self
to 'c
, but that’s probably another topic.
Next Error
The next error I ran into was
error: captured variable cannot escape `FnMut` closure body
--> src/game.rs:106:17
|
106 | .map(|num| player.play_card_by_index(num as usize))
| - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a reference to a
captured variable which escapes the closure body
| |
| inferred to be a `FnMut` closure
|
= note: `FnMut` closures only have access to their captured variables while they are executing...
= note: ...therefore, they cannot allow references to captured variables to escape
For this one, the problem is actually not in the error message. You need to specify the lifetime of Card
in the return value of .play_card_by_index()
because otherwise it’s not clear that the reference to Card
actually outlives the closure. This means you need to adjust .play_card_by_index()
to return &'c Card' instead of
&Card`.
Final Error
There was a trivial error in your .get_player_names()
. You just need to use .iter()
instead of .into_iter()
because the former will not take ownership of self
. Also, you probably want to .clone()
the player names too for a similar reason.
Full Diff
Here’s the full diff
diff --git a/src/game.rs b/src/game.rs
index 573d09d..5ccbf6b 100644
--- a/src/game.rs
+++ b/src/game.rs
@@ -36,7 +36,7 @@ impl<'c> Game<'c> {
/// Hands need to be filled on every turn, so this lets us fill everyones'
/// hands at once.
- pub fn deal_hands(&self) -> Result<(), Box<dyn std::error::Error>> {
+ pub fn deal_hands(&'c mut self) -> Result<(), Box<dyn std::error::Error>> {
for player in &mut self.players {
while player.hand.len() < player.max_hand_size {
player.add_card(self.deck.draw_white().unwrap())?;
@@ -124,7 +124,10 @@ impl<'c> Game<'c> {
}
pub fn get_player_names(&self) -> Vec<String> {
- self.players.into_iter().map(|player| player.name).collect()
+ self.players
+ .iter()
+ .map(|player| player.name.clone())
+ .collect()
}
}
diff --git a/src/player.rs b/src/player.rs
index 4bd6848..9f95373 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -46,7 +46,7 @@ impl<'c> Player<'c> {
/// Used in the TUI, we can play a card by index and get the reference
/// to the card we played
- pub fn play_card_by_index(&mut self, index: usize) -> & Card {
+ pub fn play_card_by_index(&mut self, index: usize) -> &'c Card {
self.hand.remove(index)
}
@@ -56,7 +56,7 @@ impl<'c> Player<'c> {
/// instead of making the card on the client and sending the full card info,
/// we can just send the UUID[s] of the cards that were played with some
/// data about the order they were played in.
- pub fn play_card_by_uuid(&mut self, uuid: Uuid) -> Option<& Card> {
+ pub fn play_card_by_uuid(&mut self, uuid: Uuid) -> Option<&Card> {
// TODO: Find a better way to do this
let mut index_of_card: usize = self.hand.len() + 1;
for (index, card) in self.hand.iter().enumerate() {
Good Luck!
This looks like a fun project. I hope you continue to build it in Rust!
CLICK HERE to find out more related problems solutions.