Using `if let` to check for equality

It's not silly at all, but useful. For example, consider fn foo(Wrap(x): ...) or fn foo((Ok(x) | Err(x): ...).


Yeah, so Rust managed to avoid the usual pitfall of if x = 42, so it shouldn't need Yoda conditions... and yet we still have them. I don't think that's good.

It would probably make sense to continue allowing it for code generation purposes. Suddenly failing to compile Yoda patterns would probably introduce a non-uniformity that would in turn require many macro authors to come up with special cases.

Oh, I didn't suggest we disallow it. We also allow if 42 == x, after all.

I just really dislike it being idiomatic for hand-written code.


I didn't mean the Yoda condition is good -- I was just amused to make the connection. Overall it's a natural edge case for pattern matching though. You can also write a constant let when it's irrefutable, like let () = println!(...);, which is only useful to statically assert the fact that it is constant.

I'm with this guy

I see a lot of questions about more complex syntax and determining scope and whatnot. What if we started by implementing only the minimum-viable syntax (if $expr is $pat {}) and disallow anything more complex at first? This simple form has obvious semantics and would satisfy the 90% use-case right away, and we can worry about how/whether to extend it later.

This was the same approach taken for if let $pat = $expr {}—we deferred dealing with && and other more complex syntax until later

Because that has no significant advantage over matches!().

Note that at this point the thread is very much repeating itself:

So someone with more free time than I currently have (sorry! :sob: ) should probably put up an RFC that spells out the argument: "let's stabilize matches!() since everyone wants it, and no one's been able to come up with a compelling variable bindings story, or any other reason to provide this functionality via a new is keyword". Never mind, I completely missed that this is being stabilized.

1 Like

matches! is already stable in 1.42-beta.


It has no significant advantage in the same way as for-loop has no significant advantage over an explicit loop over an iterator. In other words: yes, it's a sugar construct, but which is significantly easier to type, read and perceive over matches!() ("natural to read" property is quite a nice one). Considering that it covers a sufficient fraction of use-cases, I believe at the very least it's a proposal worth consideration.

Personally I wouldn't be against it, but on my list of "nice to have" features it's quite low.


Bindings are a significant improvement. To put it into code, with is you can do this:

if opt is Some(x) {
    println!("We got ourselves a {}", x);

Correct me if I'm wrong, but that's not possible with matches!(). That is the shortcoming we're talking about.

But that can be done with if let


Yes, but now we're back to yoda conditionals.

if let 42 = x {}

I guess this really is going in circles :smile: I'll abstain.


So just use if let with binders and matches! without binders, then?

That seems like a reasonable approach to me, anyway.

1 Like

To my mind the feature that's really missing is let-else:

    let Some(x) = x else {
        return Err(something_complicated(y));
    // x is unwrapped here
    // compile-time error if this point is reachable from the else block

I know this has been discussed before but I don't know what, if any, conclusions were reached and it's hard to search for.


TL;DR obvious syntax is ambiguous (sadly), focus is on if-let chaining currently (positive case), then potentially moving to the negative case. There is a draft that consistently allows "`let as a boolean-evaluated expression".

1 Like

Nitpick: "equals" is how I'd read ==; let ... = ... should be "let ... equal..." (no 's').

1 Like

Ah, true. "if let forty-two equal x"

On topic, I don't really think we need an is operator, since if-let already works for those usecases anyway, and for simple matching (assuming you don't want to use a constant let, since it reads weirdly: if let Some(42) = x), there's matches!(), so I'm not sure is is worth cluttering the syntax with. Unlike with ? and try!(), I don't think this is a really common thing.

1 Like

I'm tempted to use matches as is; --> is!(x, 42)

Heh, is that allowed under current macro import semantics?

is seems confusing to me, given that in Python (and I think some other languages) it refers to referential equality, which is very different from pattern-matching equality.

And, as mentioned above, introducing new bindings is done with let. The only exceptions I can think of are function arguments and globals. It would be good to maintain this consistency.

1 Like