Skip to content

Commit f4bf28c

Browse files
committed
Merge pull request #29967 from petrochenkov/beta
backport: Fix hygiene regression in patterns
2 parents 9c81560 + 93413fb commit f4bf28c

File tree

7 files changed

+65
-14
lines changed

7 files changed

+65
-14
lines changed

src/librustc/middle/pat_util.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use middle::ty;
1414
use util::nodemap::FnvHashMap;
1515

1616
use syntax::ast;
17+
use syntax::ext::mtwt;
1718
use rustc_front::hir;
1819
use rustc_front::util::walk_pat;
1920
use syntax::codemap::{respan, Span, Spanned, DUMMY_SP};
@@ -24,8 +25,8 @@ pub type PatIdMap = FnvHashMap<ast::Name, ast::NodeId>;
2425
// use the NodeId of their namesake in the first pattern.
2526
pub fn pat_id_map(dm: &DefMap, pat: &hir::Pat) -> PatIdMap {
2627
let mut map = FnvHashMap();
27-
pat_bindings(dm, pat, |_bm, p_id, _s, path1| {
28-
map.insert(path1.node, p_id);
28+
pat_bindings_hygienic(dm, pat, |_bm, p_id, _s, path1| {
29+
map.insert(mtwt::resolve(path1.node), p_id);
2930
});
3031
map
3132
}

src/librustc_driver/driver.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -693,8 +693,9 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
693693
|| resolve::resolve_crate(sess, &ast_map, make_glob_map));
694694

695695
// Discard MTWT tables that aren't required past resolution.
696+
// FIXME: get rid of uses of MTWT tables in typeck, mir and trans and clear them
696697
if !sess.opts.debugging_opts.keep_mtwt_tables {
697-
syntax::ext::mtwt::clear_tables();
698+
// syntax::ext::mtwt::clear_tables();
698699
}
699700

700701
let named_region_map = time(time_passes, "lifetime resolution",

src/librustc_mir/tcx/expr.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use rustc::middle::pat_util;
2424
use rustc::middle::ty::{self, Ty};
2525
use rustc_front::hir;
2626
use rustc_front::util as hir_util;
27+
use syntax::ext::mtwt;
2728
use syntax::parse::token;
2829
use syntax::ptr::P;
2930

@@ -477,8 +478,8 @@ fn convert_arm<'a, 'tcx: 'a>(cx: &Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx
477478
None
478479
} else {
479480
let mut map = FnvHashMap();
480-
pat_util::pat_bindings(&cx.tcx.def_map, &arm.pats[0], |_, p_id, _, path| {
481-
map.insert(path.node, p_id);
481+
pat_util::pat_bindings_hygienic(&cx.tcx.def_map, &arm.pats[0], |_, p_id, _, path| {
482+
map.insert(mtwt::resolve(path.node), p_id);
482483
});
483484
Some(Rc::new(map))
484485
};

src/librustc_mir/tcx/pattern.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc::middle::subst::Substs;
2222
use rustc::middle::ty::{self, Ty};
2323
use rustc_front::hir;
2424
use syntax::ast;
25+
use syntax::ext::mtwt;
2526
use syntax::ptr::P;
2627

2728
/// When there are multiple patterns in a single arm, each one has its
@@ -236,7 +237,7 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> {
236237
{
237238
let id = match self.binding_map {
238239
None => self.pat.id,
239-
Some(ref map) => map[&ident.node.name],
240+
Some(ref map) => map[&mtwt::resolve(ident.node)],
240241
};
241242
let var_ty = cx.tcx.node_id_to_type(self.pat.id);
242243
let region = match var_ty.sty {

src/librustc_trans/trans/_match.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ use std::fmt;
226226
use std::rc::Rc;
227227
use rustc_front::hir;
228228
use syntax::ast::{self, DUMMY_NODE_ID, NodeId};
229+
use syntax::ext::mtwt;
229230
use syntax::codemap::Span;
230231
use rustc_front::fold::Folder;
231232
use syntax::ptr::P;
@@ -475,7 +476,7 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
475476
loop {
476477
pat = match pat.node {
477478
hir::PatIdent(_, ref path, Some(ref inner)) => {
478-
bound_ptrs.push((path.node.name, val.val));
479+
bound_ptrs.push((mtwt::resolve(path.node), val.val));
479480
&**inner
480481
},
481482
_ => break
@@ -516,15 +517,15 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
516517
match this.node {
517518
hir::PatIdent(_, ref path, None) => {
518519
if pat_is_binding(dm, &*this) {
519-
bound_ptrs.push((path.node.name, val.val));
520+
bound_ptrs.push((mtwt::resolve(path.node), val.val));
520521
}
521522
}
522523
hir::PatVec(ref before, Some(ref slice), ref after) => {
523524
if let hir::PatIdent(_, ref path, None) = slice.node {
524525
let subslice_val = bind_subslice_pat(
525526
bcx, this.id, val,
526527
before.len(), after.len());
527-
bound_ptrs.push((path.node.name, subslice_val));
528+
bound_ptrs.push((mtwt::resolve(path.node), subslice_val));
528529
}
529530
}
530531
_ => {}
@@ -1125,8 +1126,8 @@ fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
11251126
}
11261127
None => {
11271128
let data = &m[0].data;
1128-
for &(ref ident, ref value_ptr) in &m[0].bound_ptrs {
1129-
let binfo = *data.bindings_map.get(ident).unwrap();
1129+
for &(ref name, ref value_ptr) in &m[0].bound_ptrs {
1130+
let binfo = *data.bindings_map.get(name).unwrap();
11301131
call_lifetime_start(bcx, binfo.llmatch);
11311132
if binfo.trmode == TrByRef && type_is_fat_ptr(bcx.tcx(), binfo.ty) {
11321133
expr::copy_fat_ptr(bcx, *value_ptr, binfo.llmatch);
@@ -1524,8 +1525,8 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &hir::Pat,
15241525
let tcx = bcx.tcx();
15251526
let reassigned = is_discr_reassigned(bcx, discr, body);
15261527
let mut bindings_map = FnvHashMap();
1527-
pat_bindings(&tcx.def_map, &*pat, |bm, p_id, span, path1| {
1528-
let name = path1.node;
1528+
pat_bindings_hygienic(&tcx.def_map, &*pat, |bm, p_id, span, path1| {
1529+
let name = mtwt::resolve(path1.node);
15291530
let variable_ty = node_id_type(bcx, p_id);
15301531
let llvariable_ty = type_of::type_of(ccx, variable_ty);
15311532
let tcx = bcx.tcx();

src/librustc_typeck/check/_match.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use util::nodemap::FnvHashMap;
2525
use std::cmp;
2626
use std::collections::hash_map::Entry::{Occupied, Vacant};
2727
use syntax::ast;
28+
use syntax::ext::mtwt;
2829
use syntax::codemap::{Span, Spanned};
2930
use syntax::ptr::P;
3031

@@ -178,7 +179,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
178179

179180
// if there are multiple arms, make sure they all agree on
180181
// what the type of the binding `x` ought to be
181-
let canon_id = *pcx.map.get(&path.node.name).unwrap();
182+
let canon_id = *pcx.map.get(&mtwt::resolve(path.node)).unwrap();
182183
if canon_id != pat.id {
183184
let ct = fcx.local_ty(pat.span, canon_id);
184185
demand::eqtype(fcx, pat.span, ct, typ);

src/test/run-pass/issue-29746.rs

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// zip!(a1,a2,a3,a4) is equivalent to:
12+
// a1.zip(a2).zip(a3).zip(a4).map(|(((x1,x2),x3),x4)| (x1,x2,x3,x4))
13+
macro_rules! zip {
14+
// Entry point
15+
([$a:expr, $b:expr, $($rest:expr),*]) => {
16+
zip!([$($rest),*], $a.zip($b), (x,y), [x,y])
17+
};
18+
19+
// Intermediate steps to build the zipped expression, the match pattern, and
20+
// and the output tuple of the closure, using macro hygene to repeatedly
21+
// introduce new variables named 'x'.
22+
([$a:expr, $($rest:expr),*], $zip:expr, $pat:pat, [$($flat:expr),*]) => {
23+
zip!([$($rest),*], $zip.zip($a), ($pat,x), [$($flat),*, x])
24+
};
25+
26+
// Final step
27+
([], $zip:expr, $pat:pat, [$($flat:expr),+]) => {
28+
$zip.map(|$pat| ($($flat),+))
29+
};
30+
31+
// Comma
32+
([$a:expr], $zip:expr, $pat:pat, [$($flat:expr),*]) => {
33+
zip!([$a,], $zip, $pat, [$($flat),*])
34+
};
35+
}
36+
37+
fn main() {
38+
let p1 = vec![1i32, 2].into_iter();
39+
let p2 = vec!["10", "20"].into_iter();
40+
let p3 = vec![100u16, 200].into_iter();
41+
let p4 = vec![1000i64, 2000].into_iter();
42+
43+
let e = zip!([p1,p2,p3,p4]).collect::<Vec<_>>();
44+
assert_eq!(e[0], (1i32,"10",100u16,1000i64));
45+
}

0 commit comments

Comments
 (0)