-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Implement destructuring assignment #71156
Conversation
r? @estebank (rust_highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
src/test/ui/destructuring-assignment/tuple_struct_destructure.rs
Outdated
Show resolved
Hide resolved
@@ -16,4 +16,7 @@ fn main() { | |||
assert_eq!((a, b), (2, 2)); | |||
(b, ..) = (5, 6, 7); | |||
assert_eq!(b, 5); | |||
|
|||
// Check the empty tuple. | |||
() = (); |
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.
This is quite amusing.
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.
since the assignment expression returns ()
this means the following is now valid Rust:
()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=();
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.
A beautiful addition to the weird-exprs
test.
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.
Add it to the weird-exprs.rs
test :)
src/librustc_ast/mut_visit.rs
Outdated
@@ -1225,7 +1226,9 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { kind, id, span, attrs }: &mut Expr, | |||
ExprKind::Struct(path, fields, expr) => { | |||
vis.visit_path(path); | |||
fields.flat_map_in_place(|field| vis.flat_map_field(field)); | |||
visit_opt(expr, |expr| vis.visit_expr(expr)); | |||
if let StructRest::Base(expr) = expr { |
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.
Would it be better to write this as a match
with all the cases expanded?
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.
This case is only ever going to apply to one variant, so I don't think there's danger of missing anything like this.
☔ The latest upstream changes (presumably #69274) made this pull request unmergeable. Please resolve the merge conflicts. |
0c87939
to
bcd08a3
Compare
☔ The latest upstream changes (presumably #71828) made this pull request unmergeable. Please resolve the merge conflicts. |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
@rustbot modify labels to +S-waiting-on-author -S-waiting-on-review |
I hope to see this ergonomy improvement in Rust |
@fanzier Any updates on this PR? |
@Muirrum the RFC rust-lang/rfcs#2909 have to be merged first before this PR can be progressed. |
The most basic use case: To replace: Probably unrelated: with const generics I sometimes wish to do something like this:
|
5c8c229
to
c25779a
Compare
I tried to rebase this branch first but there was a conflict with the PR #77283, which doesn't work anymore with the desugaring in this PR. As a consequence, the test Edit: To be clear, this is just a regression in the diagnostics: the help message is missing. |
As suggested by @petrochenkov, I've opened a new PR just for tuple destructuring as a first step: #78748. |
…enkov Implement destructuring assignment for tuples This is the first step towards implementing destructuring assignment (RFC: rust-lang/rfcs#2909, tracking issue: rust-lang#71126). This PR is the first part of rust-lang#71156, which was split up to allow for easier review. Quick summary: This change allows destructuring the LHS of an assignment if it's a (possibly nested) tuple. It is implemented via a desugaring (AST -> HIR lowering) as follows: ```rust (a,b) = (1,2) ``` ... becomes ... ```rust { let (lhs0,lhs1) = (1,2); a = lhs0; b = lhs1; } ``` Thanks to `@varkor` who helped with the implementation, particularly around default binding modes. r? `@petrochenkov`
☔ The latest upstream changes (presumably #78889) made this pull request unmergeable. Please resolve the merge conflicts. Note that reviewers usually do not review pull requests until merge conflicts are resolved! Once you resolve the conflicts, you should change the labels applied by bors to indicate that your PR is ready for review. Post this as a comment to change the labels:
|
Can someone confirm I'm understanding this correctly? The following will be converted
to
|
yes, except it would work like this: let tup = (1, 2);
(_, x) = tup; to let tup = (1, 2);
let (_, lhs2) = tup;
x = lhs2; |
…ing, r=petrochenkov Implement destructuring assignment for structs and slices This is the second step towards implementing destructuring assignment (RFC: rust-lang/rfcs#2909, tracking issue: rust-lang#71126). This PR is the second part of rust-lang#71156, which was split up to allow for easier review. Note that the first PR (rust-lang#78748) is not merged yet, so it is included as the first commit in this one. I thought this would allow the review to start earlier because I have some time this weekend to respond to reviews. If `@petrochenkov` prefers to wait until the first PR is merged, I totally understand, of course. This PR implements destructuring assignment for (tuple) structs and slices. In order to do this, the following *parser change* was necessary: struct expressions are not required to have a base expression, i.e. `Struct { a: 1, .. }` becomes legal (in order to act like a struct pattern). Unfortunately, this PR slightly regresses the diagnostics implemented in rust-lang#77283. However, it is only a missing help message in `src/test/ui/issues/issue-77218.rs`. Other instances of this diagnostic are not affected. Since I don't exactly understand how this help message works and how to fix it yet, I was hoping it's OK to regress this temporarily and fix it in a follow-up PR. Thanks to `@varkor` who helped with the implementation, particularly around the struct rest changes. r? `@petrochenkov`
…ing, r=petrochenkov Implement destructuring assignment for structs and slices This is the second step towards implementing destructuring assignment (RFC: rust-lang/rfcs#2909, tracking issue: rust-lang#71126). This PR is the second part of rust-lang#71156, which was split up to allow for easier review. Note that the first PR (rust-lang#78748) is not merged yet, so it is included as the first commit in this one. I thought this would allow the review to start earlier because I have some time this weekend to respond to reviews. If ``@petrochenkov`` prefers to wait until the first PR is merged, I totally understand, of course. This PR implements destructuring assignment for (tuple) structs and slices. In order to do this, the following *parser change* was necessary: struct expressions are not required to have a base expression, i.e. `Struct { a: 1, .. }` becomes legal (in order to act like a struct pattern). Unfortunately, this PR slightly regresses the diagnostics implemented in rust-lang#77283. However, it is only a missing help message in `src/test/ui/issues/issue-77218.rs`. Other instances of this diagnostic are not affected. Since I don't exactly understand how this help message works and how to fix it yet, I was hoping it's OK to regress this temporarily and fix it in a follow-up PR. Thanks to ``@varkor`` who helped with the implementation, particularly around the struct rest changes. r? ``@petrochenkov``
As all three parts of this PR (#78748, #78836, #79016) have been merged (or at least approved), I'll close this PR. A huge thank you to @petrochenkov for reviewing them so quickly and thoroughly, catching a few bugs in the process! |
test: add `()=()=()=...` to weird-exprs.rs Idea from rust-lang#71156 (comment) 😄 Builds on nightly since rust-lang#78748 has been merged.
…ing, r=petrochenkov Implement destructuring assignment for structs and slices This is the second step towards implementing destructuring assignment (RFC: rust-lang/rfcs#2909, tracking issue: rust-lang#71126). This PR is the second part of rust-lang#71156, which was split up to allow for easier review. Note that the first PR (rust-lang#78748) is not merged yet, so it is included as the first commit in this one. I thought this would allow the review to start earlier because I have some time this weekend to respond to reviews. If ``@petrochenkov`` prefers to wait until the first PR is merged, I totally understand, of course. This PR implements destructuring assignment for (tuple) structs and slices. In order to do this, the following *parser change* was necessary: struct expressions are not required to have a base expression, i.e. `Struct { a: 1, .. }` becomes legal (in order to act like a struct pattern). Unfortunately, this PR slightly regresses the diagnostics implemented in rust-lang#77283. However, it is only a missing help message in `src/test/ui/issues/issue-77218.rs`. Other instances of this diagnostic are not affected. Since I don't exactly understand how this help message works and how to fix it yet, I was hoping it's OK to regress this temporarily and fix it in a follow-up PR. Thanks to ``@varkor`` who helped with the implementation, particularly around the struct rest changes. r? ``@petrochenkov``
…etrochenkov Make `_` an expression, to discard values in destructuring assignments This is the third and final step towards implementing destructuring assignment (RFC: rust-lang/rfcs#2909, tracking issue: rust-lang#71126). This PR is the third and final part of rust-lang#71156, which was split up to allow for easier review. With this PR, an underscore `_` is parsed as an expression but is allowed *only* on the left-hand side of a destructuring assignment. There it simply discards a value, similarly to the wildcard `_` in patterns. For instance, ```rust (a, _) = (1, 2) ``` will simply assign 1 to `a` and discard the 2. Note that for consistency, ``` _ = foo ``` is also allowed and equivalent to just `foo`. Thanks to ````@varkor```` who helped with the implementation, particularly around pre-expansion gating. r? ````@petrochenkov````
Implement destructuring assignment, as suggested in rust-lang/rfcs#372. The accompanying RFC is rust-lang/rfcs#2909.
Note: This PR has been split up into #78748, #78836, #79016, which have been merged.
Quick summary: This allows destructuring the LHS of an assignment if it's a (possibly nested) tuple, tuple struct, or slice.
It is implemented via a desugaring (AST -> HIR lowering) as follows:
... becomes ...
Parser changes:
_
in the LHS, it allows parsing_
as an expression (a change to the parser). It is still disallowed in all other places.Struct { a: 1, .. }
becomes legal (in order to act like a struct pattern).Tracking issue: #71126.