X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc_typeck%2Fcheck%2F_match.rs;h=5ffe34d61bf7d72243f3d9a70997cd3e0d779fa4;hb=5dc91a74b1428cf3d09a868727bf20b347664137;hp=dc6a209d4fca67af3630ddc1c59b68bc09e91bf3;hpb=319e97bfcf8a995f549d79d9c80d0df17587e643;p=rust.git diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index dc6a209d4fc..5ffe34d61bf 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -9,7 +9,7 @@ // 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}; @@ -25,6 +25,7 @@ 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; @@ -44,7 +45,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, expected); match pat.node { - hir::PatWild(_) => { + hir::PatWild => { fcx.write_ty(pat.id, expected); } hir::PatLit(ref lt) => { @@ -133,7 +134,8 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, // 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()); @@ -149,7 +151,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, // 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) => { @@ -178,7 +180,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, // 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); @@ -259,17 +261,30 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, } } 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 { @@ -397,7 +412,7 @@ pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, 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(_) => { @@ -494,12 +509,12 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, /* 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, ),