My take-away from this is that we should lean into the user's confusion by making what they think is a reality an actual reality. That is, the confusion goes entirely away if let PAT = EXPR is actually an expression. This is also a good idea because checking whether an expression matches a pattern is useful. We have a bunch of methods like is_some that implement this in a low-powered way. Many Implementations of PartialEq would also be unnecessary if let was an expression.
This means that if let would still be a used form and now instead of removing the confusion around let possibly being a bool-typed expression, you now also have questions like "Which way should I use?" between the old and the new syntax. Moreover, I think this brings more complexity to the compiler rather than removing some (which let PAT = EXPR being syntactically valid achieves).
Why is that?
I think @CAD97 is right here. Cheatsheets will not be needed. If anything, by making let PAT = EXPR into a syntactically valid expression, as is done in https://github.com/rust-lang/rust/pull/60861, we can turn:
error: expected expression, found statement (`let`)
--> src/lib.rs:2:9
|
2 | bar(let 0 = 1);
| ^^^ expected expression
|
= note: variable declaration using `let` is a statement
into this:
error: `let` expressions are not supported here
--> $DIR/lib.rs:2:9
|
LL | bar(let 0 = 1);
| ^^^^^^^^^
|
= note: only supported directly in conditions of `if`- and `while`-expressions
= note: as well as when nested within `&&` and parenthesis in those conditions
(The way I have implemented this, if you simply remove the emission of this errors then (let 0 = 1): bool is now a semantically valid expression)