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 {Some(T), None} + use Option::*; + + let mut x = None; + x; + //^ Option<(i32, i32)> + + if let Some((_, _a)) = x {} + + x = Some((1, 2)); +} + "#, + ); +}