Skip to content

Change destructuring assignment lowering to use match. #96588

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

Conversation

steffahn
Copy link
Member

@steffahn steffahn commented Apr 30, 2022

Previously, lowering (a, b) = t produced code like { let (lhs1, lhs2) = t; a = lhs1; b = lhs2; },
with this PR, match t { (lhs1, lhs2) => { a = lhs1; b = lhs2; } } is produced instead.

The desired effect is to make sure that temporaries in the expression t aren't dropped too early,
in order to get better consistency between the behavior of e.g. x = t vs. [x] = [t] or (x,) = (t,)
(where t is an arbitrary expression).

Fixes #96579

As also discussed shortly here, this is a breaking change (most commonly affecting drop order of temporaries of the RHS vs. old values in the places that are being assigned) and thus this will need a crater run, and probably approval from T-lang.

The PR is still missing tests at this point. And there's a FIXME to be addressed/discussed (though the FIXME is no blocker for a crater run, as AFAICT – in anything – it could only affect diagnostics).

Previously, `(a, b) = t` produced code like `{ let (lhs1, lhs2) = t; a = lhs1; b = lhs2; }`,
with this commit instead we produce `match t { (lhs1, lhs2) => { a = lhs1; b = lhs2; } }`.

The desired effect is to make sure that temporaries in the expression `t` aren't dropped too early,
in order to get better consistency between the behavior of e.g. `x = t` vs. `[x] = [t]` or `(x,) = (t,)`
(where `t` is an arbitrary expression).
@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Apr 30, 2022
@rust-highfive
Copy link
Contributor

r? @oli-obk

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 30, 2022
@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-llvm-12 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
To only update this specific test, also pass `--test-args issues/issue-77218/issue-77218-2.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/issues/issue-77218/issue-77218-2.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/issues/issue-77218/issue-77218-2" "-A" "unused" "-Crpath" "-O" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/issues/issue-77218/issue-77218-2/auxiliary"
stdout: none
--- stderr -------------------------------
error[E0070]: invalid left-hand side of assignment
   |
   |
LL |     while Some(0) = value.get(0) { //~ ERROR invalid left-hand side of assignment
   |                -  ^
   |                cannot assign to this expression
   |
help: you might have meant to use pattern destructuring
   |
   |
LL |     while let Some(0) = value.get(0) { //~ ERROR invalid left-hand side of assignment

error[E0308]: mismatched types
  --> /checkout/src/test/ui/issues/issue-77218/issue-77218-2.rs:4:11
   |
   |
LL |     while Some(0) = value.get(0) { //~ ERROR invalid left-hand side of assignment
   |           ^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
error: aborting due to 2 previous errors

Some errors have detailed explanations: E0070, E0308.
For more information about an error, try `rustc --explain E0070`.
---
To only update this specific test, also pass `--test-args issues/issue-77218/issue-77218.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/issues/issue-77218/issue-77218.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/issues/issue-77218/issue-77218" "-A" "unused" "-Crpath" "-O" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/issues/issue-77218/issue-77218/auxiliary"
stdout: none
--- stderr -------------------------------
error[E0070]: invalid left-hand side of assignment
   |
   |
LL |     while Some(0) = value.get(0) {} //~ ERROR invalid left-hand side of assignment
   |                -  ^
   |                cannot assign to this expression
   |
help: you might have meant to use pattern destructuring
   |
   |
LL |     while let Some(0) = value.get(0) {} //~ ERROR invalid left-hand side of assignment

error[E0308]: mismatched types
  --> /checkout/src/test/ui/issues/issue-77218/issue-77218.rs:4:11
   |
   |
LL |     while Some(0) = value.get(0) {} //~ ERROR invalid left-hand side of assignment
   |           ^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
error: aborting due to 2 previous errors

Some errors have detailed explanations: E0070, E0308.
For more information about an error, try `rustc --explain E0070`.
---
22 
23 error[E0308]: mismatched types
+   --> $DIR/while-let-typo.rs:4:11
+    |
+ LL |     while Some(x) = foo {}
+    |           ^^^^^^^^^^^^^ expected `bool`, found `()`
+ error[E0308]: mismatched types
+   --> $DIR/while-let-typo.rs:5:11
+    |
+    |
+ LL |     while Some(foo) = bar {}
+    |           ^^^^^^^^^^^^^^^ expected `bool`, found `()`
+ error[E0308]: mismatched types
24   --> $DIR/while-let-typo.rs:6:11
25    |
26 LL |     while 3 = foo {}
---
To only update this specific test, also pass `--test-args suggestions/while-let-typo.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/suggestions/while-let-typo.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/suggestions/while-let-typo" "-A" "unused" "-Crpath" "-O" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/suggestions/while-let-typo/auxiliary"
stdout: none
--- stderr -------------------------------
error[E0425]: cannot find value `x` in this scope
   |
   |
LL |     while Some(x) = foo {} //~ ERROR cannot find value `x` in this scope
   |
help: you might have meant to use pattern matching
   |
   |
LL |     while let Some(x) = foo {} //~ ERROR cannot find value `x` in this scope

error[E0425]: cannot find value `x` in this scope
  --> /checkout/src/test/ui/suggestions/while-let-typo.rs:8:11
   |
   |
LL |     while x = 5 {} //~ ERROR cannot find value `x` in this scope
   |
help: you might have meant to use pattern matching
   |
   |
LL |     while let x = 5 {} //~ ERROR cannot find value `x` in this scope
Some tests failed in compiletest suite=ui mode=ui host=x86_64-unknown-linux-gnu target=x86_64-unknown-linux-gnu

error[E0308]: mismatched types
  --> /checkout/src/test/ui/suggestions/while-let-typo.rs:4:11
  --> /checkout/src/test/ui/suggestions/while-let-typo.rs:4:11
   |
LL |     while Some(x) = foo {} //~ ERROR cannot find value `x` in this scope
   |           ^^^^^^^^^^^^^ expected `bool`, found `()`
error[E0308]: mismatched types
  --> /checkout/src/test/ui/suggestions/while-let-typo.rs:5:11
   |
   |
LL |     while Some(foo) = bar {}
   |           ^^^^^^^^^^^^^^^ expected `bool`, found `()`
error[E0308]: mismatched types
  --> /checkout/src/test/ui/suggestions/while-let-typo.rs:6:11
   |
   |
LL |     while 3 = foo {} //~ ERROR mismatched types
   |           ^^^^^^^ expected `bool`, found `()`

error[E0070]: invalid left-hand side of assignment
   |
   |
LL |     while Some(3) = foo {} //~ ERROR invalid left-hand side of assignment
   |                -  ^
   |                cannot assign to this expression
   |
help: you might have meant to use pattern destructuring
   |
   |
LL |     while let Some(3) = foo {} //~ ERROR invalid left-hand side of assignment

error[E0308]: mismatched types
  --> /checkout/src/test/ui/suggestions/while-let-typo.rs:7:11
   |
   |
LL |     while Some(3) = foo {} //~ ERROR invalid left-hand side of assignment
   |           ^^^^^^^^^^^^^ expected `bool`, found `()`
error: aborting due to 7 previous errors

Some errors have detailed explanations: E0070, E0308, E0425.
For more information about an error, try `rustc --explain E0070`.

@oli-obk
Copy link
Contributor

oli-obk commented May 1, 2022

@bors try

@bors
Copy link
Collaborator

bors commented May 1, 2022

⌛ Trying commit 33eac80 with merge 37c8ca9437b76fdac722d51b7bfac3893dc01c1c...

@bors
Copy link
Collaborator

bors commented May 1, 2022

☀️ Try build successful - checks-actions
Build commit: 37c8ca9437b76fdac722d51b7bfac3893dc01c1c (37c8ca9437b76fdac722d51b7bfac3893dc01c1c)

@oli-obk
Copy link
Contributor

oli-obk commented May 1, 2022

@craterbot test

@craterbot
Copy link
Collaborator

🚨 Error: failed to parse the command

🆘 If you have any trouble with Crater please ping @rust-lang/infra!
ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@steffahn
Copy link
Member Author

steffahn commented May 1, 2022

Trying to address the diagnostics change that causes CI failure, I found that the current logic is flawed leading to code like this ICEing on current nightly

fn main() {
    let x: usize;
    while (x,) = (0_usize,) {}
}

I’ll come back to this (and open another issue, etc…) tomorrow.

@oli-obk oli-obk added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 10, 2022
@JohnCSimon
Copy link
Member

Ping from triage:
@steffahn Can you post your status on this PR?

@JohnCSimon
Copy link
Member

@steffahn
Ping from triage: I'm closing this due to inactivity, Please reopen when you are ready to continue with this.
Note: if you do please open the PR BEFORE you push to it, else you won't be able to reopen - this is a quirk of github.
Thanks for your contribution.

@rustbot label: +S-inactive

@JohnCSimon JohnCSimon closed this Jul 23, 2022
@rustbot rustbot added the S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs. label Jul 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Desuraring of destructuring assignment has subtle effects on drop-order / scopes of temporaries
8 participants