typeck/pat.rs: extract check_pat_ref.
This commit is contained in:
parent
3de221a862
commit
b4a4e718de
1 changed files with 55 additions and 44 deletions
|
|
@ -111,50 +111,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.check_pat_box(pat.span, inner, expected, def_bm, discrim_span)
|
||||
}
|
||||
PatKind::Ref(ref inner, mutbl) => {
|
||||
let expected = self.shallow_resolve(expected);
|
||||
if self.check_dereferencable(pat.span, expected, &inner) {
|
||||
// `demand::subtype` would be good enough, but using
|
||||
// `eqtype` turns out to be equally general. See (*)
|
||||
// below for details.
|
||||
|
||||
// Take region, inner-type from expected type if we
|
||||
// can, to avoid creating needless variables. This
|
||||
// also helps with the bad interactions of the given
|
||||
// hack detailed in (*) below.
|
||||
debug!("check_pat_walk: expected={:?}", expected);
|
||||
let (rptr_ty, inner_ty) = match expected.sty {
|
||||
ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
|
||||
(expected, r_ty)
|
||||
}
|
||||
_ => {
|
||||
let inner_ty = self.next_ty_var(
|
||||
TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeInference,
|
||||
span: inner.span,
|
||||
}
|
||||
);
|
||||
let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
|
||||
let region = self.next_region_var(infer::PatternRegion(pat.span));
|
||||
let rptr_ty = tcx.mk_ref(region, mt);
|
||||
debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty);
|
||||
let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
|
||||
|
||||
// Look for a case like `fn foo(&foo: u32)` and suggest
|
||||
// `fn foo(foo: &u32)`
|
||||
if let Some(mut err) = err {
|
||||
self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected);
|
||||
err.emit();
|
||||
}
|
||||
(rptr_ty, inner_ty)
|
||||
}
|
||||
};
|
||||
|
||||
self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span);
|
||||
rptr_ty
|
||||
} else {
|
||||
self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span);
|
||||
tcx.types.err
|
||||
}
|
||||
self.check_pat_ref(pat, inner, mutbl, expected, def_bm, discrim_span)
|
||||
}
|
||||
PatKind::Slice(ref before, ref slice, ref after) => {
|
||||
let expected_ty = self.structurally_resolved_type(pat.span, expected);
|
||||
|
|
@ -1059,4 +1016,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
tcx.types.err
|
||||
}
|
||||
}
|
||||
|
||||
fn check_pat_ref(
|
||||
&self,
|
||||
pat: &hir::Pat,
|
||||
inner: &'tcx hir::Pat,
|
||||
mutbl: hir::Mutability,
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: ty::BindingMode,
|
||||
discrim_span: Option<Span>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let expected = self.shallow_resolve(expected);
|
||||
if self.check_dereferencable(pat.span, expected, &inner) {
|
||||
// `demand::subtype` would be good enough, but using `eqtype` turns
|
||||
// out to be equally general. See (*) below for details.
|
||||
|
||||
// Take region, inner-type from expected type if we can,
|
||||
// to avoid creating needless variables. This also helps with
|
||||
// the bad interactions of the given hack detailed in (*) below.
|
||||
debug!("check_pat_ref: expected={:?}", expected);
|
||||
let (rptr_ty, inner_ty) = match expected.sty {
|
||||
ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
|
||||
(expected, r_ty)
|
||||
}
|
||||
_ => {
|
||||
let inner_ty = self.next_ty_var(
|
||||
TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeInference,
|
||||
span: inner.span,
|
||||
}
|
||||
);
|
||||
let mt = ty::TypeAndMut { ty: inner_ty, mutbl };
|
||||
let region = self.next_region_var(infer::PatternRegion(pat.span));
|
||||
let rptr_ty = tcx.mk_ref(region, mt);
|
||||
debug!("check_pat_ref: demanding {:?} = {:?}", expected, rptr_ty);
|
||||
let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
|
||||
|
||||
// Look for a case like `fn foo(&foo: u32)` and suggest
|
||||
// `fn foo(foo: &u32)`
|
||||
if let Some(mut err) = err {
|
||||
self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected);
|
||||
err.emit();
|
||||
}
|
||||
(rptr_ty, inner_ty)
|
||||
}
|
||||
};
|
||||
|
||||
self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span);
|
||||
rptr_ty
|
||||
} else {
|
||||
self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span);
|
||||
tcx.types.err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue