Repository: rust-analyzer/rust-analyzer (rust)

Issue:
Default binding modes are hard
The hover data reported for variable `x` here indicates that rust and r-a disagree about what to do when pattern matching a reference with "match ergonomics". We are matching `&true` against the pattern `x @ true`, and rust interprets it as `&(x @ true)` while r-a interprets it as `x @ &true`, leading to an incorrect typing annotation.
```rust
fn main() {
    if let x @ true = &true {
        //            v hover says `x: bool`
        let _: bool = x;
        // rust says: expected `bool`, found `&bool`
    }
}
```

Pull request description:
Fix bind patterns always being treated as ref taking patterns
Fixes #9107
bors r+

Patch:
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index 83e0a7a9e9..c97b495442 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -290,6 +290,10 @@ fn is_non_ref_pat(body: &hir_def::body::Body, pat: PatId) -> bool {
             Expr::Literal(Literal::String(..)) => false,
             _ => true,
         },
+        Pat::Bind { mode: BindingAnnotation::Mutable, subpat: Some(subpat), .. }
+        | Pat::Bind { mode: BindingAnnotation::Unannotated, subpat: Some(subpat), .. } => {
+            is_non_ref_pat(body, *subpat)
+        }
         Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Box { .. } | Pat::Missing => false,
     }
 }


Test patch:
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs
index cd08b5c7a5..7d00cee9b3 100644
--- a/crates/hir_ty/src/tests/patterns.rs
+++ b/crates/hir_ty/src/tests/patterns.rs
@@ -20,6 +20,8 @@ fn infer_pattern() {
                 let h = val;
             }
 
+            if let x @ true = &true {}
+
             let lambda = |a: u64, b, c: i32| { a + b; c };
 
             let ref ref_to_x = x;
@@ -30,7 +32,7 @@ fn infer_pattern() {
         "#,
         expect![[r#"
             8..9 'x': &i32
-            17..368 '{     ...o_x; }': ()
+            17..400 '{     ...o_x; }': ()
             27..28 'y': &i32
             31..32 'x': &i32
             42..44 '&z': &i32
@@ -59,24 +61,31 @@ fn infer_pattern() {
             176..204 '{     ...     }': ()
             190..191 'h': {unknown}
             194..197 'val': {unknown}
-            214..220 'lambda': |u64, u64, i32| -> i32
-            223..255 '|a: u6...b; c }': |u64, u64, i32| -> i32
-            224..225 'a': u64
-            232..233 'b': u64
-            235..236 'c': i32
-            243..255 '{ a + b; c }': i32
-            245..246 'a': u64
-            245..250 'a + b': u64
-            249..250 'b': u64
-            252..253 'c': i32
-            266..278 'ref ref_to_x': &&i32
-            281..282 'x': &i32
-            292..301 'mut mut_x': &i32
-            304..305 'x': &i32
-            315..335 'ref mu...f_to_x': &mut &i32
-            338..339 'x': &i32
-            349..350 'k': &mut &i32
-            353..365 'mut_ref_to_x': &mut &i32
+            210..236 'if let...rue {}': ()
+            217..225 'x @ true': &bool
+            221..225 'true': bool
+            221..225 'true': bool
+            228..233 '&true': &bool
+            229..233 'true': bool
+            234..236 '{}': ()
+            246..252 'lambda': |u64, u64, i32| -> i32
+            255..287 '|a: u6...b; c }': |u64, u64, i32| -> i32
+            256..257 'a': u64
+            264..265 'b': u64
+            267..268 'c': i32
+            275..287 '{ a + b; c }': i32
+            277..278 'a': u64
+            277..282 'a + b': u64
+            281..282 'b': u64
+            284..285 'c': i32
+            298..310 'ref ref_to_x': &&i32
+            313..314 'x': &i32
+            324..333 'mut mut_x': &i32
+            336..337 'x': &i32
+            347..367 'ref mu...f_to_x': &mut &i32
+            370..371 'x': &i32
+            381..382 'k': &mut &i32
+            385..397 'mut_ref_to_x': &mut &i32
         "#]],
     );
 }