From d473bdfdc3a2c377afd873abd4ace4244af80766 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 8 Dec 2023 19:54:46 +0000 Subject: [PATCH] Support bare unit structs in destructuring assignments --- compiler/rustc_ast_lowering/src/expr.rs | 2 ++ .../ui/destructuring-assignment/bad-expr-lhs.rs | 2 -- .../bad-expr-lhs.stderr | 10 +--------- .../non-exhaustive-destructure.rs | 4 ++++ .../non-exhaustive-destructure.stderr | 17 +++++++++++++++++ .../struct-or-enum-variant-path.rs | 6 ++++++ tests/ui/inference/issue-103587.stderr | 6 +----- tests/ui/issues/issue-13407.rs | 4 ++-- tests/ui/issues/issue-13407.stderr | 15 +++++++++------ 9 files changed, 42 insertions(+), 24 deletions(-) create mode 100644 tests/ui/destructuring-assignment/non-exhaustive-destructure.rs create mode 100644 tests/ui/destructuring-assignment/non-exhaustive-destructure.stderr diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 3556ee02bd7b8..dfe3a0d84f4cf 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1084,6 +1084,8 @@ impl<'hir> LoweringContext<'_, 'hir> { | ExprKind::Struct(..) | ExprKind::Tup(..) | ExprKind::Underscore => false, + // Check for unit struct constructor. + ExprKind::Path(..) => lower_ctx.extract_unit_struct_path(lhs).is_none(), // Check for tuple struct constructor. ExprKind::Call(callee, ..) => lower_ctx.extract_tuple_struct_path(callee).is_none(), ExprKind::Paren(e) => { diff --git a/tests/ui/destructuring-assignment/bad-expr-lhs.rs b/tests/ui/destructuring-assignment/bad-expr-lhs.rs index 53794783a3c87..90e1ac1994385 100644 --- a/tests/ui/destructuring-assignment/bad-expr-lhs.rs +++ b/tests/ui/destructuring-assignment/bad-expr-lhs.rs @@ -4,6 +4,4 @@ fn main() { (1, 2) = (3, 4); //~^ ERROR invalid left-hand side of assignment //~| ERROR invalid left-hand side of assignment - - None = Some(3); //~ ERROR invalid left-hand side of assignment } diff --git a/tests/ui/destructuring-assignment/bad-expr-lhs.stderr b/tests/ui/destructuring-assignment/bad-expr-lhs.stderr index d298674748053..2916d6d9f115d 100644 --- a/tests/ui/destructuring-assignment/bad-expr-lhs.stderr +++ b/tests/ui/destructuring-assignment/bad-expr-lhs.stderr @@ -30,15 +30,7 @@ LL | (1, 2) = (3, 4); | | | cannot assign to this expression -error[E0070]: invalid left-hand side of assignment - --> $DIR/bad-expr-lhs.rs:8:10 - | -LL | None = Some(3); - | ---- ^ - | | - | cannot assign to this expression - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0067, E0070. For more information about an error, try `rustc --explain E0067`. diff --git a/tests/ui/destructuring-assignment/non-exhaustive-destructure.rs b/tests/ui/destructuring-assignment/non-exhaustive-destructure.rs new file mode 100644 index 0000000000000..39939f2bad634 --- /dev/null +++ b/tests/ui/destructuring-assignment/non-exhaustive-destructure.rs @@ -0,0 +1,4 @@ +fn main() { + None = Some(3); + //~^ ERROR refutable pattern in local binding +} diff --git a/tests/ui/destructuring-assignment/non-exhaustive-destructure.stderr b/tests/ui/destructuring-assignment/non-exhaustive-destructure.stderr new file mode 100644 index 0000000000000..b9ceaa4af7ba0 --- /dev/null +++ b/tests/ui/destructuring-assignment/non-exhaustive-destructure.stderr @@ -0,0 +1,17 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/non-exhaustive-destructure.rs:2:5 + | +LL | None = Some(3); + | ^^^^ pattern `Some(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Option` +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if None = Some(3) { todo!() }; + | ++ +++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/destructuring-assignment/struct-or-enum-variant-path.rs b/tests/ui/destructuring-assignment/struct-or-enum-variant-path.rs index 8da7f90c5246d..f82e029983b75 100644 --- a/tests/ui/destructuring-assignment/struct-or-enum-variant-path.rs +++ b/tests/ui/destructuring-assignment/struct-or-enum-variant-path.rs @@ -11,17 +11,22 @@ type A = E; fn main() { let mut a; + S = S; (S, a) = (S, ()); + E::V = E::V; (E::V, a) = (E::V, ()); + ::V = E::V; (::V, a) = (E::V, ()); + A::V = A::V; (A::V, a) = (E::V, ()); } impl S { fn check() { let a; + Self = S; (Self, a) = (S, ()); } } @@ -29,6 +34,7 @@ impl S { impl E { fn check() { let a; + Self::V = E::V; (Self::V, a) = (E::V, ()); } } diff --git a/tests/ui/inference/issue-103587.stderr b/tests/ui/inference/issue-103587.stderr index b373fbfbb948c..589cb7ea7b130 100644 --- a/tests/ui/inference/issue-103587.stderr +++ b/tests/ui/inference/issue-103587.stderr @@ -26,14 +26,10 @@ error[E0308]: mismatched types LL | if None = x { } | ^^^^^^^^ expected `bool`, found `()` | -help: you might have meant to use pattern matching +help: consider adding `let` | LL | if let None = x { } | +++ -help: you might have meant to compare for equality - | -LL | if None == x { } - | + error: aborting due to 3 previous errors diff --git a/tests/ui/issues/issue-13407.rs b/tests/ui/issues/issue-13407.rs index 7ea81ffb59e7e..7794be37b8507 100644 --- a/tests/ui/issues/issue-13407.rs +++ b/tests/ui/issues/issue-13407.rs @@ -4,6 +4,6 @@ mod A { fn main() { A::C = 1; - //~^ ERROR: invalid left-hand side of assignment - //~| ERROR: struct `C` is private + //~^ ERROR: mismatched types + //~| ERROR: unit struct `C` is private } diff --git a/tests/ui/issues/issue-13407.stderr b/tests/ui/issues/issue-13407.stderr index 54b6c640d9d79..ac2eb6581fe25 100644 --- a/tests/ui/issues/issue-13407.stderr +++ b/tests/ui/issues/issue-13407.stderr @@ -10,15 +10,18 @@ note: the unit struct `C` is defined here LL | struct C; | ^^^^^^^^^ -error[E0070]: invalid left-hand side of assignment - --> $DIR/issue-13407.rs:6:10 +error[E0308]: mismatched types + --> $DIR/issue-13407.rs:6:5 | +LL | struct C; + | -------- unit struct defined here +... LL | A::C = 1; - | ---- ^ + | ^^^^ - this expression has type `{integer}` | | - | cannot assign to this expression + | expected integer, found `C` error: aborting due to 2 previous errors -Some errors have detailed explanations: E0070, E0603. -For more information about an error, try `rustc --explain E0070`. +Some errors have detailed explanations: E0308, E0603. +For more information about an error, try `rustc --explain E0308`.