Improve syntax error for misplaced lifetime quantifier (for<'a>) outside of APIT type · Issue #117882 · rust-lang/rust (original) (raw)

Code

fn foo(_f: for<'a> impl FnOnce(&'a str)) {}

Current output

error: expected identifier, found keyword impl --> src/lib.rs:1:20 | 1 | fn foo(_f: for<'a> impl FnOnce(&'a str)) {} | ^^^^ expected identifier, found keyword

error: unexpected lifetime 'a in pattern --> src/lib.rs:1:33 | 1 | fn foo(_f: for<'a> impl FnOnce(&'a str)) {} | ^^ help: remove the lifetime

error: expected one of : or |, found ) --> src/lib.rs:1:40 | 1 | fn foo(_f: for<'a> impl FnOnce(&'a str)) {} | ^ expected one of : or |

error: expected one of (, ), +, ,, ::, or <, found FnOnce --> src/lib.rs:1:25 | 1 | fn foo(_f: for<'a> impl FnOnce(&'a str)) {} | -^^^^^^ expected one of (, ), +, ,, ::, or < | | | help: missing ,

error[E0405]: cannot find trait r#impl in this scope --> src/lib.rs:1:20 | 1 | fn foo(_f: for<'a> impl FnOnce(&'a str)) {} | ^^^^ not found in this scope

error[E0782]: trait objects must include the dyn keyword --> src/lib.rs:1:12 | 1 | fn foo(_f: for<'a> impl FnOnce(&'a str)) {} | ^^^^^^^^^^^^ | help: add dyn keyword before this trait | 1 | fn foo(_f: dyn for<'a> impl FnOnce(&'a str)) {} | +++

Desired output

error: a lifetime quantifier (for<'a>) may not be used here --> src/lib.rs:1:20 | 1 | fn foo(_f: for<'a> impl FnOnce(&'a str)) {} | ^^^^^^^ this quantifier | note: lifetime quantifiers may only be used before fn pointer types and within impl Trait types help: place this for<'a> inside the impl: | 1 | fn foo(_f: impl for<'a> FnOnce(&'a str)) {} | +++++++

Rationale and extra context

I don't remember what the official name for for<'a> syntax in general is, so I've used "quantifier" in the proposed message.

The main thing I'm filing the issue for is that there's a large cascade of syntax errors, none of which explain the actual problem (the leading "expected identifier" is particularly bad), and which seem to be due to poor recovery (starting to parse the rest of the type as a new function parameter, as if there was a comma); it would be nice to have more concise and more helpful output, particularly because for<'a> is a superficially simple "modifier" syntax that does appear in multiple places in types, just not this one.

I hope that it will be simple to fix by making for<'a> something that is always parsed but not always permitted.

Also, rust-analyzer's current diagnostic for this is significantly better just by being a basic parse error: "expected a function pointer or path". It doesn't point the user to the right fix, but it does actually mention what the non-syntax-error cases would be: a fn pointer with lifetimes — or a pre-2021-unmarked-dyn (sigh).

Other cases

No response

Anything else?

Occurs on stable 1.73 and 1.76.0-nightly (2023-11-12 2b603f9)