Suggest turbofish for multi-param generics used as call arguments - #160104
Suggest turbofish for multi-param generics used as call arguments#160104martonmoro wants to merge 1 commit into
Conversation
|
The parser was modified, potentially altering the grammar of (stable) Rust cc @fmease |
|
Thanks for the pull request, and welcome! The Rust Project is excited to review your changes, and you should hear from @hanna-kruppe (or someone else) some time within the next two weeks. Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (
Why was this reviewer chosen?The reviewer was selected based on:
|
|
I’m not familiar enough with the parser code to review this, and won’t have time to get familiar with it, so: @rustbot reroll |
| @@ -0,0 +1,24 @@ | |||
| struct Many<A, B, C, D> { | |||
There was a problem hiding this comment.
can we use run-rustfix for this test?
| let failed = self.create_snapshot_for_diagnostic(); | ||
| self.restore_snapshot(start); | ||
| match self.parse_paren_comma_seq(|p| { | ||
| let expr = p.parse_expr_catch_underscore(Restrictions::empty())?; |
There was a problem hiding this comment.
The fallback here reparses the entire argument list and applies recovery to every Binary(Lt). If a later argument causes the initial parse failure, earlier valid comparisons are reconsidered.
For example this code:
struct S;
struct Many<A, B, C, D>(A, B, C, D);
impl<A, B, C, D> Many<A, B, C, D> {
fn new() -> Self {
todo!()
}
}
fn take_three(_: bool, _: bool, _: Many<i32, Many<(), i32, S, S>, i32, i32>) {}
fn main() {
let (a, b, c, d) = (1, 2, 3, 4);
take_three(a < b, c > (d), Many<i32, Many<(), i32, S, S>, i32, i32>::new());
}the current output is:
--> /tmp/now.rs:14:16
|
14 | take_three(a < b, c > (d), Many<i32, Many<(), i32, S, S>, i32, i32>::new());
| ^^^^^
|
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
14 | take_three(a ::< b, c > (d), Many<i32, Many<(), i32, S, S>, i32, i32>::new());
| ++
error: generic args in this position require the turbofish syntax
--> /tmp/now.rs:14:32
|
14 | take_three(a < b, c > (d), Many<i32, Many<(), i32, S, S>, i32, i32>::new());
| ^^^^^^^^
|
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
14 | take_three(a < b, c > (d), Many::<i32, Many<(), i32, S, S>, i32, i32>::new());
| ++
error[E0061]: this function takes 3 arguments but 2 arguments were supplied
--> /tmp/now.rs:14:5
|
14 | take_three(a < b, c > (d), Many<i32, Many<(), i32, S, S>, i32, i32>::new());
| ^^^^^^^^^^----------------------------------------------------------------- argument #3 of type `Many<i32, Many<(), i32, S, S>, i32, i32>` is missing
|
note: function defined here
--> /tmp/now.rs:10:4
|
10 | fn take_three(_: bool, _: bool, _: Many<i32, Many<(), i32, S, S>, i32, i32>) {}
| ^^^^^^^^^^ -------------------------------------------
help: provide the argument
|
14 | take_three(a < b, c > (d), Many<i32, Many<(), i32, S, S>, i32, i32>::new(), /* Many<i32, Many<(), i32, S, S>, i32, i32> */);
| ++++++++++++++++++++++++++++++++++++++++++++++++which is wrong.
The nightly output for this code is :
error: expected expression, found `,`
--> src/main.rs:14:61
|
14 | take_three(a < b, c > (d), Many<i32, Many<(), i32, S, S>, i32, i32>::new());
| ^ expected expressionwhich points out the rootcause.
| // The attempt above can emit diagnostics before it fails (like in | ||
| // `tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs`), and parsing again the same | ||
| // tokens would emit them a second time. | ||
| if self.dcx().err_count() != err_count { |
There was a problem hiding this comment.
seems like a hack here.
| let failed = self.create_snapshot_for_diagnostic(); | ||
| self.restore_snapshot(start); | ||
| match self.parse_paren_comma_seq(|p| { | ||
| let expr = p.parse_expr_catch_underscore(Restrictions::empty())?; |
There was a problem hiding this comment.
generally, i don't like the way of repeat the same parsing here, can we do in the way of stop where error happened and try to speculatively detect a missing turbofish.
This comment has been minimized.
This comment has been minimized.
ae1ac48 to
e0bdad9
Compare
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
|
@chenyukang, thank you for the review! I reworked it, and now the whole argument list retry is gone. Now it records candidate |
Fixes #159745
When parsing
bar(Many<i32, Many<(), i32, S, S>, i32, i32>::new())the parser reads<asBinary(Lt)and the comma as the end of argument 1. At>it tries to parse a RHS and finds a barecomma, hence
expected expression, found ',', and the rest of the "arguments" are parsed wrong.parse_expr_paren_seqnow parses the list once, noting each argument that came out asBinary(Lt).If a later argument fails to parse, it walks those candidates nearest-first and checks whether the
rest is generic args followed by
::or(. If none prove out, the parser is restored to where it died and the originalerror is returned untouched.