Skip to content

Commit

Permalink
make all pattern bindings with the same name resolve to the first one
Browse files Browse the repository at this point in the history
This simplifies the code considerably, removing one of the
last uses of hygienic matching out of resolution.
  • Loading branch information
Ariel Ben-Yehuda authored and petrochenkov committed Jun 9, 2016
1 parent 392b6e7 commit e783a0a
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 77 deletions.
10 changes: 0 additions & 10 deletions src/librustc/hir/pat_util.rs
Expand Up @@ -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,
Expand Down
15 changes: 1 addition & 14 deletions src/librustc_mir/hair/cx/expr.rs
Expand Up @@ -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;
Expand All @@ -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::*;
Expand Down Expand Up @@ -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(),
}
Expand Down
17 changes: 4 additions & 13 deletions src/librustc_mir/hair/cx/pattern.rs
Expand Up @@ -10,15 +10,13 @@

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;
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;

Expand All @@ -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,
}
}

Expand Down Expand Up @@ -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),
Expand Down
42 changes: 14 additions & 28 deletions src/librustc_typeck/check/_match.rs
Expand Up @@ -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};
Expand All @@ -21,26 +20,13 @@ 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;

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);
Expand All @@ -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;

Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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>) {
Expand Down
15 changes: 3 additions & 12 deletions src/librustc_typeck/check/mod.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit e783a0a

Please sign in to comment.