Skip to content

Commit 0dbd027

Browse files
author
Ariel Ben-Yehuda
committed
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.
1 parent dd6e8d4 commit 0dbd027

File tree

6 files changed

+61
-115
lines changed

6 files changed

+61
-115
lines changed

src/librustc/hir/pat_util.rs

-10
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,6 @@ use std::cell::RefCell;
2121

2222
pub type PatIdMap = FnvHashMap<ast::Name, ast::NodeId>;
2323

24-
// This is used because same-named variables in alternative patterns need to
25-
// use the NodeId of their namesake in the first pattern.
26-
pub fn pat_id_map(dm: &RefCell<DefMap>, pat: &hir::Pat) -> PatIdMap {
27-
let mut map = FnvHashMap();
28-
pat_bindings(dm, pat, |_bm, p_id, _s, path1| {
29-
map.insert(path1.node, p_id);
30-
});
31-
map
32-
}
33-
3424
pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
3525
match pat.node {
3626
PatKind::Lit(_) | PatKind::Range(_, _) | PatKind::QPath(..) => true,

src/librustc_mir/hair/cx/expr.rs

+1-14
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
// except according to those terms.
1010

1111
use hair::*;
12-
use rustc_data_structures::fnv::FnvHashMap;
1312
use rustc_const_math::ConstInt;
1413
use hair::cx::Cx;
1514
use hair::cx::block;
@@ -19,7 +18,6 @@ use rustc::hir::def::Def;
1918
use rustc::middle::const_val::ConstVal;
2019
use rustc_const_eval as const_eval;
2120
use rustc::middle::region::CodeExtent;
22-
use rustc::hir::pat_util;
2321
use rustc::ty::{self, VariantDef, Ty};
2422
use rustc::ty::cast::CastKind as TyCastKind;
2523
use rustc::mir::repr::*;
@@ -651,19 +649,8 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
651649

652650
fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
653651
arm: &'tcx hir::Arm) -> Arm<'tcx> {
654-
let mut map;
655-
let opt_map = if arm.pats.len() == 1 {
656-
None
657-
} else {
658-
map = FnvHashMap();
659-
pat_util::pat_bindings(&cx.tcx.def_map, &arm.pats[0], |_, p_id, _, path| {
660-
map.insert(path.node, p_id);
661-
});
662-
Some(&map)
663-
};
664-
665652
Arm {
666-
patterns: arm.pats.iter().map(|p| cx.refutable_pat(opt_map, p)).collect(),
653+
patterns: arm.pats.iter().map(|p| cx.refutable_pat(p)).collect(),
667654
guard: arm.guard.to_ref(),
668655
body: arm.body.to_ref(),
669656
}

src/librustc_mir/hair/cx/pattern.rs

+4-13
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,12 @@
1010

1111
use hair::*;
1212
use hair::cx::Cx;
13-
use rustc_data_structures::fnv::FnvHashMap;
1413
use rustc_const_eval as const_eval;
1514
use rustc::hir::def::Def;
1615
use rustc::hir::pat_util::{pat_is_resolved_const, pat_is_binding};
1716
use rustc::ty::{self, Ty};
1817
use rustc::mir::repr::*;
1918
use rustc::hir::{self, PatKind};
20-
use syntax::ast;
2119
use syntax::codemap::Span;
2220
use syntax::ptr::P;
2321

@@ -36,29 +34,25 @@ use syntax::ptr::P;
3634
/// ```
3735
struct PatCx<'patcx, 'cx: 'patcx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
3836
cx: &'patcx mut Cx<'cx, 'gcx, 'tcx>,
39-
binding_map: Option<&'patcx FnvHashMap<ast::Name, ast::NodeId>>,
4037
}
4138

4239
impl<'cx, 'gcx, 'tcx> Cx<'cx, 'gcx, 'tcx> {
4340
pub fn irrefutable_pat(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
44-
PatCx::new(self, None).to_pattern(pat)
41+
PatCx::new(self).to_pattern(pat)
4542
}
4643

4744
pub fn refutable_pat(&mut self,
48-
binding_map: Option<&FnvHashMap<ast::Name, ast::NodeId>>,
4945
pat: &hir::Pat)
5046
-> Pattern<'tcx> {
51-
PatCx::new(self, binding_map).to_pattern(pat)
47+
PatCx::new(self).to_pattern(pat)
5248
}
5349
}
5450

5551
impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
56-
fn new(cx: &'patcx mut Cx<'cx, 'gcx, 'tcx>,
57-
binding_map: Option<&'patcx FnvHashMap<ast::Name, ast::NodeId>>)
52+
fn new(cx: &'patcx mut Cx<'cx, 'gcx, 'tcx>)
5853
-> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
5954
PatCx {
6055
cx: cx,
61-
binding_map: binding_map,
6256
}
6357
}
6458

@@ -164,10 +158,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
164158
PatKind::Ident(bm, ref ident, ref sub)
165159
if pat_is_binding(&self.cx.tcx.def_map.borrow(), pat) =>
166160
{
167-
let id = match self.binding_map {
168-
None => pat.id,
169-
Some(ref map) => map[&ident.node],
170-
};
161+
let id = self.cx.tcx.def_map.borrow()[&pat.id].full_def().var_id();
171162
let var_ty = self.cx.tcx.node_id_to_type(pat.id);
172163
let region = match var_ty.sty {
173164
ty::TyRef(&r, _) => Some(r),

src/librustc_resolve/lib.rs

+37-34
Original file line numberDiff line numberDiff line change
@@ -2286,50 +2286,53 @@ impl<'a> Resolver<'a> {
22862286
debug!("(resolving pattern) binding `{}`", renamed);
22872287

22882288
let def_id = self.definitions.local_def_id(pattern.id);
2289-
let def = Def::Local(def_id, pattern.id);
2289+
let def;
22902290

22912291
// Record the definition so that later passes
22922292
// will be able to distinguish variants from
22932293
// locals in patterns.
22942294

2295+
if let Some(&arm) = bindings_list.get(&renamed) {
2296+
if mode == ArgumentIrrefutableMode {
2297+
// Forbid duplicate bindings in the same
2298+
// parameter list.
2299+
resolve_error(
2300+
self,
2301+
pattern.span,
2302+
ResolutionError::
2303+
IdentifierBoundMoreThanOnceInParameterList(
2304+
&ident.name.as_str()));
2305+
} else if arm == pat_id {
2306+
// Then this is a duplicate variable in the
2307+
// same disjunction, which is an error.
2308+
resolve_error(
2309+
self,
2310+
pattern.span,
2311+
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
2312+
&ident.name.as_str())
2313+
);
2314+
}
2315+
2316+
def = self.value_ribs.last_mut().unwrap()
2317+
.bindings[&renamed];
2318+
} else {
2319+
def = Def::Local(def_id, pattern.id);
2320+
2321+
// Add the binding to the local ribs, if it
2322+
// doesn't already exist in the bindings list. (We
2323+
// must not add it if it's in the bindings list
2324+
// because that breaks the assumptions later
2325+
// passes make about or-patterns.)
2326+
self.value_ribs.last_mut().unwrap()
2327+
.bindings.insert(renamed, def);
2328+
bindings_list.insert(renamed, pat_id);
2329+
}
2330+
22952331
self.record_def(pattern.id,
22962332
PathResolution {
22972333
base_def: def,
22982334
depth: 0,
22992335
});
2300-
2301-
// Add the binding to the local ribs, if it
2302-
// doesn't already exist in the bindings list. (We
2303-
// must not add it if it's in the bindings list
2304-
// because that breaks the assumptions later
2305-
// passes make about or-patterns.)
2306-
if !bindings_list.contains_key(&renamed) {
2307-
let this = &mut *self;
2308-
let last_rib = this.value_ribs.last_mut().unwrap();
2309-
last_rib.bindings.insert(renamed, def);
2310-
bindings_list.insert(renamed, pat_id);
2311-
} else if mode == ArgumentIrrefutableMode &&
2312-
bindings_list.contains_key(&renamed) {
2313-
// Forbid duplicate bindings in the same
2314-
// parameter list.
2315-
resolve_error(
2316-
self,
2317-
pattern.span,
2318-
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(
2319-
&ident.name.as_str())
2320-
);
2321-
} else if bindings_list.get(&renamed) == Some(&pat_id) {
2322-
// Then this is a duplicate variable in the
2323-
// same disjunction, which is an error.
2324-
resolve_error(
2325-
self,
2326-
pattern.span,
2327-
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
2328-
&ident.name.as_str())
2329-
);
2330-
}
2331-
// Else, not bound in the same pattern: do
2332-
// nothing.
23332336
}
23342337
}
23352338
}

src/librustc_typeck/check/_match.rs

+16-30
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010

1111
use hir::def::{self, Def};
1212
use rustc::infer::{self, InferOk, TypeOrigin};
13-
use hir::pat_util::{PatIdMap, pat_id_map, pat_is_binding};
14-
use hir::pat_util::pat_is_resolved_const;
13+
use hir::pat_util::{pat_is_binding, pat_is_resolved_const};
1514
use rustc::ty::subst::Substs;
1615
use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference};
1716
use check::{FnCtxt, Expectation};
@@ -21,26 +20,13 @@ use session::Session;
2120

2221
use std::cmp;
2322
use std::collections::hash_map::Entry::{Occupied, Vacant};
24-
use std::ops::Deref;
2523
use syntax::ast;
2624
use syntax::codemap::{Span, Spanned};
2725
use syntax::ptr::P;
2826

2927
use rustc::hir::{self, PatKind};
3028
use rustc::hir::print as pprust;
3129

32-
pub struct PatCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
33-
pub fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
34-
pub map: PatIdMap,
35-
}
36-
37-
impl<'a, 'gcx, 'tcx> Deref for PatCtxt<'a, 'gcx, 'tcx> {
38-
type Target = FnCtxt<'a, 'gcx, 'tcx>;
39-
fn deref(&self) -> &Self::Target {
40-
self.fcx
41-
}
42-
}
43-
4430
// This function exists due to the warning "diagnostic code E0164 already used"
4531
fn bad_struct_kind_err(sess: &Session, pat: &hir::Pat, path: &hir::Path, lint: bool) {
4632
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
5541
}
5642
}
5743

58-
impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
44+
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5945
pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
6046
let tcx = self.tcx;
6147

@@ -170,7 +156,7 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
170156
self.write_error(pat.id);
171157
}
172158
}
173-
PatKind::Ident(bm, ref path, ref sub)
159+
PatKind::Ident(bm, _, ref sub)
174160
if pat_is_binding(&tcx.def_map.borrow(), pat) => {
175161
let typ = self.local_ty(pat.span, pat.id);
176162
match bm {
@@ -200,15 +186,19 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
200186

201187
// if there are multiple arms, make sure they all agree on
202188
// what the type of the binding `x` ought to be
203-
if let Some(&canon_id) = self.map.get(&path.node) {
204-
if canon_id != pat.id {
205-
let ct = self.local_ty(pat.span, canon_id);
206-
self.demand_eqtype(pat.span, ct, typ);
189+
match tcx.def_map.borrow()[&pat.id].full_def() {
190+
Def::Err => {}
191+
Def::Local(_, var_id) => {
192+
if var_id != pat.id {
193+
let vt = self.local_ty(pat.span, var_id);
194+
self.demand_eqtype(pat.span, vt, typ);
195+
}
207196
}
197+
d => bug!("bad def for pattern binding `{:?}`", d)
198+
}
208199

209-
if let Some(ref p) = *sub {
210-
self.check_pat(&p, expected);
211-
}
200+
if let Some(ref p) = *sub {
201+
self.check_pat(&p, expected);
212202
}
213203
}
214204
PatKind::Ident(_, ref path, _) => {
@@ -486,12 +476,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
486476
// Typecheck the patterns first, so that we get types for all the
487477
// bindings.
488478
for arm in arms {
489-
let pcx = PatCtxt {
490-
fcx: self,
491-
map: pat_id_map(&tcx.def_map, &arm.pats[0]),
492-
};
493479
for p in &arm.pats {
494-
pcx.check_pat(&p, discrim_ty);
480+
self.check_pat(&p, discrim_ty);
495481
}
496482
}
497483

@@ -576,7 +562,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
576562
}
577563
}
578564

579-
impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
565+
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
580566
pub fn check_pat_struct(&self, pat: &'gcx hir::Pat,
581567
path: &hir::Path, fields: &'gcx [Spanned<hir::FieldPat>],
582568
etc: bool, expected: Ty<'tcx>) {

src/librustc_typeck/check/mod.rs

+3-14
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,13 @@ pub use self::compare_method::{compare_impl_method, compare_const_impl};
8181
use self::TupleArgumentsFlag::*;
8282

8383
use astconv::{AstConv, ast_region_to_region, PathParamMode};
84-
use check::_match::PatCtxt;
8584
use dep_graph::DepNode;
8685
use fmt_macros::{Parser, Piece, Position};
8786
use middle::cstore::LOCAL_CRATE;
8887
use hir::def::{self, Def};
8988
use hir::def_id::DefId;
9089
use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable};
91-
use hir::pat_util::{self, pat_id_map};
90+
use hir::pat_util::{self};
9291
use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace};
9392
use rustc::traits::{self, ProjectionMode};
9493
use rustc::ty::{GenericPredicates, TypeScheme};
@@ -679,11 +678,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
679678
});
680679

681680
// Check the pattern.
682-
let pcx = PatCtxt {
683-
fcx: &fcx,
684-
map: pat_id_map(&tcx.def_map, &input.pat),
685-
};
686-
pcx.check_pat(&input.pat, *arg_ty);
681+
fcx.check_pat(&input.pat, *arg_ty);
687682
}
688683

689684
visit.visit_block(body);
@@ -3934,8 +3929,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
39343929
}
39353930

39363931
pub fn check_decl_local(&self, local: &'gcx hir::Local) {
3937-
let tcx = self.tcx;
3938-
39393932
let t = self.local_ty(local.span, local.id);
39403933
self.write_ty(local.id, t);
39413934

@@ -3947,11 +3940,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
39473940
}
39483941
}
39493942

3950-
let pcx = PatCtxt {
3951-
fcx: self,
3952-
map: pat_id_map(&tcx.def_map, &local.pat),
3953-
};
3954-
pcx.check_pat(&local.pat, t);
3943+
self.check_pat(&local.pat, t);
39553944
let pat_ty = self.node_ty(local.pat.id);
39563945
if pat_ty.references_error() {
39573946
self.write_ty(local.id, pat_ty);

0 commit comments

Comments
 (0)