about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-12-09 00:41:26 +0000
committerbors <bors@rust-lang.org>2015-12-09 00:41:26 +0000
commit462ec057649e11ce1967b0eea6c0353375c160ea (patch)
treef3652b6a07d899e0f054fc1b5e0f384c5fca1a9e
parent37b35e962ae5390a339146a57527c399fa7f88c6 (diff)
parentc1d3164700e76323e30cdf5c84af50c2ca46ff75 (diff)
downloadrust-462ec057649e11ce1967b0eea6c0353375c160ea.tar.gz
rust-462ec057649e11ce1967b0eea6c0353375c160ea.zip
Auto merge of #30145 - petrochenkov:hyg, r=nrc
Instead of `ast::Ident`, bindings, paths and labels in HIR now keep a new structure called `hir::Ident` containing mtwt-renamed `name` and the original not-renamed `unhygienic_name`. `name` is supposed to be used by default, `unhygienic_name` is rarely used.

This is not ideal, but better than the status quo for two reasons:
- MTWT tables can be cleared immediately after lowering to HIR
- This is less bug-prone, because it is impossible now to forget applying `mtwt::resolve` to a name. It is still possible to use `name` instead of `unhygienic_name` by mistake, but `unhygienic_name`s are used only in few very special circumstances, so it shouldn't be a problem.

Besides name resolution `unhygienic_name` is used in some lints and debuginfo. `unhygienic_name` can be very well approximated by "reverse renaming" `token::intern(name.as_str())` or even plain string `name.as_str()`, except that it would break gensyms like `iter` in desugared `for` loops. This approximation is likely good enough for lints and debuginfo, but not for name resolution, unfortunately (see https://github.com/rust-lang/rust/issues/27639), so `unhygienic_name` has to be kept.

cc https://github.com/rust-lang/rust/issues/29782

r? @nrc
-rw-r--r--src/librustc/middle/check_match.rs2
-rw-r--r--src/librustc/middle/liveness.rs2
-rw-r--r--src/librustc/middle/pat_util.rs12
-rw-r--r--src/librustc/middle/resolve_lifetime.rs2
-rw-r--r--src/librustc_driver/driver.rs13
-rw-r--r--src/librustc_front/fold.rs2
-rw-r--r--src/librustc_front/hir.rs70
-rw-r--r--src/librustc_front/intravisit.rs2
-rw-r--r--src/librustc_front/lowering.rs87
-rw-r--r--src/librustc_front/util.rs2
-rw-r--r--src/librustc_lint/builtin.rs4
-rw-r--r--src/librustc_mir/hair/cx/expr.rs5
-rw-r--r--src/librustc_mir/hair/cx/pattern.rs3
-rw-r--r--src/librustc_resolve/lib.rs30
-rw-r--r--src/librustc_trans/trans/_match.rs11
-rw-r--r--src/librustc_trans/trans/debuginfo/create_scope_map.rs6
-rw-r--r--src/librustc_typeck/check/_match.rs3
17 files changed, 170 insertions, 86 deletions
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index f54e3097ac4..04f907af70b 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -247,7 +247,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
                     let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
                     if let Some(DefLocal(..)) = def {
                         if edef.variants.iter().any(|variant|
-                            variant.name == ident.node.name
+                            variant.name == ident.node.unhygienic_name
                                 && variant.kind() == VariantKind::Unit
                         ) {
                             span_warn!(cx.tcx.sess, p.span, E0170,
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index c56858fcd1c..d983f26daf7 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -1596,7 +1596,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                     self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_VARIABLES, id, sp,
                         format!("variable `{}` is assigned to, but never used",
                                 name));
-                } else {
+                } else if name != "self" {
                     self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_VARIABLES, id, sp,
                         format!("unused variable: `{}`", name));
                 }
diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs
index 031b50f4620..1284e9fd145 100644
--- a/src/librustc/middle/pat_util.rs
+++ b/src/librustc/middle/pat_util.rs
@@ -14,7 +14,6 @@ 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};
@@ -27,8 +26,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: &RefCell<DefMap>, pat: &hir::Pat) -> PatIdMap {
     let mut map = FnvHashMap();
-    pat_bindings_hygienic(dm, pat, |_bm, p_id, _s, path1| {
-        map.insert(mtwt::resolve(path1.node), p_id);
+    pat_bindings(dm, pat, |_bm, p_id, _s, path1| {
+        map.insert(path1.node, p_id);
     });
     map
 }
@@ -124,9 +123,8 @@ pub fn pat_bindings<I>(dm: &RefCell<DefMap>, pat: &hir::Pat, mut it: I) where
         true
     });
 }
-
-pub fn pat_bindings_hygienic<I>(dm: &RefCell<DefMap>, pat: &hir::Pat, mut it: I) where
-    I: FnMut(hir::BindingMode, ast::NodeId, Span, &Spanned<ast::Ident>),
+pub fn pat_bindings_ident<I>(dm: &RefCell<DefMap>, pat: &hir::Pat, mut it: I) where
+    I: FnMut(hir::BindingMode, ast::NodeId, Span, &Spanned<hir::Ident>),
 {
     walk_pat(pat, |p| {
         match p.node {
@@ -214,7 +212,7 @@ pub fn def_to_path(tcx: &ty::ctxt, id: DefId) -> hir::Path {
     tcx.with_path(id, |path| hir::Path {
         global: false,
         segments: path.last().map(|elem| hir::PathSegment {
-            identifier: ast::Ident::with_empty_ctxt(elem.name()),
+            identifier: hir::Ident::from_name(elem.name()),
             parameters: hir::PathParameters::none(),
         }).into_iter().collect(),
         span: DUMMY_SP,
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 4425a24590c..b37b3070310 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -426,7 +426,7 @@ fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v hir::Block) {
     fn expression_label(ex: &hir::Expr) -> Option<ast::Name> {
         match ex.node {
             hir::ExprWhile(_, _, Some(label)) |
-            hir::ExprLoop(_, Some(label)) => Some(label.name),
+            hir::ExprLoop(_, Some(label)) => Some(label.unhygienic_name),
             _ => None,
         }
     }
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index a8b2f382468..69e065b3e8f 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -112,6 +112,13 @@ pub fn compile_input(sess: Session,
         let mut hir_forest = time(sess.time_passes(),
                                   "lowering ast -> hir",
                                   || hir_map::Forest::new(lower_crate(&lcx, &expanded_crate)));
+
+        // Discard MTWT tables that aren't required past lowering to HIR.
+        if !sess.opts.debugging_opts.keep_mtwt_tables &&
+           !sess.opts.debugging_opts.save_analysis {
+            syntax::ext::mtwt::clear_tables();
+        }
+
         let arenas = ty::CtxtArenas::new();
         let ast_map = make_map(&sess, &mut hir_forest);
 
@@ -704,12 +711,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
              "resolution",
              || 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();
-    }
-
     let named_region_map = time(time_passes,
                                 "lifetime resolution",
                                 || middle::resolve_lifetime::krate(sess, krate, &def_map.borrow()));
diff --git a/src/librustc_front/fold.rs b/src/librustc_front/fold.rs
index 9ab26e0bfa3..08280e98ae4 100644
--- a/src/librustc_front/fold.rs
+++ b/src/librustc_front/fold.rs
@@ -12,7 +12,7 @@
 //! and returns a piece of the same type.
 
 use hir::*;
-use syntax::ast::{Ident, Name, NodeId, DUMMY_NODE_ID, Attribute, Attribute_, MetaItem};
+use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, Attribute, Attribute_, MetaItem};
 use syntax::ast::{MetaWord, MetaList, MetaNameValue};
 use syntax::attr::ThinAttributesExt;
 use hir;
diff --git a/src/librustc_front/hir.rs b/src/librustc_front/hir.rs
index dae7e38a2bf..10e5a091c0d 100644
--- a/src/librustc_front/hir.rs
+++ b/src/librustc_front/hir.rs
@@ -39,7 +39,7 @@ use intravisit::Visitor;
 use std::collections::BTreeMap;
 use syntax::codemap::{self, Span, Spanned, DUMMY_SP, ExpnId};
 use syntax::abi::Abi;
-use syntax::ast::{Name, Ident, NodeId, DUMMY_NODE_ID, TokenTree, AsmDialect};
+use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, TokenTree, AsmDialect};
 use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, CrateConfig};
 use syntax::attr::ThinAttributes;
 use syntax::owned_slice::OwnedSlice;
@@ -50,7 +50,65 @@ use print::pprust;
 use util;
 
 use std::fmt;
-use serialize::{Encodable, Encoder, Decoder};
+use std::hash::{Hash, Hasher};
+use serialize::{Encodable, Decodable, Encoder, Decoder};
+
+/// Identifier in HIR
+#[derive(Clone, Copy, Eq)]
+pub struct Ident {
+    /// Hygienic name (renamed), should be used by default
+    pub name: Name,
+    /// Unhygienic name (original, not renamed), needed in few places in name resolution
+    pub unhygienic_name: Name,
+}
+
+impl Ident {
+    /// Creates a HIR identifier with both `name` and `unhygienic_name` initialized with
+    /// the argument. Hygiene properties of the created identifier depend entirely on this
+    /// argument. If the argument is a plain interned string `intern("iter")`, then the result
+    /// is unhygienic and can interfere with other entities named "iter". If the argument is
+    /// a "fresh" name created with `gensym("iter")`, then the result is hygienic and can't
+    /// interfere with other entities having the same string as a name.
+    pub fn from_name(name: Name) -> Ident {
+        Ident { name: name, unhygienic_name: name }
+    }
+}
+
+impl PartialEq for Ident {
+    fn eq(&self, other: &Ident) -> bool {
+        self.name == other.name
+    }
+}
+
+impl Hash for Ident {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.name.hash(state)
+    }
+}
+
+impl fmt::Debug for Ident {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&self.name, f)
+    }
+}
+
+impl fmt::Display for Ident {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&self.name, f)
+    }
+}
+
+impl Encodable for Ident {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        self.name.encode(s)
+    }
+}
+
+impl Decodable for Ident {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
+        Ok(Ident::from_name(try!(Name::decode(d))))
+    }
+}
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
 pub struct Lifetime {
@@ -105,6 +163,14 @@ impl fmt::Display for Path {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct PathSegment {
     /// The identifier portion of this path segment.
+    ///
+    /// Hygiene properties of this identifier are worth noting.
+    /// Most path segments are not hygienic and they are not renamed during
+    /// lowering from AST to HIR (see comments to `fn lower_path`). However segments from
+    /// unqualified paths with one segment originating from `ExprPath` (local-variable-like paths)
+    /// can be hygienic, so they are renamed. You should not normally care about this peculiarity
+    /// and just use `identifier.name` unless you modify identifier resolution code
+    /// (`fn resolve_identifier` and other functions called by it in `rustc_resolve`).
     pub identifier: Ident,
 
     /// Type/lifetime parameters attached to this path. They come in
diff --git a/src/librustc_front/intravisit.rs b/src/librustc_front/intravisit.rs
index 3a43feb8ba7..e93f5cbd0fb 100644
--- a/src/librustc_front/intravisit.rs
+++ b/src/librustc_front/intravisit.rs
@@ -26,7 +26,7 @@
 //! property.
 
 use syntax::abi::Abi;
-use syntax::ast::{Ident, NodeId, CRATE_NODE_ID, Name, Attribute};
+use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
 use syntax::codemap::Span;
 use hir::*;
 
diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs
index 5a169095fa9..7dbd6dbf0b8 100644
--- a/src/librustc_front/lowering.rs
+++ b/src/librustc_front/lowering.rs
@@ -67,10 +67,11 @@ use std::collections::BTreeMap;
 use std::collections::HashMap;
 use syntax::ast::*;
 use syntax::attr::{ThinAttributes, ThinAttributesExt};
+use syntax::ext::mtwt;
 use syntax::ptr::P;
 use syntax::codemap::{respan, Spanned, Span};
 use syntax::owned_slice::OwnedSlice;
-use syntax::parse::token::{self, str_to_ident};
+use syntax::parse::token;
 use syntax::std_inject;
 use syntax::visit::{self, Visitor};
 
@@ -86,7 +87,7 @@ pub struct LoweringContext<'a> {
     // incrementing.
     cached_id: Cell<u32>,
     // Keep track of gensym'ed idents.
-    gensym_cache: RefCell<HashMap<(NodeId, &'static str), Ident>>,
+    gensym_cache: RefCell<HashMap<(NodeId, &'static str), hir::Ident>>,
     // A copy of cached_id, but is also set to an id while it is being cached.
     gensym_key: Cell<u32>,
 }
@@ -123,23 +124,30 @@ impl<'a, 'hir> LoweringContext<'a> {
         cached
     }
 
-    fn str_to_ident(&self, s: &'static str) -> Ident {
+    fn str_to_ident(&self, s: &'static str) -> hir::Ident {
         let cached_id = self.gensym_key.get();
         if cached_id == 0 {
-            return token::gensym_ident(s);
+            return hir::Ident::from_name(token::gensym(s));
         }
 
         let cached = self.gensym_cache.borrow().contains_key(&(cached_id, s));
         if cached {
             self.gensym_cache.borrow()[&(cached_id, s)]
         } else {
-            let result = token::gensym_ident(s);
+            let result = hir::Ident::from_name(token::gensym(s));
             self.gensym_cache.borrow_mut().insert((cached_id, s), result);
             result
         }
     }
 }
 
+pub fn lower_ident(_lctx: &LoweringContext, ident: Ident) -> hir::Ident {
+    hir::Ident {
+        name: mtwt::resolve(ident),
+        unhygienic_name: ident.name,
+    }
+}
+
 pub fn lower_view_path(lctx: &LoweringContext, view_path: &ViewPath) -> P<hir::ViewPath> {
     P(Spanned {
         node: match view_path.node {
@@ -276,14 +284,22 @@ pub fn lower_variant(lctx: &LoweringContext, v: &Variant) -> hir::Variant {
     }
 }
 
-pub fn lower_path(lctx: &LoweringContext, p: &Path) -> hir::Path {
+// Path segments are usually unhygienic, hygienic path segments can occur only in
+// identifier-like paths originating from `ExprPath`.
+// Make life simpler for rustc_resolve by renaming only such segments.
+pub fn lower_path_full(lctx: &LoweringContext, p: &Path, maybe_hygienic: bool) -> hir::Path {
+    let maybe_hygienic = maybe_hygienic && !p.global && p.segments.len() == 1;
     hir::Path {
         global: p.global,
         segments: p.segments
                    .iter()
                    .map(|&PathSegment { identifier, ref parameters }| {
                        hir::PathSegment {
-                           identifier: identifier,
+                           identifier: if maybe_hygienic {
+                               lower_ident(lctx, identifier)
+                           } else {
+                               hir::Ident::from_name(identifier.name)
+                           },
                            parameters: lower_path_parameters(lctx, parameters),
                        }
                    })
@@ -292,6 +308,10 @@ pub fn lower_path(lctx: &LoweringContext, p: &Path) -> hir::Path {
     }
 }
 
+pub fn lower_path(lctx: &LoweringContext, p: &Path) -> hir::Path {
+    lower_path_full(lctx, p, false)
+}
+
 pub fn lower_path_parameters(lctx: &LoweringContext,
                              path_parameters: &PathParameters)
                              -> hir::PathParameters {
@@ -844,7 +864,7 @@ pub fn lower_pat(lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> {
             PatWild => hir::PatWild,
             PatIdent(ref binding_mode, pth1, ref sub) => {
                 hir::PatIdent(lower_binding_mode(lctx, binding_mode),
-                              pth1,
+                              respan(pth1.span, lower_ident(lctx, pth1.node)),
                               sub.as_ref().map(|x| lower_pat(lctx, x)))
             }
             PatLit(ref e) => hir::PatLit(lower_expr(lctx, e)),
@@ -1138,10 +1158,12 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                 hir::ExprIf(lower_expr(lctx, cond), lower_block(lctx, blk), else_opt)
             }
             ExprWhile(ref cond, ref body, opt_ident) => {
-                hir::ExprWhile(lower_expr(lctx, cond), lower_block(lctx, body), opt_ident)
+                hir::ExprWhile(lower_expr(lctx, cond), lower_block(lctx, body),
+                               opt_ident.map(|ident| lower_ident(lctx, ident)))
             }
             ExprLoop(ref body, opt_ident) => {
-                hir::ExprLoop(lower_block(lctx, body), opt_ident)
+                hir::ExprLoop(lower_block(lctx, body),
+                              opt_ident.map(|ident| lower_ident(lctx, ident)))
             }
             ExprMatch(ref expr, ref arms) => {
                 hir::ExprMatch(lower_expr(lctx, expr),
@@ -1176,16 +1198,20 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                                e2.as_ref().map(|x| lower_expr(lctx, x)))
             }
             ExprPath(ref qself, ref path) => {
-                let qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
+                let hir_qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
                     hir::QSelf {
                         ty: lower_ty(lctx, ty),
                         position: position,
                     }
                 });
-                hir::ExprPath(qself, lower_path(lctx, path))
+                hir::ExprPath(hir_qself, lower_path_full(lctx, path, qself.is_none()))
             }
-            ExprBreak(opt_ident) => hir::ExprBreak(opt_ident),
-            ExprAgain(opt_ident) => hir::ExprAgain(opt_ident),
+            ExprBreak(opt_ident) => hir::ExprBreak(opt_ident.map(|sp_ident| {
+                respan(sp_ident.span, lower_ident(lctx, sp_ident.node))
+            })),
+            ExprAgain(opt_ident) => hir::ExprAgain(opt_ident.map(|sp_ident| {
+                respan(sp_ident.span, lower_ident(lctx, sp_ident.node))
+            })),
             ExprRet(ref e) => hir::ExprRet(e.as_ref().map(|x| lower_expr(lctx, x))),
             ExprInlineAsm(InlineAsm {
                     ref inputs,
@@ -1356,8 +1382,10 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
 
                     // `[opt_ident]: loop { ... }`
                     let loop_block = block_expr(lctx, match_expr);
+                    let loop_expr = hir::ExprLoop(loop_block,
+                                                  opt_ident.map(|ident| lower_ident(lctx, ident)));
                     // add attributes to the outer returned expr node
-                    expr(lctx, e.span, hir::ExprLoop(loop_block, opt_ident), e.attrs.clone())
+                    expr(lctx, e.span, loop_expr, e.attrs.clone())
                 });
             }
 
@@ -1434,10 +1462,9 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
 
                     // `[opt_ident]: loop { ... }`
                     let loop_block = block_expr(lctx, match_expr);
-                    let loop_expr = expr(lctx,
-                                         e.span,
-                                         hir::ExprLoop(loop_block, opt_ident),
-                                         None);
+                    let loop_expr = hir::ExprLoop(loop_block,
+                                                  opt_ident.map(|ident| lower_ident(lctx, ident)));
+                    let loop_expr = expr(lctx, e.span, loop_expr, None);
 
                     // `mut iter => { ... }`
                     let iter_arm = {
@@ -1593,7 +1620,7 @@ fn expr_call(lctx: &LoweringContext,
     expr(lctx, span, hir::ExprCall(e, args), attrs)
 }
 
-fn expr_ident(lctx: &LoweringContext, span: Span, id: Ident,
+fn expr_ident(lctx: &LoweringContext, span: Span, id: hir::Ident,
               attrs: ThinAttributes) -> P<hir::Expr> {
     expr_path(lctx, path_ident(span, id), attrs)
 }
@@ -1641,7 +1668,7 @@ fn expr(lctx: &LoweringContext, span: Span, node: hir::Expr_,
 fn stmt_let(lctx: &LoweringContext,
             sp: Span,
             mutbl: bool,
-            ident: Ident,
+            ident: hir::Ident,
             ex: P<hir::Expr>,
             attrs: ThinAttributes)
             -> hir::Stmt {
@@ -1701,13 +1728,13 @@ fn pat_enum(lctx: &LoweringContext,
     pat(lctx, span, pt)
 }
 
-fn pat_ident(lctx: &LoweringContext, span: Span, ident: Ident) -> P<hir::Pat> {
+fn pat_ident(lctx: &LoweringContext, span: Span, ident: hir::Ident) -> P<hir::Pat> {
     pat_ident_binding_mode(lctx, span, ident, hir::BindByValue(hir::MutImmutable))
 }
 
 fn pat_ident_binding_mode(lctx: &LoweringContext,
                           span: Span,
-                          ident: Ident,
+                          ident: hir::Ident,
                           bm: hir::BindingMode)
                           -> P<hir::Pat> {
     let pat_ident = hir::PatIdent(bm,
@@ -1731,21 +1758,21 @@ fn pat(lctx: &LoweringContext, span: Span, pat: hir::Pat_) -> P<hir::Pat> {
     })
 }
 
-fn path_ident(span: Span, id: Ident) -> hir::Path {
+fn path_ident(span: Span, id: hir::Ident) -> hir::Path {
     path(span, vec![id])
 }
 
-fn path(span: Span, strs: Vec<Ident>) -> hir::Path {
+fn path(span: Span, strs: Vec<hir::Ident>) -> hir::Path {
     path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new())
 }
 
-fn path_global(span: Span, strs: Vec<Ident>) -> hir::Path {
+fn path_global(span: Span, strs: Vec<hir::Ident>) -> hir::Path {
     path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new())
 }
 
 fn path_all(sp: Span,
             global: bool,
-            mut idents: Vec<Ident>,
+            mut idents: Vec<hir::Ident>,
             lifetimes: Vec<hir::Lifetime>,
             types: Vec<P<hir::Ty>>,
             bindings: Vec<hir::TypeBinding>)
@@ -1774,12 +1801,12 @@ fn path_all(sp: Span,
     }
 }
 
-fn std_path(lctx: &LoweringContext, components: &[&str]) -> Vec<Ident> {
+fn std_path(lctx: &LoweringContext, components: &[&str]) -> Vec<hir::Ident> {
     let mut v = Vec::new();
     if let Some(s) = lctx.crate_root {
-        v.push(str_to_ident(s));
+        v.push(hir::Ident::from_name(token::intern(s)));
     }
-    v.extend(components.iter().map(|s| str_to_ident(s)));
+    v.extend(components.iter().map(|s| hir::Ident::from_name(token::intern(s))));
     return v;
 }
 
diff --git a/src/librustc_front/util.rs b/src/librustc_front/util.rs
index 97b25dafb6d..4dc08f7a048 100644
--- a/src/librustc_front/util.rs
+++ b/src/librustc_front/util.rs
@@ -12,7 +12,7 @@ use hir;
 use hir::*;
 use intravisit::{self, Visitor, FnKind};
 use syntax::ast_util;
-use syntax::ast::{Ident, Name, NodeId, DUMMY_NODE_ID};
+use syntax::ast::{Name, NodeId, DUMMY_NODE_ID};
 use syntax::codemap::Span;
 use syntax::ptr::P;
 use syntax::owned_slice::OwnedSlice;
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 739c5f12ecb..90d9bcfffee 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -170,9 +170,7 @@ impl LateLintPass for NonShorthandFieldPatterns {
             });
             for fieldpat in field_pats {
                 if let hir::PatIdent(_, ident, None) = fieldpat.node.pat.node {
-                    if ident.node.name == fieldpat.node.name {
-                        // FIXME: should this comparison really be done on the name?
-                        // doing it on the ident will fail during compilation of libcore
+                    if ident.node.unhygienic_name == fieldpat.node.name {
                         cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span,
                                      &format!("the `{}:` in this pattern is redundant and can \
                                               be removed", ident.node))
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 24091d7dc37..08826013ebc 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -21,7 +21,6 @@ use rustc::middle::ty::{self, VariantDef, Ty};
 use rustc::mir::repr::*;
 use rustc_front::hir;
 use rustc_front::util as hir_util;
-use syntax::ext::mtwt;
 use syntax::parse::token;
 use syntax::ptr::P;
 
@@ -500,8 +499,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_hygienic(&cx.tcx.def_map, &arm.pats[0], |_, p_id, _, path| {
-            map.insert(mtwt::resolve(path.node), p_id);
+        pat_util::pat_bindings(&cx.tcx.def_map, &arm.pats[0], |_, p_id, _, path| {
+            map.insert(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 bea7950c33a..74fef684006 100644
--- a/src/librustc_mir/hair/cx/pattern.rs
+++ b/src/librustc_mir/hair/cx/pattern.rs
@@ -19,7 +19,6 @@ use rustc::middle::ty::{self, Ty};
 use rustc::mir::repr::*;
 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
@@ -162,7 +161,7 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
             {
                 let id = match self.binding_map {
                     None => pat.id,
-                    Some(ref map) => map[&mtwt::resolve(ident.node)],
+                    Some(ref map) => map[&ident.node.name],
                 };
                 let var_ty = self.cx.tcx.node_id_to_type(pat.id);
                 let region = match var_ty.sty {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 469ec14a1a0..ddada1b513d 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -57,7 +57,7 @@ use rustc::lint;
 use rustc::middle::cstore::{CrateStore, DefLike, DlDef};
 use rustc::middle::def::*;
 use rustc::middle::def_id::DefId;
-use rustc::middle::pat_util::pat_bindings_hygienic;
+use rustc::middle::pat_util::pat_bindings;
 use rustc::middle::privacy::*;
 use rustc::middle::subst::{ParamSpace, FnSpace, TypeSpace};
 use rustc::middle::ty::{Freevar, FreevarMap, TraitMap, GlobMap};
@@ -67,7 +67,6 @@ use syntax::ast;
 use syntax::ast::{CRATE_NODE_ID, Ident, Name, NodeId, CrateNum, TyIs, TyI8, TyI16, TyI32, TyI64};
 use syntax::ast::{TyUs, TyU8, TyU16, TyU32, TyU64, TyF64, TyF32};
 use syntax::attr::AttrMetaMethods;
-use syntax::ext::mtwt;
 use syntax::parse::token::{self, special_names, special_idents};
 use syntax::codemap::{self, Span, Pos};
 use syntax::util::lev_distance::{lev_distance, max_suggestion_distance};
@@ -2314,8 +2313,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     // user and one 'x' came from the macro.
     fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
         let mut result = HashMap::new();
-        pat_bindings_hygienic(&self.def_map, pat, |binding_mode, _id, sp, path1| {
-            let name = mtwt::resolve(path1.node);
+        pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path1| {
+            let name = path1.node;
             result.insert(name,
                           BindingInfo {
                               span: sp,
@@ -2519,9 +2518,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     let const_ok = mode == RefutableMode && at_rhs.is_none();
 
                     let ident = path1.node;
-                    let renamed = mtwt::resolve(ident);
+                    let renamed = ident.name;
 
-                    match self.resolve_bare_identifier_pattern(ident.name, pattern.span) {
+                    match self.resolve_bare_identifier_pattern(ident.unhygienic_name,
+                                                               pattern.span) {
                         FoundStructOrEnumVariant(def, lp) if const_ok => {
                             debug!("(resolving pattern) resolving `{}` to struct or enum variant",
                                    renamed);
@@ -2910,7 +2910,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
     // Resolve a single identifier
     fn resolve_identifier(&mut self,
-                          identifier: Ident,
+                          identifier: hir::Ident,
                           namespace: Namespace,
                           check_ribs: bool)
                           -> Option<LocalDef> {
@@ -2918,7 +2918,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         if namespace == TypeNS {
             if let Some(&prim_ty) = self.primitive_type_table
                                         .primitive_types
-                                        .get(&identifier.name) {
+                                        .get(&identifier.unhygienic_name) {
                 return Some(LocalDef::from_def(DefPrimTy(prim_ty)));
             }
         }
@@ -2929,7 +2929,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
         }
 
-        self.resolve_item_by_name_in_lexical_scope(identifier.name, namespace)
+        self.resolve_item_by_name_in_lexical_scope(identifier.unhygienic_name, namespace)
             .map(LocalDef::from_def)
     }
 
@@ -3143,13 +3143,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     }
 
     fn resolve_identifier_in_local_ribs(&mut self,
-                                        ident: Ident,
+                                        ident: hir::Ident,
                                         namespace: Namespace)
                                         -> Option<LocalDef> {
         // Check the local set of ribs.
         let (name, ribs) = match namespace {
-            ValueNS => (mtwt::resolve(ident), &self.value_ribs),
-            TypeNS => (ident.name, &self.type_ribs),
+            ValueNS => (ident.name, &self.value_ribs),
+            TypeNS => (ident.unhygienic_name, &self.type_ribs),
         };
 
         for (i, rib) in ribs.iter().enumerate().rev() {
@@ -3550,8 +3550,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
                     {
                         let rib = this.label_ribs.last_mut().unwrap();
-                        let renamed = mtwt::resolve(label);
-                        rib.bindings.insert(renamed, def_like);
+                        rib.bindings.insert(label.name, def_like);
                     }
 
                     intravisit::walk_expr(this, expr);
@@ -3559,8 +3558,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
 
             ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
-                let renamed = mtwt::resolve(label.node);
-                match self.search_label(renamed) {
+                match self.search_label(label.node.name) {
                     None => {
                         resolve_error(self,
                                       label.span,
diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs
index 1687b229a7f..fe8e8cea140 100644
--- a/src/librustc_trans/trans/_match.rs
+++ b/src/librustc_trans/trans/_match.rs
@@ -228,7 +228,6 @@ 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;
@@ -478,7 +477,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((mtwt::resolve(path.node), val.val));
+                    bound_ptrs.push((path.node.name, val.val));
                     &**inner
                 },
                 _ => break
@@ -519,7 +518,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((mtwt::resolve(path.node), val.val));
+                        bound_ptrs.push((path.node.name, val.val));
                     }
                 }
                 hir::PatVec(ref before, Some(ref slice), ref after) => {
@@ -527,7 +526,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((mtwt::resolve(path.node), subslice_val));
+                        bound_ptrs.push((path.node.name, subslice_val));
                     }
                 }
                 _ => {}
@@ -1527,8 +1526,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_hygienic(&tcx.def_map, &*pat, |bm, p_id, span, path1| {
-        let name = mtwt::resolve(path1.node);
+    pat_bindings(&tcx.def_map, &*pat, |bm, p_id, span, path1| {
+        let name = 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_trans/trans/debuginfo/create_scope_map.rs b/src/librustc_trans/trans/debuginfo/create_scope_map.rs
index 3296495453e..7d88e579e5a 100644
--- a/src/librustc_trans/trans/debuginfo/create_scope_map.rs
+++ b/src/librustc_trans/trans/debuginfo/create_scope_map.rs
@@ -47,9 +47,9 @@ pub fn create_scope_map(cx: &CrateContext,
     // Push argument identifiers onto the stack so arguments integrate nicely
     // with variable shadowing.
     for arg in args {
-        pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, _, path1| {
+        pat_util::pat_bindings_ident(def_map, &*arg.pat, |_, node_id, _, path1| {
             scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata,
-                                               name: Some(path1.node) });
+                                               name: Some(path1.node.unhygienic_name) });
             scope_map.insert(node_id, fn_metadata);
         })
     }
@@ -169,7 +169,7 @@ fn walk_pattern(cx: &CrateContext,
             // scope stack and maybe introduce an artificial scope
             if pat_util::pat_is_binding(&def_map.borrow(), &*pat) {
 
-                let name = path1.node.name;
+                let name = path1.node.unhygienic_name;
 
                 // LLVM does not properly generate 'DW_AT_start_scope' fields
                 // for variable DIEs. For this reason we have to introduce
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 8c68a546235..38c714fa8f2 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -26,7 +26,6 @@ use session::Session;
 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;
 
@@ -187,7 +186,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(&mtwt::resolve(path.node)).unwrap();
+            let canon_id = *pcx.map.get(&path.node.name).unwrap();
             if canon_id != pat.id {
                 let ct = fcx.local_ty(pat.span, canon_id);
                 demand::eqtype(fcx, pat.span, ct, typ);