about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2015-11-21 02:20:52 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2015-11-21 02:20:52 +0300
commit93413fb5978023e7288ba285b4ae13e050b3bbd9 (patch)
treee2785ff6dbafc8294e39d5ff89b62d76fdfafc1d
parent9c8156057282994590d68c3067a890303129030a (diff)
downloadrust-93413fb5978023e7288ba285b4ae13e050b3bbd9.tar.gz
rust-93413fb5978023e7288ba285b4ae13e050b3bbd9.zip
backport: Fix hygiene regression in patterns
-rw-r--r--src/librustc/middle/pat_util.rs5
-rw-r--r--src/librustc_driver/driver.rs3
-rw-r--r--src/librustc_mir/tcx/expr.rs5
-rw-r--r--src/librustc_mir/tcx/pattern.rs3
-rw-r--r--src/librustc_trans/trans/_match.rs15
-rw-r--r--src/librustc_typeck/check/_match.rs3
-rw-r--r--src/test/run-pass/issue-29746.rs45
7 files changed, 65 insertions, 14 deletions
diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs
index 48550c3d8b2..04a754b82ce 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<ast::Name, ast::NodeId>;
 // 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 69c4dcb0a19..c9e4d30fef6 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 9f7ecf52287..4604ca957d8 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 e69f563edba..bb68ae825f2 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 f0e4c20be05..566b494f661 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 d89e5ee6006..2e0af6a5d85 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 00000000000..61c601ac6a9
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::<Vec<_>>();
+    assert_eq!(e[0], (1i32,"10",100u16,1000i64));
+}