mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-29 06:23:25 +00:00
Auto merge of #12355 - ruabmbua:fix-inference-pattern-wildcards, r=flodiebold
Fix inference when pattern matching a tuple field with a wildcard This should fix the following issue: https://github.com/rust-lang/rust-analyzer/issues/12331 * Replaced the `err_ty` in `infer_pat()` with a new type variable. * Had to change the iterator code a bit, to get around multiple mutable borrows of `self` in `infer_pat()`. Also added a test * Also added a test
This commit is contained in:
commit
238253c22d
2 changed files with 41 additions and 8 deletions
|
@ -1,6 +1,6 @@
|
||||||
//! Type inference for patterns.
|
//! Type inference for patterns.
|
||||||
|
|
||||||
use std::iter::repeat;
|
use std::iter::repeat_with;
|
||||||
|
|
||||||
use chalk_ir::Mutability;
|
use chalk_ir::Mutability;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
|
@ -140,15 +140,28 @@ impl<'a> InferenceContext<'a> {
|
||||||
}
|
}
|
||||||
None => ((&args[..], &[][..]), 0),
|
None => ((&args[..], &[][..]), 0),
|
||||||
};
|
};
|
||||||
let err_ty = self.err_ty();
|
let mut expectations_iter = expectations
|
||||||
let mut expectations_iter =
|
.iter()
|
||||||
expectations.iter().map(|a| a.assert_ty_ref(Interner)).chain(repeat(&err_ty));
|
.cloned()
|
||||||
let mut infer_pat = |(&pat, ty)| self.infer_pat(pat, ty, default_bm);
|
.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());
|
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
|
||||||
inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat));
|
.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))
|
TyKind::Tuple(inner_tys.len(), Substitution::from_iter(Interner, inner_tys))
|
||||||
.intern(Interner)
|
.intern(Interner)
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue