-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
in which parentheses are suggested for should-have-been-tuple-patterns #48527
in which parentheses are suggested for should-have-been-tuple-patterns #48527
Conversation
604a8a1
to
2a5fec6
Compare
src/libsyntax/parse/parser.rs
Outdated
// suggestion-enhanced error here rather than choking on the comma | ||
// later. | ||
if let PatKind::Ident(_, _, ref sub) = pat.node { | ||
if sub.is_none() { // just `ident`, not `ident @ pattern` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PatKind::Ident
and sub.is_none
here are artificial restrictions.
What we want is to parse PAT, PAT, ..., PAT
instead of just PAT
and return PatKind::Tuple
containing those patterns.
It's not very important if those pattern are identifiers or not - if we can easily recover more, we should do it.
(You may want to modify parse_pat_tuple_elements
to return partial result even in case of failure.)
If supporting |
2a5fec6
to
d615130
Compare
@petrochenkov updated (force-push)
You're right; fixed.
The second commit here (d615130) revives the partial-result type from the abandoned #46721. This lets us check subsequent code that makes use of the destructured variables, which I think is exciting!—
(On master, we never get to the type error because parsing was interrupted by the bad pattern. With the first commit (ed6679c) but without d615130, the compiler will think that But there are other situations where autotupling can be misleading:
(The E0658 suggestion is wrong, and the E0308 diagnostic in isolation makes it look like we support Python-like parenless tuples, which we don't.) What do you think? |
(Travis failure is only because I rebased on master without being aware of #48449.) |
On further thought, I'm leaning toward the position that the incongruous type errors "downstream" are bad enough that we actually shouldn't try to recover more than the original error did. That is: |
@zackmdavis I agree with your assessment. Another (more involved) option would be to set the type of the tuple elements to In the meantime, I think it is very reasonable to bail out on the enclosing scope and continue (what you're doing). That way the rest of the code will be type checked. |
d615130
to
a36e77c
Compare
(force-pushed a more conservative version that returns r? @estebank |
Recovery is not required to be 100% correct, it's guessing by definition, it should only be correct in most cases. That said, even without recovery this is a nice improvement. |
📌 Commit a36e77c has been approved by |
💡 This pull request was already approved, no need to approve it again.
|
📌 Commit a36e77c has been approved by |
a36e77c
to
117a9fe
Compare
(rebased) |
The rebase seems to have messed the parsing up:
|
src/libsyntax/parse/parser.rs
Outdated
// later. | ||
let comma_span = self.span; | ||
self.bump(); | ||
if let Err(mut err) = self.parse_parenthesized_pat_list() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd keep fn parse_parenthesized_pat_list
but factor out fn parse_pat_list
out of it and use it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.
Programmers used to working in some other languages (such as Python or Go) might expect to be able to destructure values with comma-separated identifiers but no parentheses on the left side of an assignment. Previously, the first name in such code would get parsed as a single-indentifier pattern—recognizing, for example, the `let a` in `let a, b = (1, 2);`—whereupon we would have a fatal syntax error on seeing an unexpected comma rather than the expected semicolon (all the way nearer to the end of `parse_full_stmt`). Instead, let's look for that comma when parsing the pattern, and if we see it, momentarily make-believe that we're parsing the remaining elements in a tuple pattern, so that we can suggest wrapping it all in parentheses. We need to do this in a separate wrapper method called on the top-level pattern (or `|`-patterns) in a `let` statement, `for` loop, `if`- or `while let` expression, or match arm rather than within `parse_pat` itself, because `parse_pat` gets called recursively to parse the sub-patterns within a tuple pattern. Resolves rust-lang#48492.
117a9fe
to
1f04597
Compare
(updated) |
@bors r+ rollup |
📌 Commit 1f04597 has been approved by |
…ion_of_tuples, r=estebank in which parentheses are suggested for should-have-been-tuple-patterns ![destructure_suggest_parens](https://user-images.githubusercontent.com/1076988/36638335-48b082d4-19a7-11e8-9726-0d043544df2f.png) Programmers used to working in some other languages (such as Python or Go) might expect to be able to destructure values with comma-separated identifiers but no parentheses on the left side of an assignment. Previously, the first name in such code would get parsed as a single-indentifier pattern—recognizing, for example, the `let a` in `let a, b = (1, 2);`—whereupon we would have a fatal syntax error on seeing an unexpected comma rather than the expected semicolon (all the way nearer to the end of `parse_full_stmt`). Instead, let's look for that comma when parsing the pattern, and if we see it, make-believe that we're parsing the remaining elements in a tuple pattern, so that we can suggest wrapping it all in parentheses. We need to do this in a separate wrapper method called on a "top-level" pattern, rather than within `parse_pat` itself, because `parse_pat` gets called recursively to parse the sub-patterns within a tuple pattern. ~~We could also do this for `match` arms, `if let`, and `while let`, but we elect not to in this patch, as it seems less likely for users to make the mistake in those contexts.~~ Resolves rust-lang#48492. r? @petrochenkov
Programmers used to working in some other languages (such as Python or
Go) might expect to be able to destructure values with comma-separated
identifiers but no parentheses on the left side of an assignment.
Previously, the first name in such code would get parsed as a
single-indentifier pattern—recognizing, for example, the
let a
inlet a, b = (1, 2);
—whereupon we would have a fatal syntaxerror on seeing an unexpected comma rather than the expected semicolon
(all the way nearer to the end of
parse_full_stmt
).Instead, let's look for that comma when parsing the pattern, and if we
see it, make-believe that we're parsing the remaining elements in a
tuple pattern, so that we can suggest wrapping it all in parentheses. We
need to do this in a separate wrapper method called on a "top-level"
pattern, rather than within
parse_pat
itself, becauseparse_pat
gets called recursively to parsethe sub-patterns within a tuple pattern.
We could also do this formatch
arms,if let
, andwhile let
, butwe elect not to in this patch, as it seems less likely for users to make
the mistake in those contexts.
Resolves #48492.
r? @petrochenkov