// except according to those terms.
use middle::def;
-use middle::infer;
+use middle::infer::{self, TypeOrigin};
use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding};
use middle::pat_util::pat_is_resolved_const;
use middle::privacy::{AllPublic, LastMod};
use std::cmp;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use syntax::ast;
+use syntax::ext::mtwt;
use syntax::codemap::{Span, Spanned};
use syntax::ptr::P;
expected);
match pat.node {
- hir::PatWild(_) => {
+ hir::PatWild => {
fcx.write_ty(pat.id, expected);
}
hir::PatLit(ref lt) => {
// subtyping doesn't matter here, as the value is some kind of scalar
demand::eqtype(fcx, pat.span, expected, lhs_ty);
}
- hir::PatEnum(..) | hir::PatIdent(..) if pat_is_resolved_const(&tcx.def_map, pat) => {
+ hir::PatEnum(..) | hir::PatIdent(..)
+ if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => {
let const_did = tcx.def_map.borrow().get(&pat.id).unwrap().def_id();
let const_scheme = tcx.lookup_item_type(const_did);
assert!(const_scheme.generics.is_empty());
// is good enough.
demand::suptype(fcx, pat.span, expected, const_ty);
}
- hir::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map, pat) => {
+ hir::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map.borrow(), pat) => {
let typ = fcx.local_ty(pat.span, pat.id);
match bm {
hir::BindByRef(mutbl) => {
// if there are multiple arms, make sure they all agree on
// what the type of the binding `x` ought to be
- let canon_id = *pcx.map.get(&path.node.name).unwrap();
+ let canon_id = *pcx.map.get(&mtwt::resolve(path.node)).unwrap();
if canon_id != pat.id {
let ct = fcx.local_ty(pat.span, canon_id);
demand::eqtype(fcx, pat.span, ct, typ);
}
}
hir::PatRegion(ref inner, mutbl) => {
- let inner_ty = fcx.infcx().next_ty_var();
-
- let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
- let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
- let rptr_ty = tcx.mk_ref(tcx.mk_region(region), mt);
-
+ let expected = fcx.infcx().shallow_resolve(expected);
if check_dereferencable(pcx, pat.span, expected, &**inner) {
// `demand::subtype` would be good enough, but using
// `eqtype` turns out to be equally general. See (*)
// below for details.
- demand::eqtype(fcx, pat.span, expected, rptr_ty);
+
+ // 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.
+ let (rptr_ty, inner_ty) = match expected.sty {
+ ty::TyRef(_, mt) if mt.mutbl == mutbl => {
+ (expected, mt.ty)
+ }
+ _ => {
+ let inner_ty = fcx.infcx().next_ty_var();
+ let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
+ let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
+ let rptr_ty = tcx.mk_ref(tcx.mk_region(region), mt);
+ demand::eqtype(fcx, pat.span, expected, rptr_ty);
+ (rptr_ty, inner_ty)
+ }
+ };
+
fcx.write_ty(pat.id, rptr_ty);
check_pat(pcx, &**inner, inner_ty);
} else {
inner: &hir::Pat) -> bool {
let fcx = pcx.fcx;
let tcx = pcx.fcx.ccx.tcx;
- if pat_is_binding(&tcx.def_map, inner) {
+ if pat_is_binding(&tcx.def_map.borrow(), inner) {
let expected = fcx.infcx().shallow_resolve(expected);
expected.builtin_deref(true, ty::NoPreference).map_or(true, |mt| match mt.ty.sty {
ty::TyTrait(_) => {
/* if-let construct without an else block */
hir::MatchSource::IfLetDesugar { contains_else_clause }
if !contains_else_clause => (
- infer::IfExpressionWithNoElse(expr.span),
+ TypeOrigin::IfExpressionWithNoElse(expr.span),
bty,
result_ty,
),
_ => (
- infer::MatchExpressionArm(expr.span, arm.body.span, match_src),
+ TypeOrigin::MatchExpressionArm(expr.span, arm.body.span, match_src),
result_ty,
bty,
),