std::option::Option<std::option::Option<i8>>` doesn't implement `std::fmt::Display`

Hello,

Still busy with the last of rustlings but im stuck again

I have this challenge :

// option2.rs
// Make me compile! Execute `rustlings hint option2` for hints

// I AM NOT DONE

fn main() {
    let optional_value = Some(String::from("rustlings"));
    // Make this an if let statement whose value is "Some" type
    if let value = optional_value {
        Some(("the value of optional value is: {}", value)hint);
    } else {
        Some("The optional value doesn't contain anything!");
    }

    let mut optional_values_vec: Vec<Option<i8>> = Vec::new();
    for x in 1..10 {
        optional_values_vec.push(Some(x));
    }

    // make this a while let statement - remember that vector.pop also adds another layer of Option<T>
    // You can stack `Option<T>`'s into while let and if let
    while let value = optional_values_vec.pop() {
        println!("current value: {}", value);
    }
}

but I see this confusing error message :

error[E0277]: `std::option::Option<std::option::Option<i8>>` doesn't implement `std::fmt::Display`
  --> exercises/option/option2.rs:23:39
   |
23 |         println!("current value: {}", value);
   |                                       ^^^^^ `std::option::Option<std::option::Option<i8>>` cannot be formatted with the default formatter
   |
   = help: the trait `std::fmt::Display` is not implemented for `std::option::Option<std::option::Option<i8>>`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
   = note: required by `std::fmt::Display::fmt`

any hints how to solve this ?

Roelof

while let statements allow for pattern matching. Try to describe the shape of the thing you get from pop, instead of just giving it a name. As the error suggests, you are getting Option<Option<i8>>, and to do something useful with Option, it has to be Some, so most likely the shape you want is Some(Some(value)).

Hmm,

I m thinking this way :

// make this a while let statement - remember that vector.pop also adds another layer of Option<T>
    // You can stack `Option<T>`'s into while let and if let
    while let value = optional_values_vec.pop() {
        if let value = Some(Some(x)) {
            println!("current value: {}", x);
        }
    }

but the compiler does not agree with me

 Compiling of exercises/option/option2.rs failed! Please try again. Here's the output:
error[E0425]: cannot find value `x` in this scope
  --> exercises/option/option2.rs:23:34
   |
23 |         if let value = Some(Some(x)) {
   |                                  ^ not found in this scope

error[E0425]: cannot find value `x` in this scope
  --> exercises/option/option2.rs:24:43
   |
24 |             println!("current value: {}", x);
   |                                           ^ not found in this scope

Dude you're writing it backwards :sweat_smile:

        if let Some(Some(x))  = value {
            println!("current value: {}", x);
        }

you could do:

    while let Some(value) = optional_values_vec.pop() {
        if let Some(x) = value {
            println!("current value: {}", x);
        }
    }

By the way,

while let value = optional_values_vec.pop() {
     //...
}

is an infinite loop.

This is because you have no pattern after let. That means it matches anything, in this case None and Some, and will never stop looping.

1 Like

yep, you are right. Back to the manual how to solve that one

This seems to work :

 while let value = optional_values_vec.pop() {
        if let Some(Some(x))  = value {
            println!("current value: {}", x);
        }
        else{
            break; 
        }
           
    }

or is there a better way ?

That works but a shorter way of doing it is:

while let Some(Some(x)) = optional_values_vec.pop() {
    println!("current value: {}", x);
}

@elsuizo's code also works. The difference is that mine will stop at the first Some(None), while @elsuizo's will stop at the first None.