Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #14872 - lowr:fix/ref-pat-with-type-var, r=HKalbasi
fix: introduce new type var when expectation for ref pat is not ref Fixes #14840 When we infer the type of ref patterns, its expected type may not be reference type: 1) expected type is an unresolved inference variable, or 2) expected type is erroneously other kind of type. In either case, we should produce a reference type with a new type variable rather than an error type so that we can continue inferring the inner patterns without further errors because of the (possible) type mismatch of this pattern.
bors 2023-05-23
parent 7ac161c · parent 01f42d2 · commit 2120c91
-rw-r--r--crates/hir-ty/src/infer/pat.rs13
-rw-r--r--crates/hir-ty/src/tests/patterns.rs17
2 files changed, 26 insertions, 4 deletions
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index 05f6fcaead..0c2b179a10 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -313,16 +313,23 @@ impl<'a> InferenceContext<'a> {
fn infer_ref_pat(
&mut self,
- pat: PatId,
+ inner_pat: PatId,
mutability: Mutability,
expected: &Ty,
default_bm: BindingMode,
) -> Ty {
let expectation = match expected.as_reference() {
Some((inner_ty, _lifetime, _exp_mut)) => inner_ty.clone(),
- _ => self.result.standard_types.unknown.clone(),
+ None => {
+ let inner_ty = self.table.new_type_var();
+ let ref_ty =
+ TyKind::Ref(mutability, static_lifetime(), inner_ty.clone()).intern(Interner);
+ // Unification failure will be reported by the caller.
+ self.unify(&ref_ty, expected);
+ inner_ty
+ }
};
- let subty = self.infer_pat(pat, &expectation, default_bm);
+ let subty = self.infer_pat(inner_pat, &expectation, default_bm);
TyKind::Ref(mutability, static_lifetime(), subty).intern(Interner)
}
diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs
index c8c31bdea5..b73f0d72a3 100644
--- a/crates/hir-ty/src/tests/patterns.rs
+++ b/crates/hir-ty/src/tests/patterns.rs
@@ -1,6 +1,6 @@
use expect_test::expect;
-use super::{check, check_infer, check_infer_with_mismatches, check_types};
+use super::{check, check_infer, check_infer_with_mismatches, check_no_mismatches, check_types};
#[test]
fn infer_pattern() {
@@ -241,6 +241,21 @@ fn infer_pattern_match_ergonomics_ref() {
}
#[test]
+fn ref_pat_with_inference_variable() {
+ check_no_mismatches(
+ r#"
+enum E { A }
+fn test() {
+ let f = |e| match e {
+ &E::A => {}
+ };
+ f(&E::A);
+}
+"#,
+ );
+}
+
+#[test]
fn infer_pattern_match_slice() {
check_infer(
r#"