From a980b562a7b9035f00a67330afb95224f1196184 Mon Sep 17 00:00:00 2001
From: hkalbasi <hamidrezakalbasi@protonmail.com>
Date: Fri, 10 Mar 2023 13:44:07 +0330
Subject: [PATCH] Fix stack overflow when derefrencing `&!`

---
 crates/hir-ty/src/consteval/tests.rs             | 16 ++++++++++++++++
 crates/hir-ty/src/mir/lower.rs                   |  2 +-
 crates/hir-ty/src/mir/lower/as_place.rs          |  2 +-
 .../src/handlers/mutability_errors.rs            | 12 ++++++++++++
 4 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index f2e42d6e503..6a29e8ce52e 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -146,6 +146,22 @@ fn reference_autoderef() {
     "#,
         3,
     );
+    check_number(
+        r#"
+    struct Foo<T> { x: T }
+    impl<T> Foo<T> {
+        fn foo(&mut self) -> T { self.x }
+    }
+    fn f(i: &mut &mut Foo<Foo<i32>>) -> i32 {
+        ((**i).x).foo()
+    }
+    fn g(i: Foo<Foo<i32>>) -> i32 {
+        i.x.foo()
+    }
+    const GOAL: i32 = f(&mut &mut Foo { x: Foo { x: 3 } }) + g(Foo { x: Foo { x: 5 } });
+    "#,
+        8,
+    );
 }
 
 #[test]
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 8638e1d920e..435a914088b 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -637,7 +637,7 @@ impl MirLowerCtx<'_> {
             }
             Expr::Box { .. } => not_supported!("box expression"),
             Expr::Field { .. } | Expr::Index { .. } | Expr::UnaryOp { op: hir_def::expr::UnaryOp::Deref, .. } => {
-                let Some((p, current)) = self.lower_expr_as_place(current, expr_id, true)? else {
+                let Some((p, current)) = self.lower_expr_as_place_without_adjust(current, expr_id, true)? else {
                     return Ok(None);
                 };
                 self.push_assignment(current, place, Operand::Copy(p).into(), expr_id.into());
diff --git a/crates/hir-ty/src/mir/lower/as_place.rs b/crates/hir-ty/src/mir/lower/as_place.rs
index 09bcdd93be0..fe8147dcd3e 100644
--- a/crates/hir-ty/src/mir/lower/as_place.rs
+++ b/crates/hir-ty/src/mir/lower/as_place.rs
@@ -110,7 +110,7 @@ impl MirLowerCtx<'_> {
         }
     }
 
-    fn lower_expr_as_place_without_adjust(
+    pub(super) fn lower_expr_as_place_without_adjust(
         &mut self,
         current: BasicBlockId,
         expr_id: ExprId,
diff --git a/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
index f73d1302bf2..84189a5d560 100644
--- a/crates/ide-diagnostics/src/handlers/mutability_errors.rs
+++ b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
@@ -336,6 +336,18 @@ fn main() {
         );
     }
 
+    #[test]
+    fn regression_14310() {
+        check_diagnostics(
+            r#"
+            fn clone(mut i: &!) -> ! {
+                   //^^^^^ 💡 weak: variable does not need to be mutable
+                *i
+            }
+        "#,
+        );
+    }
+
     #[test]
     fn match_bindings() {
         check_diagnostics(