Fix inference when pattern matching a tuple field with a wildcard.

This commit is contained in:
Roland Ruckerbauer 2022-05-23 01:03:08 +02:00
parent 84be2eaf99
commit 86bb27f1a4
2 changed files with 41 additions and 8 deletions

View File

@ -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 @@ pub(super) fn infer_pat(
}
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)

View File

@ -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));
}
"#,
);
}