make all pattern bindings with the same name resolve to the first one
This simplifies the code considerably, removing one of the last uses of hygienic matching out of resolution.
This commit is contained in:
parent
392b6e7c81
commit
e783a0a5e3
5 changed files with 22 additions and 77 deletions
|
|
@ -53,16 +53,6 @@ impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
|
|||
}
|
||||
}
|
||||
|
||||
// This is used because same-named variables in alternative patterns need to
|
||||
// use the NodeId of their namesake in the first pattern.
|
||||
pub fn pat_id_map(pat: &hir::Pat) -> PatIdMap {
|
||||
let mut map = FnvHashMap();
|
||||
pat_bindings(pat, |_bm, p_id, _s, path1| {
|
||||
map.insert(path1.node, p_id);
|
||||
});
|
||||
map
|
||||
}
|
||||
|
||||
pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
|
||||
match pat.node {
|
||||
PatKind::Lit(_) | PatKind::Range(_, _) | PatKind::QPath(..) => true,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
// except according to those terms.
|
||||
|
||||
use hair::*;
|
||||
use rustc_data_structures::fnv::FnvHashMap;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc_const_math::ConstInt;
|
||||
use hair::cx::Cx;
|
||||
|
|
@ -20,7 +19,6 @@ use rustc::hir::def::Def;
|
|||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc_const_eval as const_eval;
|
||||
use rustc::middle::region::CodeExtent;
|
||||
use rustc::hir::pat_util;
|
||||
use rustc::ty::{self, VariantDef, Ty};
|
||||
use rustc::ty::cast::CastKind as TyCastKind;
|
||||
use rustc::mir::repr::*;
|
||||
|
|
@ -652,19 +650,8 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
|
|||
|
||||
fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
arm: &'tcx hir::Arm) -> Arm<'tcx> {
|
||||
let mut map;
|
||||
let opt_map = if arm.pats.len() == 1 {
|
||||
None
|
||||
} else {
|
||||
map = FnvHashMap();
|
||||
pat_util::pat_bindings(&arm.pats[0], |_, p_id, _, path| {
|
||||
map.insert(path.node, p_id);
|
||||
});
|
||||
Some(&map)
|
||||
};
|
||||
|
||||
Arm {
|
||||
patterns: arm.pats.iter().map(|p| cx.refutable_pat(opt_map, p)).collect(),
|
||||
patterns: arm.pats.iter().map(|p| cx.refutable_pat(p)).collect(),
|
||||
guard: arm.guard.to_ref(),
|
||||
body: arm.body.to_ref(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
use hair::*;
|
||||
use hair::cx::Cx;
|
||||
use rustc_data_structures::fnv::FnvHashMap;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc_const_eval as const_eval;
|
||||
use rustc::hir::def::Def;
|
||||
|
|
@ -18,7 +17,6 @@ use rustc::hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const};
|
|||
use rustc::ty::{self, Ty};
|
||||
use rustc::mir::repr::*;
|
||||
use rustc::hir::{self, PatKind};
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::ptr::P;
|
||||
|
||||
|
|
@ -37,29 +35,25 @@ use syntax::ptr::P;
|
|||
/// ```
|
||||
struct PatCx<'patcx, 'cx: 'patcx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
|
||||
cx: &'patcx mut Cx<'cx, 'gcx, 'tcx>,
|
||||
binding_map: Option<&'patcx FnvHashMap<ast::Name, ast::NodeId>>,
|
||||
}
|
||||
|
||||
impl<'cx, 'gcx, 'tcx> Cx<'cx, 'gcx, 'tcx> {
|
||||
pub fn irrefutable_pat(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
|
||||
PatCx::new(self, None).to_pattern(pat)
|
||||
PatCx::new(self).to_pattern(pat)
|
||||
}
|
||||
|
||||
pub fn refutable_pat(&mut self,
|
||||
binding_map: Option<&FnvHashMap<ast::Name, ast::NodeId>>,
|
||||
pat: &hir::Pat)
|
||||
-> Pattern<'tcx> {
|
||||
PatCx::new(self, binding_map).to_pattern(pat)
|
||||
PatCx::new(self).to_pattern(pat)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||
fn new(cx: &'patcx mut Cx<'cx, 'gcx, 'tcx>,
|
||||
binding_map: Option<&'patcx FnvHashMap<ast::Name, ast::NodeId>>)
|
||||
fn new(cx: &'patcx mut Cx<'cx, 'gcx, 'tcx>)
|
||||
-> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||
PatCx {
|
||||
cx: cx,
|
||||
binding_map: binding_map,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -168,10 +162,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
PatKind::Binding(bm, ref ident, ref sub) => {
|
||||
let id = match self.binding_map {
|
||||
None => pat.id,
|
||||
Some(ref map) => map[&ident.node],
|
||||
};
|
||||
let id = self.cx.tcx.def_map.borrow()[&pat.id].full_def().var_id();
|
||||
let var_ty = self.cx.tcx.node_id_to_type(pat.id);
|
||||
let region = match var_ty.sty {
|
||||
ty::TyRef(&r, _) => Some(r),
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
use hir::def::Def;
|
||||
use rustc::infer::{self, InferOk, TypeOrigin};
|
||||
use hir::pat_util::{PatIdMap, pat_id_map};
|
||||
use hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference};
|
||||
|
|
@ -21,7 +20,6 @@ use session::Session;
|
|||
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::cmp;
|
||||
use std::ops::Deref;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::{Span, Spanned};
|
||||
use syntax::ptr::P;
|
||||
|
|
@ -29,18 +27,6 @@ use syntax::ptr::P;
|
|||
use rustc::hir::{self, PatKind};
|
||||
use rustc::hir::print as pprust;
|
||||
|
||||
pub struct PatCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
pub fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||
pub map: PatIdMap,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Deref for PatCtxt<'a, 'gcx, 'tcx> {
|
||||
type Target = FnCtxt<'a, 'gcx, 'tcx>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.fcx
|
||||
}
|
||||
}
|
||||
|
||||
// This function exists due to the warning "diagnostic code E0164 already used"
|
||||
fn bad_struct_kind_err(sess: &Session, pat: &hir::Pat, path: &hir::Path, lint: bool) {
|
||||
let name = pprust::path_to_string(path);
|
||||
|
|
@ -55,7 +41,7 @@ fn bad_struct_kind_err(sess: &Session, pat: &hir::Pat, path: &hir::Path, lint: b
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
|
||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
|
||||
let tcx = self.tcx;
|
||||
|
||||
|
|
@ -194,15 +180,19 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
// if there are multiple arms, make sure they all agree on
|
||||
// what the type of the binding `x` ought to be
|
||||
if let Some(&canon_id) = self.map.get(&path.node) {
|
||||
if canon_id != pat.id {
|
||||
let ct = self.local_ty(pat.span, canon_id);
|
||||
self.demand_eqtype(pat.span, ct, typ);
|
||||
match tcx.def_map.borrow()[&pat.id].full_def() {
|
||||
Def::Err => {}
|
||||
Def::Local(_, var_id) => {
|
||||
if var_id != pat.id {
|
||||
let vt = self.local_ty(pat.span, var_id);
|
||||
self.demand_eqtype(pat.span, vt, typ);
|
||||
}
|
||||
}
|
||||
d => bug!("bad def for pattern binding `{:?}`", d)
|
||||
}
|
||||
|
||||
if let Some(ref p) = *sub {
|
||||
self.check_pat(&p, expected);
|
||||
}
|
||||
if let Some(ref p) = *sub {
|
||||
self.check_pat(&p, expected);
|
||||
}
|
||||
}
|
||||
PatKind::TupleStruct(ref path, ref subpats, ddpos) => {
|
||||
|
|
@ -476,12 +466,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// Typecheck the patterns first, so that we get types for all the
|
||||
// bindings.
|
||||
for arm in arms {
|
||||
let pcx = PatCtxt {
|
||||
fcx: self,
|
||||
map: pat_id_map(&arm.pats[0]),
|
||||
};
|
||||
for p in &arm.pats {
|
||||
pcx.check_pat(&p, discrim_ty);
|
||||
self.check_pat(&p, discrim_ty);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -566,7 +552,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
|
||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn check_pat_struct(&self, pat: &'gcx hir::Pat,
|
||||
path: &hir::Path, fields: &'gcx [Spanned<hir::FieldPat>],
|
||||
etc: bool, expected: Ty<'tcx>) {
|
||||
|
|
|
|||
|
|
@ -81,14 +81,13 @@ pub use self::compare_method::{compare_impl_method, compare_const_impl};
|
|||
use self::TupleArgumentsFlag::*;
|
||||
|
||||
use astconv::{AstConv, ast_region_to_region, PathParamMode};
|
||||
use check::_match::PatCtxt;
|
||||
use dep_graph::DepNode;
|
||||
use fmt_macros::{Parser, Piece, Position};
|
||||
use middle::cstore::LOCAL_CRATE;
|
||||
use hir::def::{self, Def};
|
||||
use hir::def_id::DefId;
|
||||
use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable};
|
||||
use hir::pat_util::{self, pat_id_map};
|
||||
use hir::pat_util::{self};
|
||||
use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace};
|
||||
use rustc::traits::{self, ProjectionMode};
|
||||
use rustc::ty::{GenericPredicates, TypeScheme};
|
||||
|
|
@ -672,11 +671,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
|
|||
});
|
||||
|
||||
// Check the pattern.
|
||||
let pcx = PatCtxt {
|
||||
fcx: &fcx,
|
||||
map: pat_id_map(&input.pat),
|
||||
};
|
||||
pcx.check_pat(&input.pat, *arg_ty);
|
||||
fcx.check_pat(&input.pat, *arg_ty);
|
||||
}
|
||||
|
||||
visit.visit_block(body);
|
||||
|
|
@ -3786,11 +3781,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let pcx = PatCtxt {
|
||||
fcx: self,
|
||||
map: pat_id_map(&local.pat),
|
||||
};
|
||||
pcx.check_pat(&local.pat, t);
|
||||
self.check_pat(&local.pat, t);
|
||||
let pat_ty = self.node_ty(local.pat.id);
|
||||
if pat_ty.references_error() {
|
||||
self.write_ty(local.id, pat_ty);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue