If match isn't ==, so what is it?

Imagine I have a function like:

fn get() -> Option<String> {
    Some("flower".to_string())
}

If I try using something like:

    if Some(_) == get() {
        println!("something is here")
    }

I'm getting error:

error: in expressions, `_` can only be used on the left-hand side of an assignment
  --> /media/sandbox/read/main.rs:32:13
   |
32 |     if Some(_) == get() {
   |             ^ `_` not allowed here

However,

    if Some("car".to_string()) == get() {
        println!("car is here")
    }
    if get().is_some() {
        println!("something is here")
    }

get compiled fine. More interesting that

    match get() {
        None => eprintln!("nothing"),
        Some(_) => println!("something is here"),
    }

has no problem at all. So question is - how does match decide that a variant is matching? If it doesn't use ==, what does it use?

It's "structural", that is, determined by the language, rather than your logic (even if that logic is simply derive(Eq)) - there's no trait and the caller needs to be able to see the internal shape of the data to compare them.

Your code:

if Some(_) == get() {
    println!("something is here")
}

Is essentially trying to create a value Some(_) then compare it at runtime, calling the method Eq::eq. The error message is trying to say that _ only works in "output" locations, to ignore the value.

You can get the effect you're after by using "if let":

if let Some(_) = get() {
    println!("something is here")
}

which is basically just sugar for the match, or the matches! macro, or for this specific case, the .is_some() method.

it uses the type definition, and special cases for primitive types like slice patterns, str literal patterns, etc.

any type can be matched, you don't need to implement any trait, not even marker traits like Copy.

pattern matching is a fundamental language feature, the compilers handles it automatically, while equality comparison is a library implementation, and may invoke user/library code.

Match doesn't use == (PartialEq) at all. It does structural pattern matching. It doesn't run any trait methods; it just looks directly at the enum's memory to check its hidden tag.

Actually, for your specific case (Option), there isn't even a tag. Because a String uses a pointer that can never be null, Rust uses "niche optimization" and just checks if the pointer is null to figure out if it's None.

If you want the compiler to do a pattern match instead of a value comparison in an if statement, use 'if let' or the matches! macro:

It's the other way around. match is a core language feature, == uses match:

impl<T: PartialEq> PartialEq for Option<T> {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Some(l), Some(r)) => *l == *r,
            (Some(_), None) => false,
            (None, Some(_)) => false,
            (None, None) => true,
        }
    }
}

That's a good question, I ask same questions everytime. I like to understand what's going on in assembly side, this is best way for understanding how rust idioms actually works. An enum is nothing more than a collection which contains a discriminant and payload. For example:

enum Foo {
    Bar,
    Baz(String),
    Quu { x: f64, y: f64 },
}

Maximum field count can be 32 or 128 (depends on the runner system (x32, x64, arm, wasm etc)).

In assembly side this contains discriminants (Bar, Baz, Quu) and largest payload (in this example String has largest payload size and it almost 24 bytes).

For let x = Foo::Bar rust allocates 8 byte + 24 byte. When you use match syntax (match or if) it compares discriminant section, if it equals then returns value in payload section. It generates jmp assembly statement. Actually == and match syntaxes uses jmp statement in assembly side for compare. In rust side there are different syntaxes and mindsets of course.

If I'm wrong than someone can fix me, thanks.

Awesome, it's actually what I wanted to know.

Right, since match uses a placeholder, it keeps the compiler happy.

Thanks everyone for the clarification.