about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/hir/lowering.rs14
-rw-r--r--src/librustc_lint/builtin.rs10
-rw-r--r--src/librustc_mir/build/mod.rs4
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs6
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs15
-rw-r--r--src/librustc_resolve/lib.rs133
-rw-r--r--src/librustc_resolve/macros.rs17
-rw-r--r--src/librustc_resolve/resolve_imports.rs28
-rw-r--r--src/librustc_save_analysis/lib.rs12
-rw-r--r--src/librustc_save_analysis/sig.rs2
-rw-r--r--src/libsyntax/ast.rs16
-rw-r--r--src/libsyntax/attr.rs2
-rw-r--r--src/libsyntax/ext/base.rs2
-rw-r--r--src/libsyntax/ext/build.rs23
-rw-r--r--src/libsyntax/ext/quote.rs2
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs6
-rw-r--r--src/libsyntax/fold.rs26
-rw-r--r--src/libsyntax/parse/parser.rs67
-rw-r--r--src/libsyntax/parse/token.rs6
-rw-r--r--src/libsyntax/print/pprust.rs52
-rw-r--r--src/libsyntax/visit.rs10
-rw-r--r--src/libsyntax_ext/concat_idents.rs33
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs10
-rw-r--r--src/libsyntax_pos/symbol.rs7
24 files changed, 231 insertions, 272 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 2ca386e287d..08b0def03b9 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1720,7 +1720,7 @@ impl<'a> LoweringContext<'a> {
         decl.inputs
             .iter()
             .map(|arg| match arg.pat.node {
-                PatKind::Ident(_, ident, None) => respan(ident.span, ident.node.name),
+                PatKind::Ident(_, ident, None) => respan(ident.span, ident.name),
                 _ => respan(arg.pat.span, keywords::Invalid.name()),
             })
             .collect()
@@ -2099,7 +2099,7 @@ impl<'a> LoweringContext<'a> {
 
     fn lower_field(&mut self, f: &Field) -> hir::Field {
         hir::Field {
-            name: respan(f.ident.span, self.lower_ident(f.ident.node)),
+            name: respan(f.ident.span, self.lower_ident(f.ident)),
             expr: P(self.lower_expr(&f.expr)),
             span: f.span,
             is_shorthand: f.is_shorthand,
@@ -2801,7 +2801,7 @@ impl<'a> LoweringContext<'a> {
     fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
         let node = match p.node {
             PatKind::Wild => hir::PatKind::Wild,
-            PatKind::Ident(ref binding_mode, pth1, ref sub) => {
+            PatKind::Ident(ref binding_mode, ident, ref sub) => {
                 match self.resolver.get_resolution(p.id).map(|d| d.base_def()) {
                     // `None` can occur in body-less function signatures
                     def @ None | def @ Some(Def::Local(_)) => {
@@ -2812,16 +2812,16 @@ impl<'a> LoweringContext<'a> {
                         hir::PatKind::Binding(
                             self.lower_binding_mode(binding_mode),
                             canonical_id,
-                            respan(pth1.span, pth1.node.name),
+                            respan(ident.span, ident.name),
                             sub.as_ref().map(|x| self.lower_pat(x)),
                         )
                     }
                     Some(def) => hir::PatKind::Path(hir::QPath::Resolved(
                         None,
                         P(hir::Path {
-                            span: pth1.span,
+                            span: ident.span,
                             def,
-                            segments: hir_vec![hir::PathSegment::from_name(pth1.node.name)],
+                            segments: hir_vec![hir::PathSegment::from_name(ident.name)],
                         }),
                     )),
                 }
@@ -3071,7 +3071,7 @@ impl<'a> LoweringContext<'a> {
             ),
             ExprKind::Field(ref el, ident) => hir::ExprField(
                 P(self.lower_expr(el)),
-                respan(ident.span, self.lower_ident(ident.node)),
+                respan(ident.span, self.lower_ident(ident)),
             ),
             ExprKind::TupField(ref el, ident) => hir::ExprTupField(P(self.lower_expr(el)), ident),
             ExprKind::Index(ref el, ref er) => {
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index c0728cb2b66..2cc6708bc03 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -171,16 +171,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns {
                 if fieldpat.node.is_shorthand {
                     continue;
                 }
-                if let PatKind::Binding(_, _, ident, None) = fieldpat.node.pat.node {
-                    if ident.node == fieldpat.node.name {
+                if let PatKind::Binding(_, _, name, None) = fieldpat.node.pat.node {
+                    if name.node == fieldpat.node.name {
                         let mut err = cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS,
                                      fieldpat.span,
                                      &format!("the `{}:` in this pattern is redundant",
-                                              ident.node));
+                                              name.node));
                         let subspan = cx.tcx.sess.codemap().span_through_char(fieldpat.span, ':');
                         err.span_suggestion_short(subspan,
                                                   "remove this",
-                                                  format!("{}", ident.node));
+                                                  format!("{}", name.node));
                         err.emit();
                     }
                 }
@@ -625,7 +625,7 @@ impl EarlyLintPass for AnonymousParameters {
                 for arg in sig.decl.inputs.iter() {
                     match arg.pat.node {
                         ast::PatKind::Ident(_, ident, None) => {
-                            if ident.node.name == keywords::Invalid.name() {
+                            if ident.name == keywords::Invalid.name() {
                                 cx.span_lint(ANONYMOUS_PARAMETERS,
                                              arg.pat.span,
                                              "use of deprecated anonymous parameter");
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 6f5fcc9e421..9b0e4c64171 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -467,8 +467,8 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
                 mutability: Mutability::Not,
             };
             if let Some(hir::map::NodeBinding(pat)) = tcx.hir.find(var_id) {
-                if let hir::PatKind::Binding(_, _, ref ident, _) = pat.node {
-                    decl.debug_name = ident.node;
+                if let hir::PatKind::Binding(_, _, ref name, _) = pat.node {
+                    decl.debug_name = name.node;
 
                     let bm = *hir.tables.pat_binding_modes()
                                         .get(pat.hir_id)
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 798d6353181..c3f41e8ac48 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -466,7 +466,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                 }
             }
 
-            PatKind::Binding(_, id, ref ident, ref sub) => {
+            PatKind::Binding(_, id, ref name, ref sub) => {
                 let var_ty = self.tables.node_id_to_type(pat.hir_id);
                 let region = match var_ty.sty {
                     ty::TyRef(r, _) => Some(r),
@@ -493,14 +493,14 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                     if let ty::TyRef(_, mt) = ty.sty {
                         ty = mt.ty;
                     } else {
-                        bug!("`ref {}` has wrong type {}", ident.node, ty);
+                        bug!("`ref {}` has wrong type {}", name.node, ty);
                     }
                 }
 
                 PatternKind::Binding {
                     mutability,
                     mode,
-                    name: ident.node,
+                    name: name.node,
                     var: id,
                     ty: var_ty,
                     subpattern: self.lower_opt_pattern(sub),
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 3598fe1d66c..45ecf665ef1 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -34,7 +34,6 @@ use syntax::attr;
 
 use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
 use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind, Variant};
-use syntax::codemap::respan;
 use syntax::ext::base::SyntaxExtension;
 use syntax::ext::base::Determinacy::Undetermined;
 use syntax::ext::hygiene::Mark;
@@ -115,13 +114,13 @@ impl<'a> Resolver<'a> {
 
         let mut module_path: Vec<_> = prefix.segments.iter()
             .chain(path.segments.iter())
-            .map(|seg| respan(seg.span, seg.ident))
+            .map(|seg| seg.ident)
             .collect();
 
         match use_tree.kind {
             ast::UseTreeKind::Simple(rename) => {
                 let mut ident = use_tree.ident();
-                let mut source = module_path.pop().unwrap().node;
+                let mut source = module_path.pop().unwrap();
                 let mut type_ns_only = false;
 
                 if nested {
@@ -130,7 +129,7 @@ impl<'a> Resolver<'a> {
                         type_ns_only = true;
 
                         let last_segment = *module_path.last().unwrap();
-                        if last_segment.node.name == keywords::CrateRoot.name() {
+                        if last_segment.name == keywords::CrateRoot.name() {
                             resolve_error(
                                 self,
                                 use_tree.span,
@@ -142,9 +141,9 @@ impl<'a> Resolver<'a> {
 
                         // Replace `use foo::self;` with `use foo;`
                         let _ = module_path.pop();
-                        source = last_segment.node;
+                        source = last_segment;
                         if rename.is_none() {
-                            ident = last_segment.node;
+                            ident = last_segment;
                         }
                     }
                 } else {
@@ -195,8 +194,8 @@ impl<'a> Resolver<'a> {
             }
             ast::UseTreeKind::Nested(ref items) => {
                 let prefix = ast::Path {
-                    segments: module_path.iter()
-                        .map(|s| ast::PathSegment::from_ident(s.node, s.span))
+                    segments: module_path.into_iter()
+                        .map(|ident| ast::PathSegment::from_ident(ident, ident.span))
                         .collect(),
                     span: path.span,
                 };
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index b6a43949ca3..41abb794f22 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -41,9 +41,9 @@ use rustc::ty;
 use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
 use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
 
-use syntax::codemap::{dummy_spanned, respan, BytePos, CodeMap};
+use syntax::codemap::{BytePos, CodeMap};
 use syntax::ext::hygiene::{Mark, MarkKind, SyntaxContext};
-use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy};
+use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
 use syntax::ext::base::SyntaxExtension;
 use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
 use syntax::ext::base::MacroKind;
@@ -1654,8 +1654,8 @@ impl<'a> Resolver<'a> {
         {
         let namespace = if is_value { ValueNS } else { TypeNS };
         let hir::Path { ref segments, span, ref mut def } = *path;
-        let path: Vec<SpannedIdent> = segments.iter()
-            .map(|seg| respan(span, Ident::with_empty_ctxt(seg.name)))
+        let path: Vec<Ident> = segments.iter()
+            .map(|seg| Ident::new(seg.name, span))
             .collect();
         match self.resolve_path(&path, Some(namespace), true, span) {
             PathResult::Module(module) => *def = module.def().unwrap(),
@@ -2351,7 +2351,7 @@ impl<'a> Resolver<'a> {
         let mut new_id = None;
         if let Some(trait_ref) = opt_trait_ref {
             let path: Vec<_> = trait_ref.path.segments.iter()
-                .map(|seg| respan(seg.span, seg.ident))
+                .map(|seg| seg.ident)
                 .collect();
             let def = self.smart_resolve_path_fragment(
                 trait_ref.ref_id,
@@ -2500,7 +2500,7 @@ impl<'a> Resolver<'a> {
                     _ => false,
                 } {
                     let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode };
-                    binding_map.insert(ident.node, binding_info);
+                    binding_map.insert(ident, binding_info);
                 }
             }
             true
@@ -2640,7 +2640,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn fresh_binding(&mut self,
-                     ident: &SpannedIdent,
+                     ident: Ident,
                      pat_id: NodeId,
                      outer_pat_id: NodeId,
                      pat_src: PatternSource,
@@ -2652,14 +2652,14 @@ impl<'a> Resolver<'a> {
         // because that breaks the assumptions later
         // passes make about or-patterns.)
         let mut def = Def::Local(pat_id);
-        match bindings.get(&ident.node).cloned() {
+        match bindings.get(&ident).cloned() {
             Some(id) if id == outer_pat_id => {
                 // `Variant(a, a)`, error
                 resolve_error(
                     self,
                     ident.span,
                     ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
-                        &ident.node.name.as_str())
+                        &ident.name.as_str())
                 );
             }
             Some(..) if pat_src == PatternSource::FnParam => {
@@ -2668,7 +2668,7 @@ impl<'a> Resolver<'a> {
                     self,
                     ident.span,
                     ResolutionError::IdentifierBoundMoreThanOnceInParameterList(
-                        &ident.node.name.as_str())
+                        &ident.name.as_str())
                 );
             }
             Some(..) if pat_src == PatternSource::Match ||
@@ -2676,7 +2676,7 @@ impl<'a> Resolver<'a> {
                         pat_src == PatternSource::WhileLet => {
                 // `Variant1(a) | Variant2(a)`, ok
                 // Reuse definition from the first `a`.
-                def = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident.node];
+                def = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident];
             }
             Some(..) => {
                 span_bug!(ident.span, "two bindings with the same name from \
@@ -2684,9 +2684,9 @@ impl<'a> Resolver<'a> {
             }
             None => {
                 // A completely fresh binding, add to the lists if it's valid.
-                if ident.node.name != keywords::Invalid.name() {
-                    bindings.insert(ident.node, outer_pat_id);
-                    self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident.node, def);
+                if ident.name != keywords::Invalid.name() {
+                    bindings.insert(ident, outer_pat_id);
+                    self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident, def);
                 }
             }
         }
@@ -2704,10 +2704,10 @@ impl<'a> Resolver<'a> {
         let outer_pat_id = pat.id;
         pat.walk(&mut |pat| {
             match pat.node {
-                PatKind::Ident(bmode, ref ident, ref opt_pat) => {
+                PatKind::Ident(bmode, ident, ref opt_pat) => {
                     // First try to resolve the identifier as some existing
                     // entity, then fall back to a fresh binding.
-                    let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS,
+                    let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS,
                                                                       false, pat.span)
                                       .and_then(LexicalScopeBinding::item);
                     let resolution = binding.map(NameBinding::def).and_then(|def| {
@@ -2719,7 +2719,7 @@ impl<'a> Resolver<'a> {
                             Def::Const(..) if is_syntactic_ambiguity => {
                                 // Disambiguate in favor of a unit struct/variant
                                 // or constant pattern.
-                                self.record_use(ident.node, ValueNS, binding.unwrap(), ident.span);
+                                self.record_use(ident, ValueNS, binding.unwrap(), ident.span);
                                 Some(PathResolution::new(def))
                             }
                             Def::StructCtor(..) | Def::VariantCtor(..) |
@@ -2733,7 +2733,7 @@ impl<'a> Resolver<'a> {
                                     self,
                                     ident.span,
                                     ResolutionError::BindingShadowsSomethingUnacceptable(
-                                        pat_src.descr(), ident.node.name, binding.unwrap())
+                                        pat_src.descr(), ident.name, binding.unwrap())
                                 );
                                 None
                             }
@@ -2786,7 +2786,7 @@ impl<'a> Resolver<'a> {
                           source: PathSource)
                           -> PathResolution {
         let segments = &path.segments.iter()
-            .map(|seg| respan(seg.span, seg.ident))
+            .map(|seg| seg.ident)
             .collect::<Vec<_>>();
         self.smart_resolve_path_fragment(id, qself, segments, path.span, source)
     }
@@ -2794,7 +2794,7 @@ impl<'a> Resolver<'a> {
     fn smart_resolve_path_fragment(&mut self,
                                    id: NodeId,
                                    qself: Option<&QSelf>,
-                                   path: &[SpannedIdent],
+                                   path: &[Ident],
                                    span: Span,
                                    source: PathSource)
                                    -> PathResolution {
@@ -2814,11 +2814,11 @@ impl<'a> Resolver<'a> {
                  format!("not a {}", expected),
                  span)
             } else {
-                let item_str = path[path.len() - 1].node;
+                let item_str = path[path.len() - 1];
                 let item_span = path[path.len() - 1].span;
                 let (mod_prefix, mod_str) = if path.len() == 1 {
                     (format!(""), format!("this scope"))
-                } else if path.len() == 2 && path[0].node.name == keywords::CrateRoot.name() {
+                } else if path.len() == 2 && path[0].name == keywords::CrateRoot.name() {
                     (format!(""), format!("the crate root"))
                 } else {
                     let mod_path = &path[..path.len() - 1];
@@ -2852,10 +2852,10 @@ impl<'a> Resolver<'a> {
 
             // Try to lookup the name in more relaxed fashion for better error reporting.
             let ident = *path.last().unwrap();
-            let candidates = this.lookup_import_candidates(ident.node.name, ns, is_expected);
+            let candidates = this.lookup_import_candidates(ident.name, ns, is_expected);
             if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) {
                 let enum_candidates =
-                    this.lookup_import_candidates(ident.node.name, ns, is_enum_variant);
+                    this.lookup_import_candidates(ident.name, ns, is_enum_variant);
                 let mut enum_candidates = enum_candidates.iter()
                     .map(|suggestion| import_candidate_to_paths(&suggestion)).collect::<Vec<_>>();
                 enum_candidates.sort();
@@ -2873,8 +2873,8 @@ impl<'a> Resolver<'a> {
                 }
             }
             if path.len() == 1 && this.self_type_is_available(span) {
-                if let Some(candidate) = this.lookup_assoc_candidate(ident.node, ns, is_expected) {
-                    let self_is_available = this.self_value_is_available(path[0].node.span, span);
+                if let Some(candidate) = this.lookup_assoc_candidate(ident, ns, is_expected) {
+                    let self_is_available = this.self_value_is_available(path[0].span, span);
                     match candidate {
                         AssocSuggestion::Field => {
                             err.span_suggestion(span, "try",
@@ -2919,7 +2919,7 @@ impl<'a> Resolver<'a> {
                     (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
                         ExprKind::Field(_, ident) => {
                             err.span_label(parent.span, format!("did you mean `{}::{}`?",
-                                                                 path_str, ident.node));
+                                                                 path_str, ident));
                             return (err, candidates);
                         }
                         ExprKind::MethodCall(ref segment, ..) => {
@@ -3028,7 +3028,7 @@ impl<'a> Resolver<'a> {
                 // or `<T>::A::B`. If `B` should be resolved in value namespace then
                 // it needs to be added to the trait map.
                 if ns == ValueNS {
-                    let item_name = path.last().unwrap().node;
+                    let item_name = *path.last().unwrap();
                     let traits = self.get_traits_containing_item(item_name, ns);
                     self.trait_map.insert(id, traits);
                 }
@@ -3095,7 +3095,7 @@ impl<'a> Resolver<'a> {
     fn resolve_qpath_anywhere(&mut self,
                               id: NodeId,
                               qself: Option<&QSelf>,
-                              path: &[SpannedIdent],
+                              path: &[Ident],
                               primary_ns: Namespace,
                               span: Span,
                               defer_to_typeck: bool,
@@ -3115,10 +3115,10 @@ impl<'a> Resolver<'a> {
                 };
             }
         }
-        let is_global = self.global_macros.get(&path[0].node.name).cloned()
+        let is_global = self.global_macros.get(&path[0].name).cloned()
             .map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false);
         if primary_ns != MacroNS && (is_global ||
-                                     self.macro_names.contains(&path[0].node.modern())) {
+                                     self.macro_names.contains(&path[0].modern())) {
             // Return some dummy definition, it's enough for error reporting.
             return Some(
                 PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang))
@@ -3131,7 +3131,7 @@ impl<'a> Resolver<'a> {
     fn resolve_qpath(&mut self,
                      id: NodeId,
                      qself: Option<&QSelf>,
-                     path: &[SpannedIdent],
+                     path: &[Ident],
                      ns: Namespace,
                      span: Span,
                      global_by_default: bool)
@@ -3172,8 +3172,8 @@ impl<'a> Resolver<'a> {
             PathResult::Module(..) | PathResult::Failed(..)
                     if (ns == TypeNS || path.len() > 1) &&
                        self.primitive_type_table.primitive_types
-                           .contains_key(&path[0].node.name) => {
-                let prim = self.primitive_type_table.primitive_types[&path[0].node.name];
+                           .contains_key(&path[0].name) => {
+                let prim = self.primitive_type_table.primitive_types[&path[0].name];
                 PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1)
             }
             PathResult::Module(module) => PathResolution::new(module.def().unwrap()),
@@ -3186,8 +3186,8 @@ impl<'a> Resolver<'a> {
         };
 
         if path.len() > 1 && !global_by_default && result.base_def() != Def::Err &&
-           path[0].node.name != keywords::CrateRoot.name() &&
-           path[0].node.name != keywords::DollarCrate.name() {
+           path[0].name != keywords::CrateRoot.name() &&
+           path[0].name != keywords::DollarCrate.name() {
             let unqualified_result = {
                 match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span) {
                     PathResult::NonModule(path_res) => path_res.base_def(),
@@ -3205,7 +3205,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn resolve_path(&mut self,
-                    path: &[SpannedIdent],
+                    path: &[Ident],
                     opt_ns: Option<Namespace>, // `None` indicates a module path
                     record_used: bool,
                     path_span: Span)
@@ -3217,14 +3217,14 @@ impl<'a> Resolver<'a> {
             debug!("resolve_path ident {} {:?}", i, ident);
             let is_last = i == path.len() - 1;
             let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
-            let name = ident.node.name;
+            let name = ident.name;
 
             if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() {
-                let mut ctxt = ident.node.span.ctxt().modern();
+                let mut ctxt = ident.span.ctxt().modern();
                 module = Some(self.resolve_self(&mut ctxt, self.current_module));
                 continue
             } else if allow_super && ns == TypeNS && name == keywords::Super.name() {
-                let mut ctxt = ident.node.span.ctxt().modern();
+                let mut ctxt = ident.span.ctxt().modern();
                 let self_module = match i {
                     0 => self.resolve_self(&mut ctxt, self.current_module),
                     _ => module.unwrap(),
@@ -3244,16 +3244,16 @@ impl<'a> Resolver<'a> {
             if ns == TypeNS {
                 if (i == 0 && name == keywords::CrateRoot.name()) ||
                    (i == 1 && name == keywords::Crate.name() &&
-                              path[0].node.name == keywords::CrateRoot.name()) {
+                              path[0].name == keywords::CrateRoot.name()) {
                     // `::a::b` or `::crate::a::b`
-                    module = Some(self.resolve_crate_root(ident.node.span.ctxt(), false));
+                    module = Some(self.resolve_crate_root(ident.span.ctxt(), false));
                     continue
                 } else if i == 0 && name == keywords::DollarCrate.name() {
                     // `$crate::a::b`
-                    module = Some(self.resolve_crate_root(ident.node.span.ctxt(), true));
+                    module = Some(self.resolve_crate_root(ident.span.ctxt(), true));
                     continue
-                } else if i == 1 && !token::is_path_segment_keyword(ident.node) {
-                    let prev_name = path[0].node.name;
+                } else if i == 1 && !token::is_path_segment_keyword(ident) {
+                    let prev_name = path[0].name;
                     if prev_name == keywords::Extern.name() ||
                        prev_name == keywords::CrateRoot.name() &&
                        self.session.features_untracked().extern_absolute_paths {
@@ -3276,13 +3276,13 @@ impl<'a> Resolver<'a> {
                name == keywords::Super.name() && i != 0 ||
                name == keywords::Extern.name() && i != 0 ||
                name == keywords::Crate.name() && i != 1 &&
-                    path[0].node.name != keywords::CrateRoot.name() {
+                    path[0].name != keywords::CrateRoot.name() {
                 let name_str = if name == keywords::CrateRoot.name() {
                     format!("crate root")
                 } else {
                     format!("`{}`", name)
                 };
-                let msg = if i == 1 && path[0].node.name == keywords::CrateRoot.name() {
+                let msg = if i == 1 && path[0].name == keywords::CrateRoot.name() {
                     format!("global paths cannot start with {}", name_str)
                 } else if i == 0 && name == keywords::Crate.name() {
                     format!("{} can only be used in absolute paths", name_str)
@@ -3293,12 +3293,12 @@ impl<'a> Resolver<'a> {
             }
 
             let binding = if let Some(module) = module {
-                self.resolve_ident_in_module(module, ident.node, ns, false, record_used, path_span)
+                self.resolve_ident_in_module(module, ident, ns, false, record_used, path_span)
             } else if opt_ns == Some(MacroNS) {
-                self.resolve_lexical_macro_path_segment(ident.node, ns, record_used, path_span)
+                self.resolve_lexical_macro_path_segment(ident, ns, record_used, path_span)
                     .map(MacroBinding::binding)
             } else {
-                match self.resolve_ident_in_lexical_scope(ident.node, ns, record_used, path_span) {
+                match self.resolve_ident_in_lexical_scope(ident, ns, record_used, path_span) {
                     Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
                     Some(LexicalScopeBinding::Def(def))
                             if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => {
@@ -3324,7 +3324,7 @@ impl<'a> Resolver<'a> {
                         ));
                     } else {
                         return PathResult::Failed(ident.span,
-                                                  format!("Not a module `{}`", ident.node),
+                                                  format!("Not a module `{}`", ident),
                                                   is_last);
                     }
                 }
@@ -3345,12 +3345,12 @@ impl<'a> Resolver<'a> {
                         if let Some(candidate) = candidates.get(0) {
                             format!("Did you mean `{}`?", candidate.path)
                         } else {
-                            format!("Maybe a missing `extern crate {};`?", ident.node)
+                            format!("Maybe a missing `extern crate {};`?", ident)
                         }
                     } else if i == 0 {
-                        format!("Use of undeclared type or module `{}`", ident.node)
+                        format!("Use of undeclared type or module `{}`", ident)
                     } else {
-                        format!("Could not find `{}` in `{}`", ident.node, path[i - 1].node)
+                        format!("Could not find `{}` in `{}`", ident, path[i - 1])
                     };
                     return PathResult::Failed(ident.span, msg, is_last);
                 }
@@ -3516,7 +3516,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn lookup_typo_candidate<FilterFn>(&mut self,
-                                       path: &[SpannedIdent],
+                                       path: &[Ident],
                                        ns: Namespace,
                                        filter_fn: FilterFn,
                                        span: Span)
@@ -3577,7 +3577,7 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        let name = path[path.len() - 1].node.name;
+        let name = path[path.len() - 1].name;
         // Make sure error reporting is deterministic.
         names.sort_by_key(|name| name.as_str());
         match find_best_match_for_name(names.iter(), &name.as_str(), None) {
@@ -3739,12 +3739,12 @@ impl<'a> Resolver<'a> {
 
     fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
         match expr.node {
-            ExprKind::Field(_, name) => {
+            ExprKind::Field(_, ident) => {
                 // FIXME(#6890): Even though you can't treat a method like a
                 // field, we need to add any trait methods we find that match
                 // the field name so that we can do some nice error reporting
                 // later on in typeck.
-                let traits = self.get_traits_containing_item(name.node, ValueNS);
+                let traits = self.get_traits_containing_item(ident, ValueNS);
                 self.trait_map.insert(expr.id, traits);
             }
             ExprKind::MethodCall(ref segment, ..) => {
@@ -4244,30 +4244,30 @@ impl<'a> Resolver<'a> {
     }
 }
 
-fn is_self_type(path: &[SpannedIdent], namespace: Namespace) -> bool {
-    namespace == TypeNS && path.len() == 1 && path[0].node.name == keywords::SelfType.name()
+fn is_self_type(path: &[Ident], namespace: Namespace) -> bool {
+    namespace == TypeNS && path.len() == 1 && path[0].name == keywords::SelfType.name()
 }
 
-fn is_self_value(path: &[SpannedIdent], namespace: Namespace) -> bool {
-    namespace == ValueNS && path.len() == 1 && path[0].node.name == keywords::SelfValue.name()
+fn is_self_value(path: &[Ident], namespace: Namespace) -> bool {
+    namespace == ValueNS && path.len() == 1 && path[0].name == keywords::SelfValue.name()
 }
 
-fn names_to_string(idents: &[SpannedIdent]) -> String {
+fn names_to_string(idents: &[Ident]) -> String {
     let mut result = String::new();
     for (i, ident) in idents.iter()
-                            .filter(|i| i.node.name != keywords::CrateRoot.name())
+                            .filter(|ident| ident.name != keywords::CrateRoot.name())
                             .enumerate() {
         if i > 0 {
             result.push_str("::");
         }
-        result.push_str(&ident.node.name.as_str());
+        result.push_str(&ident.name.as_str());
     }
     result
 }
 
 fn path_names_to_string(path: &Path) -> String {
     names_to_string(&path.segments.iter()
-                        .map(|seg| respan(seg.span, seg.ident))
+                        .map(|seg| seg.ident)
                         .collect::<Vec<_>>())
 }
 
@@ -4356,7 +4356,6 @@ fn module_to_string(module: Module) -> Option<String> {
     }
     Some(names_to_string(&names.into_iter()
                         .rev()
-                        .map(|n| dummy_spanned(n))
                         .collect::<Vec<_>>()))
 }
 
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index c65ee11e427..3b3bdfdba9c 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -20,7 +20,6 @@ use rustc::hir::map::{self, DefCollector};
 use rustc::{ty, lint};
 use syntax::ast::{self, Name, Ident};
 use syntax::attr::{self, HasAttrs};
-use syntax::codemap::respan;
 use syntax::errors::DiagnosticBuilder;
 use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator};
 use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
@@ -413,7 +412,7 @@ impl<'a> Resolver<'a> {
                                   kind: MacroKind, force: bool)
                                   -> Result<Def, Determinacy> {
         let ast::Path { ref segments, span } = *path;
-        let path: Vec<_> = segments.iter().map(|seg| respan(seg.span, seg.ident)).collect();
+        let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
         let invocation = self.invocations[&scope];
         let module = invocation.module.get();
         self.current_module = if module.is_trait() { module.parent.unwrap() } else { module };
@@ -447,19 +446,16 @@ impl<'a> Resolver<'a> {
                     Err(Determinacy::Determined)
                 },
             };
-            let path = path.iter().map(|p| p.node).collect::<Vec<_>>();
             self.current_module.nearest_item_scope().macro_resolutions.borrow_mut()
                 .push((path.into_boxed_slice(), span));
             return def;
         }
 
-        let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope,
-                                                          path[0].node,
-                                                          false);
+        let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, path[0], false);
         let result = if let Some(MacroBinding::Legacy(binding)) = legacy_resolution {
             Ok(Def::Macro(binding.def_id, MacroKind::Bang))
         } else {
-            match self.resolve_lexical_macro_path_segment(path[0].node, MacroNS, false, span) {
+            match self.resolve_lexical_macro_path_segment(path[0], MacroNS, false, span) {
                 Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()),
                 Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined),
                 Err(_) => {
@@ -470,7 +466,7 @@ impl<'a> Resolver<'a> {
         };
 
         self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut()
-            .push((scope, path[0].node, span, kind));
+            .push((scope, path[0], span, kind));
 
         result
     }
@@ -608,7 +604,6 @@ impl<'a> Resolver<'a> {
     pub fn finalize_current_module_macro_resolutions(&mut self) {
         let module = self.current_module;
         for &(ref path, span) in module.macro_resolutions.borrow().iter() {
-            let path = path.iter().map(|p| respan(span, *p)).collect::<Vec<_>>();
             match self.resolve_path(&path, Some(MacroNS), true, span) {
                 PathResult::NonModule(_) => {},
                 PathResult::Failed(span, msg, _) => {
@@ -684,8 +679,8 @@ impl<'a> Resolver<'a> {
                     false
                 }
             };
-            let ident = Ident::from_str(name);
-            self.lookup_typo_candidate(&vec![respan(span, ident)], MacroNS, is_macro, span)
+            let ident = Ident::new(Symbol::intern(name), span);
+            self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro, span)
         });
 
         if let Some(suggestion) = suggestion {
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 90a90d73153..87738f7b79b 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -24,7 +24,7 @@ use rustc::hir::def::*;
 use rustc::session::DiagnosticMessageId;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 
-use syntax::ast::{Ident, Name, SpannedIdent, NodeId};
+use syntax::ast::{Ident, Name, NodeId};
 use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
 use syntax::ext::hygiene::Mark;
 use syntax::parse::token;
@@ -58,7 +58,7 @@ pub enum ImportDirectiveSubclass<'a> {
 pub struct ImportDirective<'a> {
     pub id: NodeId,
     pub parent: Module<'a>,
-    pub module_path: Vec<SpannedIdent>,
+    pub module_path: Vec<Ident>,
     pub imported_module: Cell<Option<Module<'a>>>, // the resolution of `module_path`
     pub subclass: ImportDirectiveSubclass<'a>,
     pub span: Span,
@@ -257,7 +257,7 @@ impl<'a> Resolver<'a> {
 
     // Add an import directive to the current module.
     pub fn add_import_directive(&mut self,
-                                module_path: Vec<SpannedIdent>,
+                                module_path: Vec<Ident>,
                                 subclass: ImportDirectiveSubclass<'a>,
                                 span: Span,
                                 id: NodeId,
@@ -606,9 +606,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
 
         // FIXME: Last path segment is treated specially in import resolution, so extern crate
         // mode for absolute paths needs some special support for single-segment imports.
-        if module_path.len() == 1 && (module_path[0].node.name == keywords::CrateRoot.name() ||
-                                      module_path[0].node.name == keywords::Extern.name()) {
-            let is_extern = module_path[0].node.name == keywords::Extern.name() ||
+        if module_path.len() == 1 && (module_path[0].name == keywords::CrateRoot.name() ||
+                                      module_path[0].name == keywords::Extern.name()) {
+            let is_extern = module_path[0].name == keywords::Extern.name() ||
                             self.session.features_untracked().extern_absolute_paths;
             match directive.subclass {
                 GlobImport { .. } if is_extern => {
@@ -617,7 +617,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                 }
                 SingleImport { source, target, .. } => {
                     let crate_root = if source.name == keywords::Crate.name() &&
-                                        module_path[0].node.name != keywords::Extern.name() {
+                                        module_path[0].name != keywords::Extern.name() {
                         if target.name == keywords::Crate.name() {
                             return Some((directive.span,
                                          "crate root imports need to be explicitly named: \
@@ -669,9 +669,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                 let (mut self_path, mut self_result) = (module_path.clone(), None);
                 let is_special = |ident| token::is_path_segment_keyword(ident) &&
                                          ident.name != keywords::CrateRoot.name();
-                if !self_path.is_empty() && !is_special(self_path[0].node) &&
-                   !(self_path.len() > 1 && is_special(self_path[1].node)) {
-                    self_path[0].node.name = keywords::SelfValue.name();
+                if !self_path.is_empty() && !is_special(self_path[0]) &&
+                   !(self_path.len() > 1 && is_special(self_path[1])) {
+                    self_path[0].name = keywords::SelfValue.name();
                     self_result = Some(self.resolve_path(&self_path, None, false, span));
                 }
                 return if let Some(PathResult::Module(..)) = self_result {
@@ -957,7 +957,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                             let resolutions = imported_module.parent.expect("parent should exist")
                                 .resolutions.borrow();
                             let enum_path_segment_index = directive.module_path.len() - 1;
-                            let enum_ident = directive.module_path[enum_path_segment_index].node;
+                            let enum_ident = directive.module_path[enum_path_segment_index];
 
                             let enum_resolution = resolutions.get(&(enum_ident, TypeNS))
                                 .expect("resolution should exist");
@@ -1011,12 +1011,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
     }
 }
 
-fn import_path_to_string(names: &[SpannedIdent],
+fn import_path_to_string(names: &[Ident],
                          subclass: &ImportDirectiveSubclass,
                          span: Span) -> String {
     let pos = names.iter()
-        .position(|p| span == p.span && p.node.name != keywords::CrateRoot.name());
-    let global = !names.is_empty() && names[0].node.name == keywords::CrateRoot.name();
+        .position(|p| span == p.span && p.name != keywords::CrateRoot.name());
+    let global = !names.is_empty() && names[0].name == keywords::CrateRoot.name();
     if let Some(pos) = pos {
         let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] };
         names_to_string(names)
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index fb4cb2afe5a..74c2597fa99 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -554,7 +554,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 };
                 match self.tables.expr_ty_adjusted(&hir_node).sty {
                     ty::TyAdt(def, _) if !def.is_enum() => {
-                        let f = def.non_enum_variant().field_named(ident.node.name);
+                        let f = def.non_enum_variant().field_named(ident.name);
                         let sub_span = self.span_utils.span_for_last_ident(expr.span);
                         filter!(self.span_utils, sub_span, expr.span, None);
                         let span = self.span_from_span(sub_span.unwrap());
@@ -817,7 +817,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         field_ref: &ast::Field,
         variant: &ty::VariantDef,
     ) -> Option<Ref> {
-        let f = variant.find_field_named(field_ref.ident.node.name)?;
+        let f = variant.find_field_named(field_ref.ident.name)?;
         // We don't really need a sub-span here, but no harm done
         let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span);
         filter!(self.span_utils, sub_span, field_ref.ident.span, None);
@@ -982,12 +982,12 @@ impl<'l, 'a: 'l> Visitor<'a> for PathCollector<'l> {
             PatKind::TupleStruct(ref path, ..) | PatKind::Path(_, ref path) => {
                 self.collected_paths.push((p.id, path));
             }
-            PatKind::Ident(bm, ref path1, _) => {
+            PatKind::Ident(bm, ident, _) => {
                 debug!(
                     "PathCollector, visit ident in pat {}: {:?} {:?}",
-                    path1.node,
+                    ident,
                     p.span,
-                    path1.span
+                    ident.span
                 );
                 let immut = match bm {
                     // Even if the ref is mut, you can't change the ref, only
@@ -997,7 +997,7 @@ impl<'l, 'a: 'l> Visitor<'a> for PathCollector<'l> {
                     ast::BindingMode::ByValue(mt) => mt,
                 };
                 self.collected_idents
-                    .push((p.id, path1.node, path1.span, immut));
+                    .push((p.id, ident, ident.span, immut));
             }
             _ => {}
         }
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index fd4d3e76386..23845c94aa4 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -671,7 +671,7 @@ impl Sig for ast::StructField {
     fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) -> Result {
         let mut text = String::new();
         let mut defs = None;
-        if let Some(ref ident) = self.ident {
+        if let Some(ident) = self.ident {
             text.push_str(&ident.to_string());
             defs = Some(SigElement {
                 id: id_from_node_id(self.id, scx),
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index a3839a861c6..652aaa795c3 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -541,7 +541,7 @@ impl Pat {
         let node = match &self.node {
             PatKind::Wild => TyKind::Infer,
             PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None) =>
-                TyKind::Path(None, Path::from_ident(ident.span, ident.node)),
+                TyKind::Path(None, Path::from_ident(ident.span, *ident)),
             PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
             PatKind::Mac(mac) => TyKind::Mac(mac.clone()),
             PatKind::Ref(pat, mutbl) =>
@@ -638,7 +638,7 @@ pub enum PatKind {
     /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third
     /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens
     /// during name resolution.
-    Ident(BindingMode, SpannedIdent, Option<P<Pat>>),
+    Ident(BindingMode, Ident, Option<P<Pat>>),
 
     /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`.
     /// The `bool` is `true` in the presence of a `..`.
@@ -910,15 +910,13 @@ pub struct Arm {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct Field {
-    pub ident: SpannedIdent,
+    pub ident: Ident,
     pub expr: P<Expr>,
     pub span: Span,
     pub is_shorthand: bool,
     pub attrs: ThinVec<Attribute>,
 }
 
-pub type SpannedIdent = Spanned<Ident>;
-
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum BlockCheckMode {
     Default,
@@ -1144,7 +1142,7 @@ pub enum ExprKind {
     /// For example, `a += 1`.
     AssignOp(BinOp, P<Expr>, P<Expr>),
     /// Access of a named struct field (`obj.foo`)
-    Field(P<Expr>, SpannedIdent),
+    Field(P<Expr>, Ident),
     /// Access of an unnamed field of a struct or tuple-struct
     ///
     /// For example, `foo.0`.
@@ -1689,7 +1687,7 @@ pub type ExplicitSelf = Spanned<SelfKind>;
 impl Arg {
     pub fn to_self(&self) -> Option<ExplicitSelf> {
         if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.node {
-            if ident.node.name == keywords::SelfValue.name() {
+            if ident.name == keywords::SelfValue.name() {
                 return match self.ty.node {
                     TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
                     TyKind::Rptr(lt, MutTy{ref ty, mutbl}) if ty.node == TyKind::ImplicitSelf => {
@@ -1705,13 +1703,13 @@ impl Arg {
 
     pub fn is_self(&self) -> bool {
         if let PatKind::Ident(_, ident, _) = self.pat.node {
-            ident.node.name == keywords::SelfValue.name()
+            ident.name == keywords::SelfValue.name()
         } else {
             false
         }
     }
 
-    pub fn from_self(eself: ExplicitSelf, eself_ident: SpannedIdent) -> Arg {
+    pub fn from_self(eself: ExplicitSelf, eself_ident: Ident) -> Arg {
         let span = eself.span.to(eself_ident.span);
         let infer_ty = P(Ty {
             id: DUMMY_NODE_ID,
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 739679b71d5..541517b2bcb 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -1117,7 +1117,7 @@ impl MetaItem {
         let (span, name) = match tokens.next() {
             Some(TokenTree::Token(span, Token::Ident(ident, _))) => (span, ident.name),
             Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => match nt.0 {
-                token::Nonterminal::NtIdent(ident, _) => (ident.span, ident.node.name),
+                token::Nonterminal::NtIdent(ident, _) => (ident.span, ident.name),
                 token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()),
                 _ => return None,
             },
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 1e264369f91..75b1366d3cd 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -251,7 +251,7 @@ impl<F> TTMacroExpander for F
                 if let tokenstream::TokenTree::Token(_, token::Interpolated(ref nt)) = tt {
                     if let token::NtIdent(ident, is_raw) = nt.0 {
                         return tokenstream::TokenTree::Token(ident.span,
-                                                             token::Ident(ident.node, is_raw));
+                                                             token::Ident(ident, is_raw));
                     }
                 }
                 fold::noop_fold_tt(tt, self)
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 8dabc03c2f9..fc3000ea0b5 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -38,11 +38,11 @@ pub trait AstBuilder {
 
     fn qpath(&self, self_type: P<ast::Ty>,
              trait_path: ast::Path,
-             ident: ast::SpannedIdent)
+             ident: ast::Ident)
              -> (ast::QSelf, ast::Path);
     fn qpath_all(&self, self_type: P<ast::Ty>,
                 trait_path: ast::Path,
-                ident: ast::SpannedIdent,
+                ident: ast::Ident,
                 lifetimes: Vec<ast::Lifetime>,
                 types: Vec<P<ast::Ty>>,
                 bindings: Vec<ast::TypeBinding>)
@@ -344,7 +344,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     fn qpath(&self,
              self_type: P<ast::Ty>,
              trait_path: ast::Path,
-             ident: ast::SpannedIdent)
+             ident: ast::Ident)
              -> (ast::QSelf, ast::Path) {
         self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![])
     }
@@ -355,7 +355,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     fn qpath_all(&self,
                  self_type: P<ast::Ty>,
                  trait_path: ast::Path,
-                 ident: ast::SpannedIdent,
+                 ident: ast::Ident,
                  lifetimes: Vec<ast::Lifetime>,
                  types: Vec<P<ast::Ty>>,
                  bindings: Vec<ast::TypeBinding>)
@@ -366,11 +366,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         } else {
             None
         };
-        path.segments.push(ast::PathSegment {
-            ident: ident.node,
-            span: ident.span,
-            parameters,
-        });
+        path.segments.push(ast::PathSegment { ident, span: ident.span, parameters });
 
         (ast::QSelf {
             ty: self_type,
@@ -636,8 +632,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
 
     fn expr_field_access(&self, sp: Span, expr: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr> {
-        let id = Spanned { node: ident, span: sp };
-        self.expr(sp, ast::ExprKind::Field(expr, id))
+        self.expr(sp, ast::ExprKind::Field(expr, ident.with_span_pos(sp)))
     }
     fn expr_tup_field_access(&self, sp: Span, expr: P<ast::Expr>, idx: usize) -> P<ast::Expr> {
         let id = Spanned { node: idx, span: sp };
@@ -672,9 +667,9 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> {
         self.expr(b.span, ast::ExprKind::Block(b))
     }
-    fn field_imm(&self, span: Span, name: Ident, e: P<ast::Expr>) -> ast::Field {
+    fn field_imm(&self, span: Span, ident: Ident, e: P<ast::Expr>) -> ast::Field {
         ast::Field {
-            ident: respan(span, name),
+            ident: ident.with_span_pos(span),
             expr: e,
             span,
             is_shorthand: false,
@@ -835,7 +830,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                               span: Span,
                               ident: ast::Ident,
                               bm: ast::BindingMode) -> P<ast::Pat> {
-        let pat = PatKind::Ident(bm, Spanned{span: span, node: ident}, None);
+        let pat = PatKind::Ident(bm, ident.with_span_pos(span), None);
         self.pat(span, pat)
     }
     fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat> {
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index b412c2fbc7f..10dc17beb96 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -75,7 +75,7 @@ pub mod rt {
 
     impl ToTokens for ast::Ident {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(DUMMY_SP, Token::from_ast_ident(*self))]
+            vec![TokenTree::Token(self.span, Token::from_ast_ident(*self))]
         }
     }
 
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 8cb331c65da..fdff17b13ed 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -86,7 +86,6 @@ use self::TokenTreeOrTokenTreeVec::*;
 
 use ast::Ident;
 use syntax_pos::{self, BytePos, Span};
-use codemap::respan;
 use errors::FatalError;
 use ext::tt::quoted::{self, TokenTree};
 use parse::{Directory, ParseSess};
@@ -824,9 +823,10 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
         "expr" => token::NtExpr(panictry!(p.parse_expr())),
         "ty" => token::NtTy(panictry!(p.parse_ty())),
         // this could be handled like a token, since it is one
-        "ident" => if let Some((ident, is_raw)) = get_macro_ident(&p.token) {
+        "ident" => if let Some((ident, is_raw))) = get_macro_ident(&p.token) {
+            let span = p.span;
             p.bump();
-            token::NtIdent(respan(p.prev_span, ident), is_raw)
+            token::NtIdent(Ident::new(ident.name, span), is_raw)
         } else {
             let token_str = pprust::token_to_string(&p.token);
             p.fatal(&format!("expected ident, found {}", &token_str)).emit();
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 2c757a0a887..9ffa91c431c 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -439,8 +439,8 @@ pub fn noop_fold_variant<T: Folder>(v: Variant, fld: &mut T) -> Variant {
     }
 }
 
-pub fn noop_fold_ident<T: Folder>(i: Ident, _: &mut T) -> Ident {
-    i
+pub fn noop_fold_ident<T: Folder>(ident: Ident, fld: &mut T) -> Ident {
+    Ident::new(ident.name, fld.new_span(ident.span))
 }
 
 pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize {
@@ -634,8 +634,7 @@ pub fn noop_fold_interpolated<T: Folder>(nt: token::Nonterminal, fld: &mut T)
         token::NtPat(pat) => token::NtPat(fld.fold_pat(pat)),
         token::NtExpr(expr) => token::NtExpr(fld.fold_expr(expr)),
         token::NtTy(ty) => token::NtTy(fld.fold_ty(ty)),
-        token::NtIdent(id, is_raw) =>
-            token::NtIdent(Spanned::<Ident>{node: fld.fold_ident(id.node), ..id}, is_raw),
+        token::NtIdent(id, is_raw) => token::NtIdent(fld.fold_ident(id), is_raw),
         token::NtMeta(meta) => token::NtMeta(fld.fold_meta_item(meta)),
         token::NtPath(path) => token::NtPath(fld.fold_path(path)),
         token::NtTT(tt) => token::NtTT(fld.fold_tt(tt)),
@@ -859,7 +858,7 @@ pub fn noop_fold_struct_field<T: Folder>(f: StructField, fld: &mut T) -> StructF
 
 pub fn noop_fold_field<T: Folder>(f: Field, folder: &mut T) -> Field {
     Field {
-        ident: respan(f.ident.span, folder.fold_ident(f.ident.node)),
+        ident: folder.fold_ident(f.ident),
         expr: folder.fold_expr(f.expr),
         span: folder.new_span(f.span),
         is_shorthand: f.is_shorthand,
@@ -1119,11 +1118,10 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
         id: folder.new_id(id),
         node: match node {
             PatKind::Wild => PatKind::Wild,
-            PatKind::Ident(binding_mode, pth1, sub) => {
+            PatKind::Ident(binding_mode, ident, sub) => {
                 PatKind::Ident(binding_mode,
-                        Spanned{span: folder.new_span(pth1.span),
-                                node: folder.fold_ident(pth1.node)},
-                        sub.map(|x| folder.fold_pat(x)))
+                               folder.fold_ident(ident),
+                               sub.map(|x| folder.fold_pat(x)))
             }
             PatKind::Lit(e) => PatKind::Lit(folder.fold_expr(e)),
             PatKind::TupleStruct(pth, pats, ddpos) => {
@@ -1272,14 +1270,12 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
                             folder.fold_expr(er))
             }
             ExprKind::Field(el, ident) => {
-                ExprKind::Field(folder.fold_expr(el),
-                          respan(folder.new_span(ident.span),
-                                 folder.fold_ident(ident.node)))
+                ExprKind::Field(folder.fold_expr(el), folder.fold_ident(ident))
             }
-            ExprKind::TupField(el, ident) => {
+            ExprKind::TupField(el, index) => {
                 ExprKind::TupField(folder.fold_expr(el),
-                             respan(folder.new_span(ident.span),
-                                    folder.fold_usize(ident.node)))
+                             respan(folder.new_span(index.span),
+                                    folder.fold_usize(index.node)))
             }
             ExprKind::Index(el, er) => {
                 ExprKind::Index(folder.fold_expr(el), folder.fold_expr(er))
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 81f8428c2c7..0c8ffa2ebde 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -512,13 +512,10 @@ impl From<P<Expr>> for LhsExpr {
 
 /// Create a placeholder argument.
 fn dummy_arg(span: Span) -> Arg {
-    let spanned = Spanned {
-        span,
-        node: keywords::Invalid.ident()
-    };
+    let ident = Ident::new(keywords::Invalid.name(), span);
     let pat = P(Pat {
         id: ast::DUMMY_NODE_ID,
-        node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), spanned, None),
+        node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None),
         span,
     });
     let ty = Ty {
@@ -778,7 +775,7 @@ impl<'a> Parser<'a> {
 
     fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> {
         match self.token {
-            token::Ident(i, _) => {
+            token::Ident(ident, _) => {
                 if self.token.is_reserved_ident() {
                     let mut err = self.expected_ident_found();
                     if recover {
@@ -787,8 +784,9 @@ impl<'a> Parser<'a> {
                         return Err(err);
                     }
                 }
+                let span = self.span;
                 self.bump();
-                Ok(i)
+                Ok(Ident::new(ident.name, span))
             }
             _ => {
                 Err(if self.prev_token_kind == PrevTokenKind::DocComment {
@@ -1321,7 +1319,7 @@ impl<'a> Parser<'a> {
 
     fn eat_label(&mut self) -> Option<Label> {
         let ident = match self.token {
-            token::Lifetime(ref ident) => *ident,
+            token::Lifetime(ident) => ident,
             token::Interpolated(ref nt) => match nt.0 {
                 token::NtLifetime(lifetime) => lifetime.ident,
                 _ => return None,
@@ -1784,13 +1782,11 @@ impl<'a> Parser<'a> {
             pat
         } else {
             debug!("parse_arg_general ident_to_pat");
-            let sp = self.prev_span;
-            let spanned = Spanned { span: sp, node: keywords::Invalid.ident() };
+            let ident = Ident::new(keywords::Invalid.name(), self.prev_span);
             P(Pat {
                 id: ast::DUMMY_NODE_ID,
-                node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable),
-                                     spanned, None),
-                span: sp
+                node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None),
+                span: ident.span,
             })
         };
 
@@ -1899,13 +1895,14 @@ impl<'a> Parser<'a> {
 
     pub fn parse_path_segment_ident(&mut self) -> PResult<'a, ast::Ident> {
         match self.token {
-            token::Ident(sid, _) if self.token.is_path_segment_keyword() => {
+            token::Ident(ident, _) if self.token.is_path_segment_keyword() => {
+                let span = self.span;
                 self.bump();
-                Ok(sid)
+                Ok(Ident::new(ident.name, span))
             }
             _ => self.parse_ident(),
-         }
-     }
+        }
+    }
 
     /// Parses qualified path.
     /// Assumes that the leading `<` has been parsed already.
@@ -2003,7 +2000,6 @@ impl<'a> Parser<'a> {
 
     fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool)
                           -> PResult<'a, PathSegment> {
-        let ident_span = self.span;
         let ident = self.parse_path_segment_ident()?;
 
         let is_args_start = |token: &token::Token| match *token {
@@ -2051,10 +2047,10 @@ impl<'a> Parser<'a> {
                 ParenthesizedParameterData { inputs, output, span }.into()
             };
 
-            PathSegment { ident, span: ident_span, parameters }
+            PathSegment { ident, span: ident.span, parameters }
         } else {
             // Generic arguments are not found.
-            PathSegment::from_ident(ident, ident_span)
+            PathSegment::from_ident(ident, ident.span)
         })
     }
 
@@ -2085,7 +2081,7 @@ impl<'a> Parser<'a> {
     pub fn parse_field_name(&mut self) -> PResult<'a, Ident> {
         if let token::Literal(token::Integer(name), None) = self.token {
             self.bump();
-            Ok(Ident::with_empty_ctxt(name))
+            Ok(Ident::new(name, self.prev_span))
         } else {
             self.parse_ident_common(false)
         }
@@ -2095,24 +2091,22 @@ impl<'a> Parser<'a> {
     pub fn parse_field(&mut self) -> PResult<'a, Field> {
         let attrs = self.parse_outer_attributes()?;
         let lo = self.span;
-        let hi;
 
         // Check if a colon exists one ahead. This means we're parsing a fieldname.
         let (fieldname, expr, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
             let fieldname = self.parse_field_name()?;
-            hi = self.prev_span;
-            self.bump();
+            self.bump(); // `:`
             (fieldname, self.parse_expr()?, false)
         } else {
             let fieldname = self.parse_ident_common(false)?;
-            hi = self.prev_span;
 
             // Mimic `x: x` for the `x` field shorthand.
-            let path = ast::Path::from_ident(lo.to(hi), fieldname);
-            (fieldname, self.mk_expr(lo.to(hi), ExprKind::Path(None, path), ThinVec::new()), true)
+            let path = ast::Path::from_ident(fieldname.span, fieldname);
+            let expr = self.mk_expr(fieldname.span, ExprKind::Path(None, path), ThinVec::new());
+            (fieldname, expr, true)
         };
         Ok(ast::Field {
-            ident: respan(lo.to(hi), fieldname),
+            ident: fieldname,
             span: lo.to(expr.span),
             expr,
             is_shorthand,
@@ -2592,8 +2586,7 @@ impl<'a> Parser<'a> {
                 }
 
                 let span = lo.to(self.prev_span);
-                let ident = respan(segment.span, segment.ident);
-                self.mk_expr(span, ExprKind::Field(self_arg, ident), ThinVec::new())
+                self.mk_expr(span, ExprKind::Field(self_arg, segment.ident), ThinVec::new())
             }
         })
     }
@@ -2736,7 +2729,7 @@ impl<'a> Parser<'a> {
             }
             _ => return,
         };
-        self.token = token::Ident(ident.node, is_raw);
+        self.token = token::Ident(ident, is_raw);
         self.span = ident.span;
     }
 
@@ -3672,10 +3665,9 @@ impl<'a> Parser<'a> {
                     (false, true) => BindingMode::ByValue(Mutability::Mutable),
                     (false, false) => BindingMode::ByValue(Mutability::Immutable),
                 };
-                let fieldpath = codemap::Spanned{span:self.prev_span, node:fieldname};
                 let fieldpat = P(Pat {
                     id: ast::DUMMY_NODE_ID,
-                    node: PatKind::Ident(bind_type, fieldpath, None),
+                    node: PatKind::Ident(bind_type, fieldname, None),
                     span: boxed_span.to(hi),
                 });
 
@@ -3966,9 +3958,7 @@ impl<'a> Parser<'a> {
     fn parse_pat_ident(&mut self,
                        binding_mode: ast::BindingMode)
                        -> PResult<'a, PatKind> {
-        let ident_span = self.span;
         let ident = self.parse_ident()?;
-        let name = codemap::Spanned{span: ident_span, node: ident};
         let sub = if self.eat(&token::At) {
             Some(self.parse_pat()?)
         } else {
@@ -3987,7 +3977,7 @@ impl<'a> Parser<'a> {
                 "expected identifier, found enum pattern"))
         }
 
-        Ok(PatKind::Ident(binding_mode, name, sub))
+        Ok(PatKind::Ident(binding_mode, ident, sub))
     }
 
     /// Parse a local variable declaration
@@ -5051,9 +5041,8 @@ impl<'a> Parser<'a> {
     fn parse_self_arg(&mut self) -> PResult<'a, Option<Arg>> {
         let expect_ident = |this: &mut Self| match this.token {
             // Preserve hygienic context.
-            token::Ident(ident, _) => {
-                let sp = this.span; this.bump(); codemap::respan(sp, ident)
-            }
+            token::Ident(ident, _) =>
+                { let span = this.span; this.bump(); Ident::new(ident.name, span) }
             _ => unreachable!()
         };
         let isolated_self = |this: &mut Self, n| {
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 5fe2b081566..003b0ac356d 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -321,7 +321,7 @@ impl Token {
         match *self {
             Ident(ident, is_raw) => Some((ident, is_raw)),
             Interpolated(ref nt) => match nt.0 {
-                NtIdent(ident, is_raw) => Some((ident.node, is_raw)),
+                NtIdent(ident, is_raw) => Some((ident, is_raw)),
                 _ => None,
             },
             _ => None,
@@ -539,7 +539,7 @@ impl Token {
                 tokens = prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span);
             }
             Nonterminal::NtIdent(ident, is_raw) => {
-                let token = Token::Ident(ident.node, is_raw);
+                let token = Token::Ident(ident, is_raw);
                 tokens = Some(TokenTree::Token(ident.span, token).into());
             }
             Nonterminal::NtLifetime(lifetime) => {
@@ -571,7 +571,7 @@ pub enum Nonterminal {
     NtPat(P<ast::Pat>),
     NtExpr(P<ast::Expr>),
     NtTy(P<ast::Ty>),
-    NtIdent(ast::SpannedIdent, /* is_raw */ bool),
+    NtIdent(ast::Ident, /* is_raw */ bool),
     /// Stuff inside brackets for attributes
     NtMeta(ast::MetaItem),
     NtPath(ast::Path),
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index b7026529a5e..9dad422a728 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -262,26 +262,26 @@ pub fn token_to_string(tok: &Token) -> String {
         token::Shebang(s)           => format!("/* shebang: {}*/", s),
 
         token::Interpolated(ref nt) => match nt.0 {
-            token::NtExpr(ref e)         => expr_to_string(e),
-            token::NtMeta(ref e)         => meta_item_to_string(e),
-            token::NtTy(ref e)           => ty_to_string(e),
-            token::NtPath(ref e)         => path_to_string(e),
-            token::NtItem(ref e)         => item_to_string(e),
-            token::NtBlock(ref e)        => block_to_string(e),
-            token::NtStmt(ref e)         => stmt_to_string(e),
-            token::NtPat(ref e)          => pat_to_string(e),
-            token::NtIdent(ref e, false) => ident_to_string(e.node),
-            token::NtIdent(ref e, true)  => format!("r#{}", ident_to_string(e.node)),
-            token::NtTT(ref tree)        => tt_to_string(tree.clone()),
-            token::NtArm(ref e)          => arm_to_string(e),
-            token::NtImplItem(ref e)     => impl_item_to_string(e),
-            token::NtTraitItem(ref e)    => trait_item_to_string(e),
-            token::NtGenerics(ref e)     => generic_params_to_string(&e.params),
-            token::NtWhereClause(ref e)  => where_clause_to_string(e),
-            token::NtArg(ref e)          => arg_to_string(e),
-            token::NtVis(ref e)          => vis_to_string(e),
-            token::NtLifetime(ref e)     => lifetime_to_string(e),
-            token::NtForeignItem(ref ni) => foreign_item_to_string(ni),
+            token::NtExpr(ref e)        => expr_to_string(e),
+            token::NtMeta(ref e)        => meta_item_to_string(e),
+            token::NtTy(ref e)          => ty_to_string(e),
+            token::NtPath(ref e)        => path_to_string(e),
+            token::NtItem(ref e)        => item_to_string(e),
+            token::NtBlock(ref e)       => block_to_string(e),
+            token::NtStmt(ref e)        => stmt_to_string(e),
+            token::NtPat(ref e)         => pat_to_string(e),
+            token::NtIdent(e, false)    => ident_to_string(e),
+            token::NtIdent(e, true)     => format!("r#{}", ident_to_string(e)),
+            token::NtTT(ref tree)       => tt_to_string(tree.clone()),
+            token::NtArm(ref e)         => arm_to_string(e),
+            token::NtImplItem(ref e)    => impl_item_to_string(e),
+            token::NtTraitItem(ref e)   => trait_item_to_string(e),
+            token::NtGenerics(ref e)    => generic_params_to_string(&e.params),
+            token::NtWhereClause(ref e) => where_clause_to_string(e),
+            token::NtArg(ref e)         => arg_to_string(e),
+            token::NtVis(ref e)         => vis_to_string(e),
+            token::NtLifetime(ref e)    => lifetime_to_string(e),
+            token::NtForeignItem(ref e) => foreign_item_to_string(e),
         }
     }
 }
@@ -1924,7 +1924,7 @@ impl<'a> State<'a> {
             |s, field| {
                 s.ibox(INDENT_UNIT)?;
                 if !field.is_shorthand {
-                    s.print_ident(field.ident.node)?;
+                    s.print_ident(field.ident)?;
                     s.word_space(":")?;
                 }
                 s.print_expr(&field.expr)?;
@@ -2198,10 +2198,10 @@ impl<'a> State<'a> {
                 self.word_space("=")?;
                 self.print_expr_maybe_paren(rhs, prec)?;
             }
-            ast::ExprKind::Field(ref expr, id) => {
+            ast::ExprKind::Field(ref expr, ident) => {
                 self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?;
                 self.s.word(".")?;
-                self.print_ident(id.node)?;
+                self.print_ident(ident)?;
             }
             ast::ExprKind::TupField(ref expr, id) => {
                 self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?;
@@ -2526,7 +2526,7 @@ impl<'a> State<'a> {
          is that it doesn't matter */
         match pat.node {
             PatKind::Wild => self.s.word("_")?,
-            PatKind::Ident(binding_mode, ref path1, ref sub) => {
+            PatKind::Ident(binding_mode, ident, ref sub) => {
                 match binding_mode {
                     ast::BindingMode::ByRef(mutbl) => {
                         self.word_nbsp("ref")?;
@@ -2537,7 +2537,7 @@ impl<'a> State<'a> {
                         self.word_nbsp("mut")?;
                     }
                 }
-                self.print_ident(path1.node)?;
+                self.print_ident(ident)?;
                 if let Some(ref p) = *sub {
                     self.s.word("@")?;
                     self.print_pat(p)?;
@@ -2999,7 +2999,7 @@ impl<'a> State<'a> {
                     self.print_explicit_self(&eself)?;
                 } else {
                     let invalid = if let PatKind::Ident(_, ident, _) = input.pat.node {
-                        ident.node.name == keywords::Invalid.name()
+                        ident.name == keywords::Invalid.name()
                     } else {
                         false
                     };
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 88fddb13686..7be3c2790e8 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -430,8 +430,8 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
         PatKind::Paren(ref subpattern) => {
             visitor.visit_pat(subpattern)
         }
-        PatKind::Ident(_, ref pth1, ref optional_subpattern) => {
-            visitor.visit_ident(pth1.span, pth1.node);
+        PatKind::Ident(_, ident, ref optional_subpattern) => {
+            visitor.visit_ident(ident.span, ident);
             walk_list!(visitor, visit_pat, optional_subpattern);
         }
         PatKind::Lit(ref expression) => visitor.visit_expr(expression),
@@ -666,7 +666,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
             visitor.visit_path(path, expression.id);
             for field in fields {
                 walk_list!(visitor, visit_attribute, field.attrs.iter());
-                visitor.visit_ident(field.ident.span, field.ident.node);
+                visitor.visit_ident(field.ident.span, field.ident);
                 visitor.visit_expr(&field.expr)
             }
             walk_list!(visitor, visit_expr, optional_base);
@@ -745,9 +745,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
             visitor.visit_expr(left_expression);
             visitor.visit_expr(right_expression);
         }
-        ExprKind::Field(ref subexpression, ref ident) => {
+        ExprKind::Field(ref subexpression, ident) => {
             visitor.visit_expr(subexpression);
-            visitor.visit_ident(ident.span, ident.node);
+            visitor.visit_ident(ident.span, ident);
         }
         ExprKind::TupField(ref subexpression, _) => {
             visitor.visit_expr(subexpression);
diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs
index 2b80d698764..1df7706966d 100644
--- a/src/libsyntax_ext/concat_idents.rs
+++ b/src/libsyntax_ext/concat_idents.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use syntax::ast;
-use syntax::codemap::DUMMY_SP;
 use syntax::ext::base::*;
 use syntax::ext::base;
 use syntax::feature_gate;
@@ -53,28 +52,17 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
             }
         }
     }
-    let res = ast::Ident::new(Symbol::intern(&res_str),
-                              DUMMY_SP.apply_mark(cx.current_expansion.mark));
-    struct Result {
-        ident: ast::Ident,
-        span: Span,
-    };
 
-    impl Result {
-        fn path(&self) -> ast::Path {
-            ast::Path {
-                span: self.span,
-                segments: vec![ast::PathSegment::from_ident(self.ident, self.span)],
-            }
-        }
-    }
+    let ident = ast::Ident::new(Symbol::intern(&res_str), sp.apply_mark(cx.current_expansion.mark));
+
+    struct ConcatIdentsResult { ident: ast::Ident }
 
-    impl base::MacResult for Result {
+    impl base::MacResult for ConcatIdentsResult {
         fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
             Some(P(ast::Expr {
                 id: ast::DUMMY_NODE_ID,
-                node: ast::ExprKind::Path(None, self.path()),
-                span: self.span,
+                node: ast::ExprKind::Path(None, ast::Path::from_ident(self.ident.span, self.ident)),
+                span: self.ident.span,
                 attrs: ast::ThinVec::new(),
             }))
         }
@@ -82,14 +70,11 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
         fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
             Some(P(ast::Ty {
                 id: ast::DUMMY_NODE_ID,
-                node: ast::TyKind::Path(None, self.path()),
-                span: self.span,
+                node: ast::TyKind::Path(None, ast::Path::from_ident(self.ident.span, self.ident)),
+                span: self.ident.span,
             }))
         }
     }
 
-    Box::new(Result {
-        ident: res,
-        span: sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark)),
-    })
+    Box::new(ConcatIdentsResult { ident })
 }
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index c51f44cdece..ab285c4d395 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -195,6 +195,7 @@ use syntax::abi::Abi;
 use syntax::ast::{
     self, BinOpKind, EnumDef, Expr, GenericParam, Generics, Ident, PatKind, VariantData
 };
+
 use syntax::attr;
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
@@ -952,7 +953,7 @@ impl<'a> MethodDef<'a> {
         let args = {
             let self_args = explicit_self.map(|explicit_self| {
                 ast::Arg::from_self(explicit_self,
-                                    respan(trait_.span, keywords::SelfValue.ident()))
+                                    keywords::SelfValue.ident().with_span_pos(trait_.span))
             });
             let nonself_args = arg_types.into_iter()
                 .map(|(name, ty)| cx.arg(trait_.span, name, ty));
@@ -1581,7 +1582,7 @@ impl<'a> TraitDef<'a> {
 
     fn create_subpatterns(&self,
                           cx: &mut ExtCtxt,
-                          field_paths: Vec<ast::SpannedIdent>,
+                          field_paths: Vec<ast::Ident>,
                           mutbl: ast::Mutability,
                           use_temporaries: bool)
                           -> Vec<P<ast::Pat>> {
@@ -1613,10 +1614,7 @@ impl<'a> TraitDef<'a> {
         for (i, struct_field) in struct_def.fields().iter().enumerate() {
             let sp = struct_field.span.with_ctxt(self.span.ctxt());
             let ident = cx.ident_of(&format!("{}_{}", prefix, i));
-            paths.push(codemap::Spanned {
-                span: sp,
-                node: ident,
-            });
+            paths.push(ident.with_span_pos(sp));
             let val = cx.expr_path(cx.path_ident(sp, ident));
             let val = if use_temporaries {
                 val
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 661a28d8375..279f1dec142 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -41,7 +41,12 @@ impl Ident {
         Ident::with_empty_ctxt(Symbol::intern(string))
     }
 
-    pub fn without_first_quote(&self) -> Ident {
+    /// Replace `lo` and `hi` with those from `span`, but keep hygiene context.
+    pub fn with_span_pos(self, span: Span) -> Ident {
+        Ident::new(self.name, span.with_ctxt(self.span.ctxt()))
+    }
+
+    pub fn without_first_quote(self) -> Ident {
         Ident::new(Symbol::from(self.name.as_str().trim_left_matches('\'')), self.span)
     }