};
use hir_expand::name::Name;
-use super::{BindingMode, Expectation, InferenceContext};
+use super::{BindingMode, Expectation, InferenceContext, TypeMismatch};
use crate::{
lower::lower_to_chalk_mutability, static_lifetime, Interner, Substitution, Ty, TyBuilder,
TyExt, TyKind,
pub(super) fn infer_pat(
&mut self,
pat: PatId,
- mut expected: &Ty,
+ expected: &Ty,
mut default_bm: BindingMode,
) -> Ty {
let body = Arc::clone(&self.body); // avoid borrow checker problem
+ let mut expected = self.resolve_ty_shallow(expected);
if is_non_ref_pat(&body, pat) {
while let Some((inner, _lifetime, mutability)) = expected.as_reference() {
- expected = inner;
+ expected = self.resolve_ty_shallow(inner);
default_bm = match default_bm {
BindingMode::Move => BindingMode::Ref(mutability),
BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not),
let ty = match &body[pat] {
&Pat::Tuple { ref args, ellipsis } => {
let expectations = match expected.as_tuple() {
- Some(parameters) => &*parameters.interned(),
+ Some(parameters) => &*parameters.as_slice(&Interner),
_ => &[],
};
- let (pre, post) = match ellipsis {
- Some(idx) => args.split_at(idx),
- None => (&args[..], &[][..]),
+ let ((pre, post), n_uncovered_patterns) = match ellipsis {
+ Some(idx) => {
+ (args.split_at(idx), expectations.len().saturating_sub(args.len()))
+ }
+ None => ((&args[..], &[][..]), 0),
};
- let n_uncovered_patterns = expectations.len().saturating_sub(args.len());
let err_ty = self.err_ty();
let mut expectations_iter =
expectations.iter().map(|a| a.assert_ty_ref(&Interner)).chain(repeat(&err_ty));
}
Pat::Or(ref pats) => {
if let Some((first_pat, rest)) = pats.split_first() {
- let ty = self.infer_pat(*first_pat, expected, default_bm);
+ let ty = self.infer_pat(*first_pat, &expected, default_bm);
for pat in rest {
- self.infer_pat(*pat, expected, default_bm);
+ self.infer_pat(*pat, &expected, default_bm);
}
ty
} else {
Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
p.as_deref(),
subpats,
- expected,
+ &expected,
default_bm,
pat,
*ellipsis,
),
Pat::Record { path: p, args: fields, ellipsis: _ } => {
- self.infer_record_pat(p.as_deref(), fields, expected, default_bm, pat)
+ self.infer_record_pat(p.as_deref(), fields, &expected, default_bm, pat)
}
Pat::Path(path) => {
// FIXME use correct resolver for the surrounding expression
BindingMode::convert(*mode)
};
let inner_ty = if let Some(subpat) = subpat {
- self.infer_pat(*subpat, expected, default_bm)
+ self.infer_pat(*subpat, &expected, default_bm)
} else {
- expected.clone()
+ expected
};
let inner_ty = self.insert_type_vars_shallow(inner_ty);
}
BindingMode::Move => inner_ty.clone(),
};
- let bound_ty = self.resolve_ty_as_possible(bound_ty);
self.write_pat_ty(pat, bound_ty);
return inner_ty;
}
let (inner_ty, alloc_ty) = match expected.as_adt() {
Some((adt, subst)) if adt == box_adt => (
subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(),
- subst.interned().get(1).and_then(|a| a.ty(&Interner).cloned()),
+ subst.as_slice(&Interner).get(1).and_then(|a| a.ty(&Interner).cloned()),
),
_ => (self.result.standard_types.unknown.clone(), None),
};
};
// use a new type variable if we got error type here
let ty = self.insert_type_vars_shallow(ty);
- if !self.unify(&ty, expected) {
- // FIXME record mismatch, we need to change the type of self.type_mismatches for that
+ if !self.unify(&ty, &expected) {
+ self.result
+ .type_mismatches
+ .insert(pat.into(), TypeMismatch { expected: expected, actual: ty.clone() });
}
- let ty = self.resolve_ty_as_possible(ty);
self.write_pat_ty(pat, ty.clone());
ty
}