about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRoland Ruckerbauer <roland.rucky@gmail.com>2022-05-23 01:03:08 +0200
committerRoland Ruckerbauer <roland.rucky@gmail.com>2022-05-23 12:24:54 +0200
commit86bb27f1a4029ebf7d487add52b1dc2132c154d9 (patch)
tree4b0b50f38d731f9995d79b9621b350be7d9dfa8f
parent84be2eaf99c1c057b401f755f92d22d5896900f2 (diff)
downloadrust-86bb27f1a4029ebf7d487add52b1dc2132c154d9.tar.gz
rust-86bb27f1a4029ebf7d487add52b1dc2132c154d9.zip
Fix inference when pattern matching a tuple field with a wildcard.
-rw-r--r--crates/hir-ty/src/infer/pat.rs29
-rw-r--r--crates/hir-ty/src/tests/patterns.rs20
2 files changed, 41 insertions, 8 deletions
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index f8131314c69..dbce0f7cd4f 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -1,6 +1,6 @@
 //! Type inference for patterns.
 
-use std::iter::repeat;
+use std::iter::repeat_with;
 
 use chalk_ir::Mutability;
 use hir_def::{
@@ -140,15 +140,28 @@ impl<'a> InferenceContext<'a> {
                     }
                     None => ((&args[..], &[][..]), 0),
                 };
-                let err_ty = self.err_ty();
-                let mut expectations_iter =
-                    expectations.iter().map(|a| a.assert_ty_ref(Interner)).chain(repeat(&err_ty));
-                let mut infer_pat = |(&pat, ty)| self.infer_pat(pat, ty, default_bm);
+                let mut expectations_iter = expectations
+                    .iter()
+                    .cloned()
+                    .map(|a| a.assert_ty_ref(Interner).clone())
+                    .chain(repeat_with(|| self.table.new_type_var()));
 
                 let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + args.len());
-                inner_tys.extend(pre.iter().zip(expectations_iter.by_ref()).map(&mut infer_pat));
-                inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned());
-                inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat));
+
+                inner_tys
+                    .extend(expectations_iter.by_ref().take(n_uncovered_patterns + args.len()));
+
+                // Process pre
+                for (ty, pat) in inner_tys.iter_mut().zip(pre) {
+                    *ty = self.infer_pat(*pat, ty, default_bm);
+                }
+
+                // Process post
+                for (ty, pat) in
+                    inner_tys.iter_mut().skip(pre.len() + n_uncovered_patterns).zip(post)
+                {
+                    *ty = self.infer_pat(*pat, ty, default_bm);
+                }
 
                 TyKind::Tuple(inner_tys.len(), Substitution::from_iter(Interner, inner_tys))
                     .intern(Interner)
diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs
index acdd8f50efb..399553356b0 100644
--- a/crates/hir-ty/src/tests/patterns.rs
+++ b/crates/hir-ty/src/tests/patterns.rs
@@ -969,3 +969,23 @@ fn main() {
     "#,
     );
 }
+
+#[test]
+fn tuple_wildcard() {
+    check_types(
+        r#"
+fn main() {
+    enum Option<T> {Some(T), None}
+    use Option::*;
+
+    let mut x = None;
+    x;
+  //^ Option<(i32, i32)>
+
+    if let Some((_, _a)) = x {}
+
+    x = Some((1, 2));
+}
+        "#,
+    );
+}