about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs48
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs11
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs4
4 files changed, 35 insertions, 37 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
index a8753628afa..86e5afdb509 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
@@ -334,7 +334,11 @@ impl InferenceContext<'_> {
                     ExprIsRead::No
                 };
                 let input_ty = self.infer_expr(expr, &Expectation::none(), child_is_read);
-                self.infer_top_pat(pat, &input_ty, None);
+                self.infer_top_pat(
+                    pat,
+                    &input_ty,
+                    Some(DeclContext { origin: DeclOrigin::LetExpr }),
+                );
                 self.result.standard_types.bool_.clone()
             }
             Expr::Block { statements, tail, label, id } => {
@@ -1633,8 +1637,7 @@ impl InferenceContext<'_> {
                             };
 
                             let decl = DeclContext {
-                                has_else: else_branch.is_some(),
-                                origin: DeclOrigin::LocalDecl,
+                                origin: DeclOrigin::LocalDecl { has_else: else_branch.is_some() },
                             };
 
                             this.infer_top_pat(*pat, &ty, Some(decl));
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
index 98693de4bb6..5ff22bea34d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
@@ -498,7 +498,7 @@ impl InferenceContext<'_> {
 
         // If `expected` is an infer ty, we try to equate it to an array if the given pattern
         // allows it. See issue #16609
-        if self.decl_allows_array_type_infer(decl) && expected.is_ty_var() {
+        if self.pat_is_irrefutable(decl) && expected.is_ty_var() {
             if let Some(resolved_array_ty) =
                 self.try_resolve_slice_ty_to_array_ty(prefix, suffix, slice)
             {
@@ -601,42 +601,38 @@ impl InferenceContext<'_> {
         Some(array_ty)
     }
 
-    /// Determines whether we can infer the expected type in the slice pattern to be of type array.
+    /// Used to determine whether we can infer the expected type in the slice pattern to be of type array.
     /// This is only possible if we're in an irrefutable pattern. If we were to allow this in refutable
     /// patterns we wouldn't e.g. report ambiguity in the following situation:
     ///
     /// ```ignore(rust)
-    /// struct Zeroes;
-    /// const ARR: [usize; 2] = [0; 2];
-    /// const ARR2: [usize; 2] = [2; 2];
+    ///    struct Zeroes;
+    ///    const ARR: [usize; 2] = [0; 2];
+    ///    const ARR2: [usize; 2] = [2; 2];
     ///
-    /// impl Into<&'static [usize; 2]> for Zeroes {
-    ///     fn into(self) -> &'static [usize; 2] {
+    ///    impl Into<&'static [usize; 2]> for Zeroes {
+    ///        fn into(self) -> &'static [usize; 2] {
     ///            &ARR
-    ///     }
-    /// }
+    ///        }
+    ///    }
     ///
-    /// impl Into<&'static [usize]> for Zeroes {
-    ///     fn into(self) -> &'static [usize] {
-    ///        &ARR2
-    ///     }
-    /// }
+    ///    impl Into<&'static [usize]> for Zeroes {
+    ///        fn into(self) -> &'static [usize] {
+    ///            &ARR2
+    ///        }
+    ///    }
     ///
-    /// fn main() {
-    ///     let &[a, b]: &[usize] = Zeroes.into() else {
-    ///       ..
-    ///     };
-    /// }
+    ///    fn main() {
+    ///        let &[a, b]: &[usize] = Zeroes.into() else {
+    ///           ..
+    ///        };
+    ///    }
     /// ```
     ///
     /// If we're in an irrefutable pattern we prefer the array impl candidate given that
-    /// the slice impl candidate would be be rejected anyway (if no ambiguity existed).
-    fn decl_allows_array_type_infer(&self, decl_ctxt: Option<DeclContext>) -> bool {
-        if let Some(decl_ctxt) = decl_ctxt {
-            !decl_ctxt.has_else && matches!(decl_ctxt.origin, DeclOrigin::LocalDecl)
-        } else {
-            false
-        }
+    /// the slice impl candidate would be rejected anyway (if no ambiguity existed).
+    fn pat_is_irrefutable(&self, decl_ctxt: Option<DeclContext>) -> bool {
+        matches!(decl_ctxt, Some(DeclContext { origin: DeclOrigin::LocalDecl { has_else: false } }))
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index acac7ddcad3..55d81875a2b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -1052,18 +1052,17 @@ pub fn known_const_to_ast(
 
 #[derive(Debug, Copy, Clone)]
 pub(crate) enum DeclOrigin {
-    // from an `if let` expression
     LetExpr,
-    // from `let x = ..`
-    LocalDecl,
+    /// from `let x = ..`
+    LocalDecl {
+        has_else: bool,
+    },
 }
 
 /// Provides context for checking patterns in declarations. More specifically this
 /// allows us to infer array types if the pattern is irrefutable and allows us to infer
-/// the size of the array. See issue #76342.
+/// the size of the array. See issue rust-lang/rust#76342.
 #[derive(Debug, Copy, Clone)]
 pub(crate) struct DeclContext {
-    // whether we're in a let-else context
-    pub(crate) has_else: bool,
     pub(crate) origin: DeclOrigin,
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
index 50bc47cf673..4949d4016bf 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
@@ -67,9 +67,9 @@ fn infer_pattern() {
             143..144 'e': {unknown}
             157..204 'if let...     }': ()
             160..175 'let [val] = opt': bool
-            164..169 '[val]': [{unknown}; 1]
+            164..169 '[val]': [{unknown}]
             165..168 'val': {unknown}
-            172..175 'opt': [{unknown}; 1]
+            172..175 'opt': [{unknown}]
             176..204 '{     ...     }': ()
             190..191 'h': {unknown}
             194..197 'val': {unknown}