diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index 48550c3d8b2f1..04a754b82ce5f 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -14,6 +14,7 @@ use middle::ty; use util::nodemap::FnvHashMap; use syntax::ast; +use syntax::ext::mtwt; use rustc_front::hir; use rustc_front::util::walk_pat; use syntax::codemap::{respan, Span, Spanned, DUMMY_SP}; @@ -24,8 +25,8 @@ pub type PatIdMap = FnvHashMap; // use the NodeId of their namesake in the first pattern. pub fn pat_id_map(dm: &DefMap, pat: &hir::Pat) -> PatIdMap { let mut map = FnvHashMap(); - pat_bindings(dm, pat, |_bm, p_id, _s, path1| { - map.insert(path1.node, p_id); + pat_bindings_hygienic(dm, pat, |_bm, p_id, _s, path1| { + map.insert(mtwt::resolve(path1.node), p_id); }); map } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 69c4dcb0a197c..c9e4d30fef641 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -693,8 +693,9 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, || resolve::resolve_crate(sess, &ast_map, make_glob_map)); // Discard MTWT tables that aren't required past resolution. + // FIXME: get rid of uses of MTWT tables in typeck, mir and trans and clear them if !sess.opts.debugging_opts.keep_mtwt_tables { - syntax::ext::mtwt::clear_tables(); + // syntax::ext::mtwt::clear_tables(); } let named_region_map = time(time_passes, "lifetime resolution", diff --git a/src/librustc_mir/tcx/expr.rs b/src/librustc_mir/tcx/expr.rs index 9f7ecf522876f..4604ca957d88e 100644 --- a/src/librustc_mir/tcx/expr.rs +++ b/src/librustc_mir/tcx/expr.rs @@ -24,6 +24,7 @@ use rustc::middle::pat_util; use rustc::middle::ty::{self, Ty}; use rustc_front::hir; use rustc_front::util as hir_util; +use syntax::ext::mtwt; use syntax::parse::token; use syntax::ptr::P; @@ -477,8 +478,8 @@ fn convert_arm<'a, 'tcx: 'a>(cx: &Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx None } else { let mut map = FnvHashMap(); - pat_util::pat_bindings(&cx.tcx.def_map, &arm.pats[0], |_, p_id, _, path| { - map.insert(path.node, p_id); + pat_util::pat_bindings_hygienic(&cx.tcx.def_map, &arm.pats[0], |_, p_id, _, path| { + map.insert(mtwt::resolve(path.node), p_id); }); Some(Rc::new(map)) }; diff --git a/src/librustc_mir/tcx/pattern.rs b/src/librustc_mir/tcx/pattern.rs index e69f563edbac3..bb68ae825f2f7 100644 --- a/src/librustc_mir/tcx/pattern.rs +++ b/src/librustc_mir/tcx/pattern.rs @@ -22,6 +22,7 @@ use rustc::middle::subst::Substs; use rustc::middle::ty::{self, Ty}; use rustc_front::hir; use syntax::ast; +use syntax::ext::mtwt; use syntax::ptr::P; /// When there are multiple patterns in a single arm, each one has its @@ -236,7 +237,7 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> { { let id = match self.binding_map { None => self.pat.id, - Some(ref map) => map[&ident.node.name], + Some(ref map) => map[&mtwt::resolve(ident.node)], }; let var_ty = cx.tcx.node_id_to_type(self.pat.id); let region = match var_ty.sty { diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index f0e4c20be0505..566b494f66175 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -226,6 +226,7 @@ use std::fmt; use std::rc::Rc; use rustc_front::hir; use syntax::ast::{self, DUMMY_NODE_ID, NodeId}; +use syntax::ext::mtwt; use syntax::codemap::Span; use rustc_front::fold::Folder; use syntax::ptr::P; @@ -475,7 +476,7 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, loop { pat = match pat.node { hir::PatIdent(_, ref path, Some(ref inner)) => { - bound_ptrs.push((path.node.name, val.val)); + bound_ptrs.push((mtwt::resolve(path.node), val.val)); &**inner }, _ => break @@ -516,7 +517,7 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, match this.node { hir::PatIdent(_, ref path, None) => { if pat_is_binding(dm, &*this) { - bound_ptrs.push((path.node.name, val.val)); + bound_ptrs.push((mtwt::resolve(path.node), val.val)); } } hir::PatVec(ref before, Some(ref slice), ref after) => { @@ -524,7 +525,7 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let subslice_val = bind_subslice_pat( bcx, this.id, val, before.len(), after.len()); - bound_ptrs.push((path.node.name, subslice_val)); + bound_ptrs.push((mtwt::resolve(path.node), subslice_val)); } } _ => {} @@ -1125,8 +1126,8 @@ fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } None => { let data = &m[0].data; - for &(ref ident, ref value_ptr) in &m[0].bound_ptrs { - let binfo = *data.bindings_map.get(ident).unwrap(); + for &(ref name, ref value_ptr) in &m[0].bound_ptrs { + let binfo = *data.bindings_map.get(name).unwrap(); call_lifetime_start(bcx, binfo.llmatch); if binfo.trmode == TrByRef && type_is_fat_ptr(bcx.tcx(), binfo.ty) { 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, let tcx = bcx.tcx(); let reassigned = is_discr_reassigned(bcx, discr, body); let mut bindings_map = FnvHashMap(); - pat_bindings(&tcx.def_map, &*pat, |bm, p_id, span, path1| { - let name = path1.node; + pat_bindings_hygienic(&tcx.def_map, &*pat, |bm, p_id, span, path1| { + let name = mtwt::resolve(path1.node); let variable_ty = node_id_type(bcx, p_id); let llvariable_ty = type_of::type_of(ccx, variable_ty); let tcx = bcx.tcx(); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index d89e5ee6006a4..2e0af6a5d852a 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -25,6 +25,7 @@ use util::nodemap::FnvHashMap; 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; @@ -178,7 +179,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); diff --git a/src/test/run-pass/issue-29746.rs b/src/test/run-pass/issue-29746.rs new file mode 100644 index 0000000000000..61c601ac6a903 --- /dev/null +++ b/src/test/run-pass/issue-29746.rs @@ -0,0 +1,45 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// zip!(a1,a2,a3,a4) is equivalent to: +// a1.zip(a2).zip(a3).zip(a4).map(|(((x1,x2),x3),x4)| (x1,x2,x3,x4)) +macro_rules! zip { + // Entry point + ([$a:expr, $b:expr, $($rest:expr),*]) => { + zip!([$($rest),*], $a.zip($b), (x,y), [x,y]) + }; + + // Intermediate steps to build the zipped expression, the match pattern, and + // and the output tuple of the closure, using macro hygene to repeatedly + // introduce new variables named 'x'. + ([$a:expr, $($rest:expr),*], $zip:expr, $pat:pat, [$($flat:expr),*]) => { + zip!([$($rest),*], $zip.zip($a), ($pat,x), [$($flat),*, x]) + }; + + // Final step + ([], $zip:expr, $pat:pat, [$($flat:expr),+]) => { + $zip.map(|$pat| ($($flat),+)) + }; + + // Comma + ([$a:expr], $zip:expr, $pat:pat, [$($flat:expr),*]) => { + zip!([$a,], $zip, $pat, [$($flat),*]) + }; +} + +fn main() { + let p1 = vec![1i32, 2].into_iter(); + let p2 = vec!["10", "20"].into_iter(); + let p3 = vec![100u16, 200].into_iter(); + let p4 = vec![1000i64, 2000].into_iter(); + + let e = zip!([p1,p2,p3,p4]).collect::>(); + assert_eq!(e[0], (1i32,"10",100u16,1000i64)); +}