Baymax
Baymax

Reputation: 33

"possibly uninitialized variable" when it is initialized inside `match`

This code (playground):

fn main() {
    let fruits = "banana";
    let num = 20;
    let result: i32;

    match fruits {
        "banana" => {
            if num > 100 {
                result = num * 3;
            } else if num > 30 {
                result = num * 4;
            } else {
                result = num * 5;
            }
        }
        "apple" => {
            if num > 100 {
                result = num * 16;
            } else if num > 30 {
                result = num * 18;
            } else {
                result = num * 20;
            }
        }

        _ => println!("wrong fruits option"),
    }
    // if num > 100 { result = num * 3; }
    // else if num > 30 { result = num * 4; }
    // else { result = num * 5;}
    println!("{}", result)
}

Gives the following error:

error[E0381]: borrow of possibly-uninitialized variable: `result`
  --> src/main.rs:31:20
   |
31 |     println!("{}", result)
   |                    ^^^^^^ use of possibly-uninitialized `result`
   |
   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)

As you can see result is initialized in match, so why is compiler giving me an error?

After changing the line

let result : i32;

to (playground)

let mut result = 0;

The code is compiling and working fine.

This is also working (playground):

fn main() {
    // let fruits = "banana";
    let num = 20;
    let result: i32;

    // match fruits {
    //     "banana" => {
    //         if num > 100 {
    //             result = num * 3;
    //         } else if num > 30 {
    //             result = num * 4;
    //         } else {
    //             result = num * 5;
    //         }
    //     }
    //     "apple" => {
    //         if num > 100 {
    //             result = num * 16;
    //         } else if num > 30 {
    //             result = num * 18;
    //         } else {
    //             result = num * 20;
    //         }
    //     }

    //     _ => println!("wrong fruits option"),
    // }
    if num > 100 {
        result = num * 3;
    } else if num > 30 {
        result = num * 4;
    } else {
        result = num * 5;
    }
    println!("{}", result)
}

Upvotes: 3

Views: 2041

Answers (1)

Finomnis
Finomnis

Reputation: 22718

The reason result may be uninitialized is that the _ case does not initialize result.

However, I don't think your intention is to initialize result in that case. The real error here is probably that you probably intended the _ case to be an error case that stops the execution. However, you didn't tell it to stop the execution.

There is multiple ways to solve that:

  • Add a return or exit statement in the _ case
  • Replace the println with a panic
  • Introduce proper error handling by adding a Result return value to main and then return an error.

For the least amount of effort I decided to go with a panic. Just be aware that in production, panics should be the very last solution. Proper error handling with Result and Error is always preferred.

So here's my minimal modification to make it work:

fn main() {
    let fruits = "banana";
    let num = 20;
    let result: i32;

    match fruits {
        "banana" => {
            if num > 100 {
                result = num * 3;
            } else if num > 30 {
                result = num * 4;
            } else {
                result = num * 5;
            }
        }
        "apple" => {
            if num > 100 {
                result = num * 16;
            } else if num > 30 {
                result = num * 18;
            } else {
                result = num * 20;
            }
        }

        _ => panic!("wrong fruits option"),
    }
    // if num > 100 { result = num * 3; }
    // else if num > 30 { result = num * 4; }
    // else { result = num * 5;}
    println!("{}", result)
}

Upvotes: 3

Related Questions