HiveBrain v1.2.0
Get Started
← Back to all entries
snippetrustModerate

How can I pattern match against an Option<String>?

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
howstringoptionagainstcanpatternmatch

Problem

I can straight-forwardly match a String in Rust:

let a = "hello".to_string();

match &a[..] {
    "hello" => {
        println!("Matches hello");
    }
    _ => panic!(),
}


If I have an option type, it fails:

match Some(a) {
    Some("hello") => {
        println!("Matches some hello");
    }
    _ => panic!(),
}


because the types don't match:

error[E0308]: mismatched types
--> src/main.rs:5:14
|
5 | Some("hello") => {
| ^^^^^^^ expected struct
std::string::String, found reference
|
= note: expected type
std::string::String
found type
&'static str


I can't do the [..] trick because we have an Option. The best that
I have come up with so far is:

match Some(a) {
    Some(b) => match (&b[..]) {
        "hello" => {
            println!("Matches some, some hello");
        }
        _ => panic!(),
    },
    None => panic!(),
}


which works but is terrible for its verbosity.

In this case, my code is just an example. I do not control the creation of either the String or the Some(String) — so I can't change this type in reality as I could do in my example.

Any other options?

Solution

It's a known limitation of Rust's patterns.

Method calls (including internal methods for operators like ==) automatically call .deref() as needed, so String gets automagically turned into &str for comparisons with literals.

On the other hand, the patterns are quite literal in their comparisons, and find that String and &str are different.

There are two solutions:

-
Change Option to Option before matching on it: Some(a).as_deref(). The as_deref() is a combo of as_ref() that makes Option (preventing move), and deref()/as_str() then unambiguously references it as a &str.

-
Use match guard: match Some(a) { Some(ref s) if s == "hello" => … }. Some(ref s) matches any String, and captures it as s: &String, which you can then compare in the if guard which does the usual flexible coercions to make it work.

See also:

  • Converting from Option to Option

Context

Stack Overflow Q#48034119, score: 46

Revisions (0)

No revisions yet.