diff options
| author | Roland Ruckerbauer <roland.rucky@gmail.com> | 2022-05-23 01:03:08 +0200 |
|---|---|---|
| committer | Roland Ruckerbauer <roland.rucky@gmail.com> | 2022-05-23 12:24:54 +0200 |
| commit | 86bb27f1a4029ebf7d487add52b1dc2132c154d9 (patch) | |
| tree | 4b0b50f38d731f9995d79b9621b350be7d9dfa8f | |
| parent | 84be2eaf99c1c057b401f755f92d22d5896900f2 (diff) | |
| download | rust-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.rs | 29 | ||||
| -rw-r--r-- | crates/hir-ty/src/tests/patterns.rs | 20 |
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)); +} + "#, + ); +} |
