diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index 09132396054ff..e794ab39e5450 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}; @@ -26,8 +27,8 @@ pub type PatIdMap = FnvHashMap; // use the NodeId of their namesake in the first pattern. pub fn pat_id_map(dm: &RefCell, 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 ba9bf4bac7d49..d83bb411b4d05 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -678,8 +678,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, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 3fd895afa983e..a590a2c61e16a 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -22,6 +22,7 @@ use rustc::middle::pat_util; use rustc::middle::ty::{self, VariantDef, Ty}; use rustc_front::hir; use rustc_front::util as hir_util; +use syntax::ext::mtwt; use syntax::parse::token; use syntax::ptr::P; @@ -490,8 +491,8 @@ fn convert_arm<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm< None } else { 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(&map) }; diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs index e9b58199023bf..3d5cb83197585 100644 --- a/src/librustc_mir/hair/cx/pattern.rs +++ b/src/librustc_mir/hair/cx/pattern.rs @@ -19,6 +19,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 @@ -161,7 +162,7 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> { { let id = match self.binding_map { None => pat.id, - Some(ref map) => map[&ident.node.name], + Some(ref map) => map[&mtwt::resolve(ident.node)], }; let var_ty = self.cx.tcx.node_id_to_type(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 0fb0407d3ba72..b2e989bc874a3 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -228,6 +228,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; @@ -477,7 +478,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 @@ -518,7 +519,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.borrow(), &*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) => { @@ -526,7 +527,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)); } } _ => {} @@ -1127,8 +1128,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); @@ -1526,8 +1527,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 cd7012cd4ec6d..aaaca48600661 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; @@ -179,7 +180,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)); +}