Repository: rust
Issue: Further improve diagnostics for expressions in pattern position
Labels: A-diagnostics,A-parser,T-compiler,D-newcomer-roadblock,D-terse,A-patterns

I've had this on my TODO list for a while but never had the time to write a PR for it. Therefore I'm just going to open an issue for it instead.

Since PR #118625 we try to reparse *something* in pattern position as an expression under certain conditions and provide a smarter diagnostic of the form “*expected a pattern, found an expression // arbitrary expressions are not allowed in patterns*” which is already amazing.

However, the current heuristic has a few limitations I'd like to see addressed which should be relatively simple to implement:

1. [x] The heuristic doesn't cover **field accesses** (of the form `$literal.$ident` and so forth) but only things that look like method calls (e.g., `0.f()`). I argue we should also detect expressions like `x.f` and `s.0`. **This would've prevented [#104996](https://github.com/rust-lang/rust/issues/104996) from getting opened!** (addressed in [#123877](https://github.com/rust-lang/rust/pull/123877))
   - [x] Firstly we need to remove the extra check for parentheses located after the `.`-“herald” check.
   - [ ] Then, we should in my opinion check the `Span` to make sure that there's no whitespace/comment before & after the `.` to avoid overzealously emitting this diagnostic when the user accidentally typoed a comma as a dot (as in `(x. y)` ← `(x, y)`) which isn't too farfetched given the keys are right next to each other on most keyboards (just need to check `sp0.hi == sp1.lo`). Of course, this would rule out multi-line method / field chains but that should be rare. We could (as a follow-up) check if the would-be expression is “appropriately” indented (by utilizing `SourceMap` methods) to address that, too. (NOTE: this isn't implemented yet, unclear if we actually want this)
   - [x] The following is a bit opinionated: I think we should remove the capitalization check (at the moment, we don't consider `x.Foo()` to be a method call). If you disagree, we should at least also consider `_` to be a valid start of a field or method name (`x._foo()` doesn't get recognized at the time of writing).
   - [x] We should support sequences of numeric field accesses like `x.0.1` without accidentally flagging `x.0e4` as an expression (`x.0.1` gets lexed as [*Ident*, *Dot*, *FloatLit*]). See [`parse_expr_tuple_field_access_float`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/struct.Parser.html#method.parse_expr_tuple_field_access) for prior art.
2. [x] We should consider the **keyword `as`** to be a “herald” next to `.` to recover `0 as usize` etc. in pattern position (addressed in [#123877](https://github.com/rust-lang/rust/pull/123877)).
3. [ ] We should somehow recover `f().g()` ~~and `(0).f()`~~ etc. meaning more method calls / field accesses where **the “basis” is a more complex expression**. Rephrased: Recognize more “`$expr.$ident`” over just “`$lit_or_ident.$ident`” (the latter is the status quo, roughly, if I'm not mistaken).
   - [x] Recovering from `(0).f()` was addressed in [#123877](https://github.com/rust-lang/rust/pull/123877).
5. [x] We should add a help message (structured or text-based) **instructing the user to extract the expression to a const item**: “*extract the expression to a `const` and refer to that*” (addressed in [#123877](https://github.com/rust-lang/rust/pull/123877)).
6. [x] At some point we should provide a structured multipart suggestion for **wrapping expressions in pattern position in a `const {}` block** (feature `inline_const_pat`). We *could* provide the suggestion if `self.sess.unstable_features.is_nightly_build()` holds but I don't know if others like the idea of that. Note that we cannot check if feature `inline_const_pat` is enabled from inside the parser ~~and *diagnostic stashing/stealing* doesn't help here either since we want to “stash” a *sub*diagnostic (a structured suggestion)~~ not true actually, should be possible to impl (addressed in [#123877](https://github.com/rust-lang/rust/pull/123877).
7. [ ] Various FIXMEs added in https://github.com/rust-lang/rust/pull/123877
<!-- TRIAGEBOT_START -->

<!-- TRIAGEBOT_ASSIGN_START -->

<!-- TRIAGEBOT_ASSIGN_DATA_START$${"user":"ShE3py"}$$TRIAGEBOT_ASSIGN_DATA_END -->

<!-- TRIAGEBOT_ASSIGN_END -->
<!-- TRIAGEBOT_END -->