Matching error or result in while let

Hello Everyone
I am new in Rust.

I am doing a Hangman game in Rust which reads the words from a file and ask to the user to guess the word by asking the user to enter a character by stdin.

I have the next Structs

pub struct Hangman<'a> {
        pub word: &'a String,
        pub remaining_attempts: i32,
        pub used_chars: &'a mut HashMap<char, ()>,
        pub wrong_chars:&'a mut  HashMap<char, ()>

pub enum GameStatus {
pub struct Stats {
        guessed: String,
        guessed_char: char,
        status: GameStatus

I also have a play method in the impl of Hangman

pub fn play(&mut self, char: char) -> Result<Stats, GameError> {
            let mut guessed: Vec<String> = vec![String::from("_"); self.word.len()];
            // println!("Ingresa una letra");
            let mut input_letter = char;
            let mut found: bool = false;
            let mut stats: Stats = Stats{
                guessed: "".to_string(),
                status: GameStatus::Pending,
                guessed_char: '\0'

            if !self.can_play() {
                return Err(GameError::NoChancesAvailable);

            if self.is_char_already_used(&input_letter) {
                return Err(GameError::CharacterIsAlreadyUsed);

            for (i, c) in (self.get_word_to_guess()).chars().enumerate() {
                if c == input_letter {
                    found = true;
                    guessed[i] = c.to_string();


            if found {
                stats.guessed_char = input_letter;
            } else {

            if guessed.join("") == *self.get_word_to_guess() {
                stats.status = GameStatus::Success;


            return Ok(stats);



use std::fmt;

pub enum GameError {

impl std::error::Error for GameError {}

impl fmt::Display for GameError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            GameError::NoChancesAvailable => write!(f, "No more chances"),
            GameError::CharacterIsAlreadyUsed => write!(f, "Character is already used"),

In I have this function:

fn play(ahorcado: &mut hangman) {
    println!("Please input a char");
    let mut input_char = get_char();
    let mut game =;

I would like to loop the call while stats.stats == GameStatus::Pending
or while GameError::CharacterIsAlreadyUsed error is returned.

I tried a couple of things like while let (while let - Rust By Example)

and also Pattern Matching but I can't achieve what I'm looking for. I got a lot of compiler errors.

I am sorry if I have a lot of bad practices. I just started with the language I am still learning about lifetimes, scopes, etc.


Here are some things which may be helpful:

  • Hangman should probably just own all of its data by removing all the &s and lifetimes from the struct. This will simplify the program a lot already.
  • If you don't need the keys of a HashMap, use a HashSet
  • Use clippy by running cargo clippy to get automated suggestions on how to improve your code

As for the loop, I would suggest using loop and explicitly returning when you detect that the game is over. Something like this

fn play(hangman: &mut Hangman) {
    loop {
        println!("Please input a char");
        let input_char = get_char();
        let game =;
        // do something here to detect if the game is over and return if so


Really thanks for the answer!!

I followed your hints and I ended up to:

loop {
        println!("turnos restantes: {}", ahorcado.get_remaining_attempts());
        println!("Ingresa una letra");
        let input_char = get_char();
        let game =;
        match &game  {
                Ok(stats) => {
                    match stats.status {
                        GameStatus::Success => {
                            println!("Felicitaciones adivino la palabra");
                            println!("La palabra era: {}", ahorcado.word);
                        GameStatus::Pending => {
                        GameStatus::GameOver => {
                            println!("Game over");
                        GameStatus::CharGuessed => {
                            println!("Adivino la siguiente letra: {}", stats.guessed_char);
                            println!("La palabra hasta ahora es: {}", stats.get_guessed_word());
                Err(e) => {
                    match e {
                        GameError::NoChancesAvailable => {
                            eprintln!("Error: {}", e);
                        GameError::CharacterIsAlreadyUsed => eprintln!("Error: {}", e),

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.