about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs13
-rw-r--r--tests/ui/suggestions/while-let-typo.rs2
-rw-r--r--tests/ui/suggestions/while-let-typo.stderr13
-rw-r--r--tests/ui/typeck/issue-112385-while-assign-lhs-place-expr-ice.rs9
-rw-r--r--tests/ui/typeck/issue-112385-while-assign-lhs-place-expr-ice.stderr14
5 files changed, 47 insertions, 4 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index eba5c829e39..30a543aab50 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1640,7 +1640,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                                 hir::Stmt {
                                                     kind:
                                                         hir::StmtKind::Expr(hir::Expr {
-                                                            kind: hir::ExprKind::Assign(..),
+                                                            kind: hir::ExprKind::Assign(lhs, ..),
                                                             ..
                                                         }),
                                                     ..
@@ -1650,7 +1650,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                     } = blk
                                     {
                                         self.comes_from_while_condition(blk.hir_id, |_| {
-                                            err.downgrade_to_delayed_bug();
+                                            // We cannot suppress the error if the LHS of assignment
+                                            // is a syntactic place expression because E0070 would
+                                            // not be emitted by `check_lhs_assignable`.
+                                            let res = self.typeck_results.borrow().expr_ty_opt(lhs);
+
+                                            if !lhs.is_syntactic_place_expr()
+                                                || res.references_error()
+                                            {
+                                                err.downgrade_to_delayed_bug();
+                                            }
                                         })
                                     }
                                 }
diff --git a/tests/ui/suggestions/while-let-typo.rs b/tests/ui/suggestions/while-let-typo.rs
index dbbcdee3c19..21b254054bb 100644
--- a/tests/ui/suggestions/while-let-typo.rs
+++ b/tests/ui/suggestions/while-let-typo.rs
@@ -2,7 +2,7 @@ fn main() {
     let foo = Some(0);
     let bar = None;
     while Some(x) = foo {} //~ ERROR cannot find value `x` in this scope
-    while Some(foo) = bar {}
+    while Some(foo) = bar {} //~ ERROR mismatched types
     while 3 = foo {} //~ ERROR mismatched types
     while Some(3) = foo {} //~ ERROR invalid left-hand side of assignment
     while x = 5 {} //~ ERROR cannot find value `x` in this scope
diff --git a/tests/ui/suggestions/while-let-typo.stderr b/tests/ui/suggestions/while-let-typo.stderr
index 7cc2ed3149b..69a7e5761d4 100644
--- a/tests/ui/suggestions/while-let-typo.stderr
+++ b/tests/ui/suggestions/while-let-typo.stderr
@@ -21,6 +21,17 @@ LL |     while let x = 5 {}
    |           +++
 
 error[E0308]: mismatched types
+  --> $DIR/while-let-typo.rs:5:11
+   |
+LL |     while Some(foo) = bar {}
+   |           ^^^^^^^^^^^^^^^ expected `bool`, found `()`
+   |
+help: consider adding `let`
+   |
+LL |     while let Some(foo) = bar {}
+   |           +++
+
+error[E0308]: mismatched types
   --> $DIR/while-let-typo.rs:6:11
    |
 LL |     while 3 = foo {}
@@ -39,7 +50,7 @@ help: you might have meant to use pattern destructuring
 LL |     while let Some(3) = foo {}
    |           +++
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0070, E0308, E0425.
 For more information about an error, try `rustc --explain E0070`.
diff --git a/tests/ui/typeck/issue-112385-while-assign-lhs-place-expr-ice.rs b/tests/ui/typeck/issue-112385-while-assign-lhs-place-expr-ice.rs
new file mode 100644
index 00000000000..3cb011dc06f
--- /dev/null
+++ b/tests/ui/typeck/issue-112385-while-assign-lhs-place-expr-ice.rs
@@ -0,0 +1,9 @@
+// Previously, the while loop with an assignment statement (mistakenly) as the condition
+// which has a place expr as the LHS would trigger an ICE in typeck.
+// Reduced from https://github.com/rust-lang/rust/issues/112385.
+
+fn main() {
+    let foo = Some(());
+    while Some(foo) = None {}
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/typeck/issue-112385-while-assign-lhs-place-expr-ice.stderr b/tests/ui/typeck/issue-112385-while-assign-lhs-place-expr-ice.stderr
new file mode 100644
index 00000000000..cf2648d0840
--- /dev/null
+++ b/tests/ui/typeck/issue-112385-while-assign-lhs-place-expr-ice.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-112385-while-assign-lhs-place-expr-ice.rs:7:11
+   |
+LL |     while Some(foo) = None {}
+   |           ^^^^^^^^^^^^^^^^ expected `bool`, found `()`
+   |
+help: consider adding `let`
+   |
+LL |     while let Some(foo) = None {}
+   |           +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.