Unnamed repository; edit this file 'description' to name the repository.
-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 f8131314c6..dbce0f7cd4 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 acdd8f50ef..399553356b 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));
+}
+ "#,
+ );
+}