Unnamed repository; edit this file 'description' to name the repository.
Revert tests::patterns::infer_pattern
And apply requested changes
Ali Bektas 2025-02-03
parent dd46120 · commit 135fca9
-rw-r--r--crates/hir-ty/src/infer/expr.rs9
-rw-r--r--crates/hir-ty/src/infer/pat.rs48
-rw-r--r--crates/hir-ty/src/lib.rs11
-rw-r--r--crates/hir-ty/src/tests/patterns.rs4
4 files changed, 35 insertions, 37 deletions
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index a8753628af..86e5afdb50 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/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/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index 98693de4bb..5ff22bea34 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/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/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index acac7ddcad..55d81875a2 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/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/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs
index 50bc47cf67..4949d4016b 100644
--- a/crates/hir-ty/src/tests/patterns.rs
+++ b/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}