Auto merge of #64483 - petrochenkov:expectattr2, r=Centril

resolve: Tweak some "cannot find" wording for macros
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index b50cfa0..58789a1 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1316,7 +1316,7 @@
                             ImplTraitContext::Universal(in_band_ty_params),
                         );
                         // Set the name to `impl Bound1 + Bound2`.
-                        let ident = Ident::from_str(&pprust::ty_to_string(t)).with_span_pos(span);
+                        let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
                         in_band_ty_params.push(hir::GenericParam {
                             hir_id: self.lower_node_id(def_node_id),
                             name: ParamName::Plain(ident),
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 561bf20..21ea476 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -618,24 +618,19 @@
             }
 
             // Trigger the lint if the nested item is a non-self single item
-            let node_ident;
-            match items[0].0.kind {
+            let node_name = match items[0].0.kind {
                 ast::UseTreeKind::Simple(rename, ..) => {
                     let orig_ident = items[0].0.prefix.segments.last().unwrap().ident;
                     if orig_ident.name == kw::SelfLower {
                         return;
                     }
-                    node_ident = rename.unwrap_or(orig_ident);
+                    rename.unwrap_or(orig_ident).name
                 }
-                ast::UseTreeKind::Glob => {
-                    node_ident = ast::Ident::from_str("*");
-                }
-                ast::UseTreeKind::Nested(_) => {
-                    return;
-                }
-            }
+                ast::UseTreeKind::Glob => Symbol::intern("*"),
+                ast::UseTreeKind::Nested(_) => return,
+            };
 
-            let msg = format!("braces around {} is unnecessary", node_ident.name);
+            let msg = format!("braces around {} is unnecessary", node_name);
             cx.span_lint(UNUSED_IMPORT_BRACES, item.span, &msg);
         }
     }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index d6450f0..a1e3bbc 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -444,7 +444,8 @@
             .insert(local_span, (name.to_string(), data.get_span(id.index, sess)));
 
         LoadedMacro::MacroDef(ast::Item {
-            ident: ast::Ident::from_str(&name.as_str()),
+            // FIXME: cross-crate hygiene
+            ident: ast::Ident::with_dummy_span(name.as_symbol()),
             id: ast::DUMMY_NODE_ID,
             span: local_span,
             attrs: attrs.iter().cloned().collect(),
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index f97fcb0..74f68e5 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -40,7 +40,7 @@
 use syntax::ext::hygiene::{ExpnId, Transparency, SyntaxContext};
 use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
 use syntax::ext::base::{SyntaxExtension, MacroKind, SpecialDerives};
-use syntax::symbol::{Symbol, kw, sym};
+use syntax::symbol::{kw, sym};
 
 use syntax::visit::{self, Visitor};
 use syntax::attr;
@@ -241,7 +241,7 @@
 
     fn names_to_string(segments: &[Segment]) -> String {
         names_to_string(&segments.iter()
-                            .map(|seg| seg.ident)
+                            .map(|seg| seg.ident.name)
                             .collect::<Vec<_>>())
     }
 }
@@ -951,7 +951,7 @@
     struct_constructors: DefIdMap<(Res, ty::Visibility)>,
 
     /// Features enabled for this crate.
-    active_features: FxHashSet<Symbol>,
+    active_features: FxHashSet<Name>,
 
     /// Stores enum visibilities to properly build a reduced graph
     /// when visiting the correspondent variants.
@@ -1018,8 +1018,8 @@
     fn resolve_str_path(
         &mut self,
         span: Span,
-        crate_root: Option<Symbol>,
-        components: &[Symbol],
+        crate_root: Option<Name>,
+        components: &[Name],
         ns: Namespace,
     ) -> (ast::Path, Res) {
         let root = if crate_root.is_some() {
@@ -2555,7 +2555,7 @@
     fn add_suggestion_for_rename_of_use(
         &self,
         err: &mut DiagnosticBuilder<'_>,
-        name: Symbol,
+        name: Name,
         directive: &ImportDirective<'_>,
         binding_span: Span,
     ) {
@@ -2770,22 +2770,22 @@
     }
 }
 
-fn names_to_string(idents: &[Ident]) -> String {
+fn names_to_string(names: &[Name]) -> String {
     let mut result = String::new();
-    for (i, ident) in idents.iter()
-                            .filter(|ident| ident.name != kw::PathRoot)
+    for (i, name) in names.iter()
+                            .filter(|name| **name != kw::PathRoot)
                             .enumerate() {
         if i > 0 {
             result.push_str("::");
         }
-        result.push_str(&ident.as_str());
+        result.push_str(&name.as_str());
     }
     result
 }
 
 fn path_names_to_string(path: &Path) -> String {
     names_to_string(&path.segments.iter()
-                        .map(|seg| seg.ident)
+                        .map(|seg| seg.ident.name)
                         .collect::<Vec<_>>())
 }
 
@@ -2793,15 +2793,14 @@
 fn module_to_string(module: Module<'_>) -> Option<String> {
     let mut names = Vec::new();
 
-    fn collect_mod(names: &mut Vec<Ident>, module: Module<'_>) {
+    fn collect_mod(names: &mut Vec<Name>, module: Module<'_>) {
         if let ModuleKind::Def(.., name) = module.kind {
             if let Some(parent) = module.parent {
-                names.push(Ident::with_dummy_span(name));
+                names.push(name);
                 collect_mod(names, parent);
             }
         } else {
-            // danger, shouldn't be ident?
-            names.push(Ident::from_str("<opaque>"));
+            names.push(Name::intern("<opaque>"));
             collect_mod(names, module.parent.unwrap());
         }
     }
@@ -2810,9 +2809,8 @@
     if names.is_empty() {
         return None;
     }
-    Some(names_to_string(&names.into_iter()
-                        .rev()
-                        .collect::<Vec<_>>()))
+    names.reverse();
+    Some(names_to_string(&names))
 }
 
 #[derive(Copy, Clone, Debug)]
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index eb509f1..e77e829 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -1433,15 +1433,17 @@
     let global = !names.is_empty() && names[0].name == kw::PathRoot;
     if let Some(pos) = pos {
         let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] };
-        names_to_string(names)
+        names_to_string(&names.iter().map(|ident| ident.name).collect::<Vec<_>>())
     } else {
         let names = if global { &names[1..] } else { names };
         if names.is_empty() {
             import_directive_subclass_to_string(subclass)
         } else {
-            format!("{}::{}",
-                    names_to_string(names),
-                    import_directive_subclass_to_string(subclass))
+            format!(
+                "{}::{}",
+                names_to_string(&names.iter().map(|ident| ident.name).collect::<Vec<_>>()),
+                import_directive_subclass_to_string(subclass),
+            )
         }
     }
 }
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 7759a98..384c055 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -977,13 +977,6 @@
         span.with_call_site_ctxt(self.current_expansion.id)
     }
 
-    /// Span with a context reproducing `macro_rules` hygiene (hygienic locals, unhygienic items).
-    /// FIXME: This should be eventually replaced either with `with_def_site_ctxt` (preferably),
-    /// or with `with_call_site_ctxt` (where necessary).
-    pub fn with_legacy_ctxt(&self, span: Span) -> Span {
-        span.with_legacy_ctxt(self.current_expansion.id)
-    }
-
     /// Returns span for the macro which originally caused the current expansion to happen.
     ///
     /// Stops backtracing at include! boundary.
@@ -1081,8 +1074,8 @@
     pub fn set_trace_macros(&mut self, x: bool) {
         self.ecfg.trace_mac = x
     }
-    pub fn ident_of(&self, st: &str) -> ast::Ident {
-        ast::Ident::from_str(st)
+    pub fn ident_of(&self, st: &str, sp: Span) -> ast::Ident {
+        ast::Ident::from_str_and_span(st, sp)
     }
     pub fn std_path(&self, components: &[Symbol]) -> Vec<ast::Ident> {
         let def_site = self.with_def_site_ctxt(DUMMY_SP);
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 06a5531..f1d0e0b 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -363,7 +363,7 @@
         self.expr(sp, ast::ExprKind::Field(expr, ident.with_span_pos(sp)))
     }
     pub fn expr_tup_field_access(&self, sp: Span, expr: P<ast::Expr>, idx: usize) -> P<ast::Expr> {
-        let ident = Ident::from_str(&idx.to_string()).with_span_pos(sp);
+        let ident = Ident::new(sym::integer(idx), sp);
         self.expr(sp, ast::ExprKind::Field(expr, ident))
     }
     pub fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
@@ -525,7 +525,7 @@
         let err = self.std_path(&[sym::result, sym::Result, sym::Err]);
         let err_path = self.path_global(sp, err);
 
-        let binding_variable = self.ident_of("__try_var");
+        let binding_variable = self.ident_of("__try_var", sp);
         let binding_pat = self.pat_ident(sp, binding_variable);
         let binding_expr = self.expr_ident(sp, binding_variable);
 
diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index baae615..cf19664 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -1256,7 +1256,7 @@
             for part in idents {
                 fixed_name.push_str(&format!("_{}", part.name));
             }
-            ident = Ident::from_str(&fixed_name).with_span_pos(fixed_name_sp);
+            ident = Ident::from_str_and_span(&fixed_name, fixed_name_sp);
 
             self.struct_span_err(fixed_name_sp, error_msg)
                 .span_label(fixed_name_sp, "dash-separated idents are not valid")
diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs
index 328b307..75d727b 100644
--- a/src/libsyntax_ext/asm.rs
+++ b/src/libsyntax_ext/asm.rs
@@ -62,7 +62,7 @@
     MacEager::expr(P(ast::Expr {
         id: ast::DUMMY_NODE_ID,
         node: ast::ExprKind::InlineAsm(P(inline_asm)),
-        span: cx.with_legacy_ctxt(sp),
+        span: cx.with_def_site_ctxt(sp),
         attrs: ThinVec::new(),
     }))
 }
diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs
index 001996e..cbfe14f 100644
--- a/src/libsyntax_ext/assert.rs
+++ b/src/libsyntax_ext/assert.rs
@@ -23,7 +23,9 @@
         }
     };
 
-    let sp = cx.with_legacy_ctxt(sp);
+    // `core::panic` and `std::panic` are different macros, so we use call-site
+    // context to pick up whichever is currently in scope.
+    let sp = cx.with_call_site_ctxt(sp);
     let panic_call = Mac {
         path: Path::from_ident(Ident::new(sym::panic, sp)),
         tts: custom_message.unwrap_or_else(|| {
diff --git a/src/libsyntax_ext/cfg.rs b/src/libsyntax_ext/cfg.rs
index 0342e44..3c33baf 100644
--- a/src/libsyntax_ext/cfg.rs
+++ b/src/libsyntax_ext/cfg.rs
@@ -16,7 +16,7 @@
     sp: Span,
     tts: TokenStream,
 ) -> Box<dyn base::MacResult + 'static> {
-    let sp = cx.with_legacy_ctxt(sp);
+    let sp = cx.with_def_site_ctxt(sp);
 
     match parse_cfg(cx, sp, tts) {
         Ok(cfg) => {
diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs
index fc56dff..16f0160 100644
--- a/src/libsyntax_ext/concat.rs
+++ b/src/libsyntax_ext/concat.rs
@@ -59,6 +59,6 @@
     } else if has_errors {
         return DummyResult::any(sp);
     }
-    let sp = cx.with_legacy_ctxt(sp);
+    let sp = cx.with_def_site_ctxt(sp);
     base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator)))
 }
diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs
index 6391b62..f344706 100644
--- a/src/libsyntax_ext/concat_idents.rs
+++ b/src/libsyntax_ext/concat_idents.rs
@@ -39,7 +39,7 @@
         }
     }
 
-    let ident = ast::Ident::new(Symbol::intern(&res_str), cx.with_legacy_ctxt(sp));
+    let ident = ast::Ident::new(Symbol::intern(&res_str), cx.with_call_site_ctxt(sp));
 
     struct ConcatIdentsResult { ident: ast::Ident }
 
diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
index debdc30..13d63aa 100644
--- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs
+++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
@@ -109,7 +109,7 @@
         GtOp => "gt",
         GeOp => "ge",
     };
-    cx.expr_method_call(span, lft, ast::Ident::from_str_and_span(op_str, span), vec![rgt])
+    cx.expr_method_call(span, lft, cx.ident_of(op_str, span), vec![rgt])
 }
 
 pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> {
diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs
index 781645a..088b61b 100644
--- a/src/libsyntax_ext/deriving/debug.rs
+++ b/src/libsyntax_ext/deriving/debug.rs
@@ -62,7 +62,7 @@
     // We want to make sure we have the ctxt set so that we can use unstable methods
     let span = cx.with_def_site_ctxt(span);
     let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
-    let builder = Ident::from_str_and_span("debug_trait_builder", span);
+    let builder = cx.ident_of("debug_trait_builder", span);
     let builder_expr = cx.expr_ident(span, builder.clone());
 
     let fmt = substr.nonself_args[0].clone();
@@ -72,7 +72,7 @@
         ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
             // tuple struct/"normal" variant
             let expr =
-                cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]);
+                cx.expr_method_call(span, fmt, cx.ident_of("debug_tuple", span), vec![name]);
             stmts.push(cx.stmt_let(span, true, builder, expr));
 
             for field in fields {
@@ -93,7 +93,7 @@
         ast::VariantData::Struct(..) => {
             // normal struct/struct variant
             let expr =
-                cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]);
+                cx.expr_method_call(span, fmt, cx.ident_of("debug_struct", span), vec![name]);
             stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
 
             for field in fields {
@@ -113,7 +113,7 @@
         }
     }
 
-    let expr = cx.expr_method_call(span, builder_expr, Ident::from_str("finish"), vec![]);
+    let expr = cx.expr_method_call(span, builder_expr, cx.ident_of("finish", span), vec![]);
 
     stmts.push(cx.stmt_expr(expr));
     let block = cx.block(span, stmts);
diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs
index d3d604b..cde72ab 100644
--- a/src/libsyntax_ext/deriving/decodable.rs
+++ b/src/libsyntax_ext/deriving/decodable.rs
@@ -66,10 +66,14 @@
                           krate: &str)
                           -> P<Expr> {
     let decoder = substr.nonself_args[0].clone();
-    let recurse = vec![cx.ident_of(krate), cx.ident_of("Decodable"), cx.ident_of("decode")];
+    let recurse = vec![
+        cx.ident_of(krate, trait_span),
+        cx.ident_of("Decodable", trait_span),
+        cx.ident_of("decode", trait_span),
+    ];
     let exprdecode = cx.expr_path(cx.path_global(trait_span, recurse));
     // throw an underscore in front to suppress unused variable warnings
-    let blkarg = cx.ident_of("_d");
+    let blkarg = cx.ident_of("_d", trait_span);
     let blkdecoder = cx.expr_ident(trait_span, blkarg);
 
     return match *substr.fields {
@@ -78,7 +82,7 @@
                 Unnamed(ref fields, _) => fields.len(),
                 Named(ref fields) => fields.len(),
             };
-            let read_struct_field = cx.ident_of("read_struct_field");
+            let read_struct_field = cx.ident_of("read_struct_field", trait_span);
 
             let path = cx.path_ident(trait_span, substr.type_ident);
             let result =
@@ -94,17 +98,17 @@
             let result = cx.expr_ok(trait_span, result);
             cx.expr_method_call(trait_span,
                                 decoder,
-                                cx.ident_of("read_struct"),
+                                cx.ident_of("read_struct", trait_span),
                                 vec![cx.expr_str(trait_span, substr.type_ident.name),
                                      cx.expr_usize(trait_span, nfields),
                                      cx.lambda1(trait_span, result, blkarg)])
         }
         StaticEnum(_, ref fields) => {
-            let variant = cx.ident_of("i");
+            let variant = cx.ident_of("i", trait_span);
 
             let mut arms = Vec::with_capacity(fields.len() + 1);
             let mut variants = Vec::with_capacity(fields.len());
-            let rvariant_arg = cx.ident_of("read_enum_variant_arg");
+            let rvariant_arg = cx.ident_of("read_enum_variant_arg", trait_span);
 
             for (i, &(ident, v_span, ref parts)) in fields.iter().enumerate() {
                 variants.push(cx.expr_str(v_span, ident.name));
@@ -132,11 +136,11 @@
             let variant_vec = cx.expr_addr_of(trait_span, variant_vec);
             let result = cx.expr_method_call(trait_span,
                                              blkdecoder,
-                                             cx.ident_of("read_enum_variant"),
+                                             cx.ident_of("read_enum_variant", trait_span),
                                              vec![variant_vec, lambda]);
             cx.expr_method_call(trait_span,
                                 decoder,
-                                cx.ident_of("read_enum"),
+                                cx.ident_of("read_enum", trait_span),
                                 vec![cx.expr_str(trait_span, substr.type_ident.name),
                                      cx.lambda1(trait_span, result, blkarg)])
         }
diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs
index 8b18fb2..655d3bb 100644
--- a/src/libsyntax_ext/deriving/encodable.rs
+++ b/src/libsyntax_ext/deriving/encodable.rs
@@ -153,16 +153,16 @@
                           -> P<Expr> {
     let encoder = substr.nonself_args[0].clone();
     // throw an underscore in front to suppress unused variable warnings
-    let blkarg = cx.ident_of("_e");
+    let blkarg = cx.ident_of("_e", trait_span);
     let blkencoder = cx.expr_ident(trait_span, blkarg);
     let fn_path = cx.expr_path(cx.path_global(trait_span,
-                                              vec![cx.ident_of(krate),
-                                                   cx.ident_of("Encodable"),
-                                                   cx.ident_of("encode")]));
+                                              vec![cx.ident_of(krate, trait_span),
+                                                   cx.ident_of("Encodable", trait_span),
+                                                   cx.ident_of("encode", trait_span)]));
 
     return match *substr.fields {
         Struct(_, ref fields) => {
-            let emit_struct_field = cx.ident_of("emit_struct_field");
+            let emit_struct_field = cx.ident_of("emit_struct_field", trait_span);
             let mut stmts = Vec::new();
             for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() {
                 let name = match name {
@@ -201,7 +201,7 @@
 
             cx.expr_method_call(trait_span,
                                 encoder,
-                                cx.ident_of("emit_struct"),
+                                cx.ident_of("emit_struct", trait_span),
                                 vec![cx.expr_str(trait_span, substr.type_ident.name),
                                      cx.expr_usize(trait_span, fields.len()),
                                      blk])
@@ -214,7 +214,7 @@
             // actually exist.
             let me = cx.stmt_let(trait_span, false, blkarg, encoder);
             let encoder = cx.expr_ident(trait_span, blkarg);
-            let emit_variant_arg = cx.ident_of("emit_enum_variant_arg");
+            let emit_variant_arg = cx.ident_of("emit_enum_variant_arg", trait_span);
             let mut stmts = Vec::new();
             if !fields.is_empty() {
                 let last = fields.len() - 1;
@@ -244,7 +244,7 @@
             let name = cx.expr_str(trait_span, variant.ident.name);
             let call = cx.expr_method_call(trait_span,
                                            blkencoder,
-                                           cx.ident_of("emit_enum_variant"),
+                                           cx.ident_of("emit_enum_variant", trait_span),
                                            vec![name,
                                                 cx.expr_usize(trait_span, idx),
                                                 cx.expr_usize(trait_span, fields.len()),
@@ -252,7 +252,7 @@
             let blk = cx.lambda1(trait_span, call, blkarg);
             let ret = cx.expr_method_call(trait_span,
                                           encoder,
-                                          cx.ident_of("emit_enum"),
+                                          cx.ident_of("emit_enum", trait_span),
                                           vec![cx.expr_str(trait_span ,substr.type_ident.name),
                                                blk]);
             cx.expr_block(cx.block(trait_span, vec![me, cx.stmt_expr(ret)]))
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index c53fa7d..aceee62 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -237,7 +237,7 @@
     /// Whether there is a self argument (outer Option) i.e., whether
     /// this is a static function, and whether it is a pointer (inner
     /// Option)
-    pub explicit_self: Option<Option<PtrTy<'a>>>,
+    pub explicit_self: Option<Option<PtrTy>>,
 
     /// Arguments other than the self argument
     pub args: Vec<(Ty<'a>, &'a str)>,
@@ -843,7 +843,7 @@
                                 -> P<Expr> {
         let substructure = Substructure {
             type_ident,
-            method_ident: cx.ident_of(self.name),
+            method_ident: cx.ident_of(self.name, trait_.span),
             self_args,
             nonself_args,
             fields,
@@ -890,7 +890,7 @@
 
         for (ty, name) in self.args.iter() {
             let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
-            let ident = ast::Ident::from_str_and_span(name, trait_.span);
+            let ident = cx.ident_of(name, trait_.span);
             arg_tys.push((ident, ast_ty));
 
             let arg_expr = cx.expr_ident(trait_.span, ident);
@@ -938,7 +938,7 @@
 
         let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident);
 
-        let method_ident = cx.ident_of(self.name);
+        let method_ident = cx.ident_of(self.name, trait_.span);
         let fn_decl = cx.fn_decl(args, ast::FunctionRetTy::Ty(ret_type));
         let body_block = cx.block_expr(body);
 
@@ -1201,7 +1201,7 @@
             ).collect::<Vec<String>>();
 
         let self_arg_idents = self_arg_names.iter()
-            .map(|name| cx.ident_of(&name[..]))
+            .map(|name| cx.ident_of(name, sp))
             .collect::<Vec<ast::Ident>>();
 
         // The `vi_idents` will be bound, solely in the catch-all, to
@@ -1210,7 +1210,7 @@
         let vi_idents = self_arg_names.iter()
             .map(|name| {
                 let vi_suffix = format!("{}_vi", &name[..]);
-                ast::Ident::from_str_and_span(&vi_suffix[..], trait_.span)
+                cx.ident_of(&vi_suffix[..], trait_.span)
             })
             .collect::<Vec<ast::Ident>>();
 
@@ -1389,7 +1389,7 @@
 
                 let target_ty = cx.ty_ident(
                     sp,
-                    ast::Ident::from_str_and_span(target_type_name, sp),
+                    cx.ident_of(target_type_name, sp),
                 );
                 let variant_disr = cx.expr_cast(sp, variant_value, target_ty);
                 let let_stmt = cx.stmt_let(sp, false, ident, variant_disr);
@@ -1591,7 +1591,7 @@
         let mut ident_exprs = Vec::new();
         for (i, struct_field) in struct_def.fields().iter().enumerate() {
             let sp = struct_field.span.with_ctxt(self.span.ctxt());
-            let ident = ast::Ident::from_str_and_span(&format!("{}_{}", prefix, i), self.span);
+            let ident = cx.ident_of(&format!("{}_{}", prefix, i), self.span);
             paths.push(ident.with_span_pos(sp));
             let val = cx.expr_path(cx.path_ident(sp, ident));
             let val = if use_temporaries {
diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs
index cb1c7b2..b341a07 100644
--- a/src/libsyntax_ext/deriving/generic/ty.rs
+++ b/src/libsyntax_ext/deriving/generic/ty.rs
@@ -13,9 +13,9 @@
 
 /// The types of pointers
 #[derive(Clone)]
-pub enum PtrTy<'a> {
+pub enum PtrTy {
     /// &'lifetime mut
-    Borrowed(Option<&'a str>, ast::Mutability),
+    Borrowed(Option<Ident>, ast::Mutability),
     /// *mut
     #[allow(dead_code)]
     Raw(ast::Mutability),
@@ -26,7 +26,7 @@
 #[derive(Clone)]
 pub struct Path<'a> {
     path: Vec<&'a str>,
-    lifetime: Option<&'a str>,
+    lifetime: Option<Ident>,
     params: Vec<Box<Ty<'a>>>,
     kind: PathKind,
 }
@@ -46,7 +46,7 @@
         Path::new_(vec![path], None, Vec::new(), PathKind::Local)
     }
     pub fn new_<'r>(path: Vec<&'r str>,
-                    lifetime: Option<&'r str>,
+                    lifetime: Option<Ident>,
                     params: Vec<Box<Ty<'r>>>,
                     kind: PathKind)
                     -> Path<'r> {
@@ -72,7 +72,7 @@
                    self_ty: Ident,
                    self_generics: &Generics)
                    -> ast::Path {
-        let mut idents = self.path.iter().map(|s| Ident::from_str_and_span(*s, span)).collect();
+        let mut idents = self.path.iter().map(|s| cx.ident_of(*s, span)).collect();
         let lt = mk_lifetimes(cx, span, &self.lifetime);
         let tys: Vec<P<ast::Ty>> =
             self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
@@ -99,7 +99,7 @@
 pub enum Ty<'a> {
     Self_,
     /// &/Box/ Ty
-    Ptr(Box<Ty<'a>>, PtrTy<'a>),
+    Ptr(Box<Ty<'a>>, PtrTy),
     /// mod::mod::Type<[lifetime], [Params...]>, including a plain type
     /// parameter, and things like `i32`
     Literal(Path<'a>),
@@ -107,14 +107,14 @@
     Tuple(Vec<Ty<'a>>),
 }
 
-pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
+pub fn borrowed_ptrty() -> PtrTy {
     Borrowed(None, ast::Mutability::Immutable)
 }
 pub fn borrowed(ty: Box<Ty<'_>>) -> Ty<'_> {
     Ptr(ty, borrowed_ptrty())
 }
 
-pub fn borrowed_explicit_self<'r>() -> Option<Option<PtrTy<'r>>> {
+pub fn borrowed_explicit_self() -> Option<Option<PtrTy>> {
     Some(Some(borrowed_ptrty()))
 }
 
@@ -126,13 +126,11 @@
     Tuple(Vec::new())
 }
 
-fn mk_lifetime(cx: &ExtCtxt<'_>, span: Span, lt: &Option<&str>) -> Option<ast::Lifetime> {
-    lt.map(|s|
-        cx.lifetime(span, Ident::from_str(s))
-    )
+fn mk_lifetime(cx: &ExtCtxt<'_>, span: Span, lt: &Option<Ident>) -> Option<ast::Lifetime> {
+    lt.map(|ident| cx.lifetime(span, ident))
 }
 
-fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option<&str>) -> Vec<ast::Lifetime> {
+fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option<Ident>) -> Vec<ast::Lifetime> {
     mk_lifetime(cx, span, lt).into_iter().collect()
 }
 
@@ -209,7 +207,7 @@
             cx.trait_bound(path)
         })
         .collect();
-    cx.typaram(span, ast::Ident::from_str_and_span(name, span), attrs.to_owned(), bounds, None)
+    cx.typaram(span, cx.ident_of(name, span), attrs.to_owned(), bounds, None)
 }
 
 fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
@@ -265,7 +263,7 @@
 
 pub fn get_explicit_self(cx: &ExtCtxt<'_>,
                          span: Span,
-                         self_ptr: &Option<PtrTy<'_>>)
+                         self_ptr: &Option<PtrTy>)
                          -> (P<Expr>, ast::ExplicitSelf) {
     // this constructs a fresh `self` path
     let self_path = cx.expr_self(span);
@@ -276,7 +274,7 @@
                 respan(span,
                        match *ptr {
                            Borrowed(ref lt, mutbl) => {
-                               let lt = lt.map(|s| cx.lifetime(span, Ident::from_str(s)));
+                               let lt = lt.map(|s| cx.lifetime(span, s));
                                SelfKind::Region(lt, mutbl)
                            }
                            Raw(_) => {
diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs
index 179b7fe..70e1fbe 100644
--- a/src/libsyntax_ext/env.rs
+++ b/src/libsyntax_ext/env.rs
@@ -20,16 +20,16 @@
         Some(v) => v,
     };
 
-    let sp = cx.with_legacy_ctxt(sp);
+    let sp = cx.with_def_site_ctxt(sp);
     let e = match env::var(&*var.as_str()) {
         Err(..) => {
-            let lt = cx.lifetime(sp, Ident::with_dummy_span(kw::StaticLifetime));
+            let lt = cx.lifetime(sp, Ident::new(kw::StaticLifetime, sp));
             cx.expr_path(cx.path_all(sp,
                                      true,
                                      cx.std_path(&[sym::option, sym::Option, sym::None]),
                                      vec![GenericArg::Type(cx.ty_rptr(sp,
                                                      cx.ty_ident(sp,
-                                                                 Ident::with_dummy_span(sym::str)),
+                                                                 Ident::new(sym::str, sp)),
                                                      Some(lt),
                                                      ast::Mutability::Immutable))],
                                      vec![]))
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 5bfbdc9..46c7cbb 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -486,7 +486,7 @@
         let sp = self.macsp;
         let count = |c, arg| {
             let mut path = Context::rtpath(self.ecx, "Count");
-            path.push(self.ecx.ident_of(c));
+            path.push(self.ecx.ident_of(c, sp));
             match arg {
                 Some(arg) => self.ecx.expr_call_global(sp, path, vec![arg]),
                 None => self.ecx.expr_path(self.ecx.path_global(sp, path)),
@@ -534,7 +534,7 @@
                 let pos = {
                     let pos = |c, arg| {
                         let mut path = Context::rtpath(self.ecx, "Position");
-                        path.push(self.ecx.ident_of(c));
+                        path.push(self.ecx.ident_of(c, sp));
                         match arg {
                             Some(i) => {
                                 let arg = self.ecx.expr_usize(sp, i);
@@ -603,7 +603,7 @@
                 let fill = self.ecx.expr_lit(sp, ast::LitKind::Char(fill));
                 let align = |name| {
                     let mut p = Context::rtpath(self.ecx, "Alignment");
-                    p.push(self.ecx.ident_of(name));
+                    p.push(self.ecx.ident_of(name, sp));
                     self.ecx.path_global(sp, p)
                 };
                 let align = match arg.format.align {
@@ -621,11 +621,11 @@
                     sp,
                     path,
                     vec![
-                        self.ecx.field_imm(sp, self.ecx.ident_of("fill"), fill),
-                        self.ecx.field_imm(sp, self.ecx.ident_of("align"), align),
-                        self.ecx.field_imm(sp, self.ecx.ident_of("flags"), flags),
-                        self.ecx.field_imm(sp, self.ecx.ident_of("precision"), prec),
-                        self.ecx.field_imm(sp, self.ecx.ident_of("width"), width),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("fill", sp), fill),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("align", sp), align),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("flags", sp), flags),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("precision", sp), prec),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("width", sp), width),
                     ],
                 );
 
@@ -634,8 +634,8 @@
                     sp,
                                           path,
                     vec![
-                        self.ecx.field_imm(sp, self.ecx.ident_of("position"), pos),
-                        self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("position", sp), pos),
+                        self.ecx.field_imm(sp, self.ecx.ident_of("format", sp), fmt),
                     ],
                 ))
             }
@@ -653,7 +653,7 @@
         let mut heads = Vec::with_capacity(self.args.len());
 
         let names_pos: Vec<_> = (0..self.args.len())
-            .map(|i| ast::Ident::from_str_and_span(&format!("arg{}", i), self.macsp))
+            .map(|i| self.ecx.ident_of(&format!("arg{}", i), self.macsp))
             .collect();
 
         // First, build up the static array which will become our precompiled
diff --git a/src/libsyntax_ext/global_allocator.rs b/src/libsyntax_ext/global_allocator.rs
index f4af169..19a87e6 100644
--- a/src/libsyntax_ext/global_allocator.rs
+++ b/src/libsyntax_ext/global_allocator.rs
@@ -28,7 +28,7 @@
     };
 
     // Generate a bunch of new items using the AllocFnFactory
-    let span = ecx.with_legacy_ctxt(item.span);
+    let span = ecx.with_def_site_ctxt(item.span);
     let f = AllocFnFactory {
         span,
         kind: AllocatorKind::Global,
@@ -43,7 +43,7 @@
     let const_ty = ecx.ty(span, TyKind::Tup(Vec::new()));
     let const_body = ecx.expr_block(ecx.block(span, stmts));
     let const_item =
-        ecx.item_const(span, Ident::with_dummy_span(kw::Underscore), const_ty, const_body);
+        ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
 
     // Return the original item and the new methods.
     vec![Annotatable::Item(item), Annotatable::Item(const_item)]
@@ -61,7 +61,7 @@
         let mut abi_args = Vec::new();
         let mut i = 0;
         let ref mut mk = || {
-            let name = Ident::from_str(&format!("arg{}", i));
+            let name = self.cx.ident_of(&format!("arg{}", i), self.span);
             i += 1;
             name
         };
@@ -83,7 +83,7 @@
         );
         let item = self.cx.item(
             self.span,
-            Ident::from_str(&self.kind.fn_name(method.name)),
+            self.cx.ident_of(&self.kind.fn_name(method.name), self.span),
             self.attrs(),
             kind,
         );
@@ -119,7 +119,7 @@
     ) -> P<Expr> {
         match *ty {
             AllocatorTy::Layout => {
-                let usize = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::usize));
+                let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span));
                 let ty_usize = self.cx.ty_path(usize);
                 let size = ident();
                 let align = ident();
@@ -177,12 +177,12 @@
     }
 
     fn usize(&self) -> P<Ty> {
-        let usize = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::usize));
+        let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span));
         self.cx.ty_path(usize)
     }
 
     fn ptr_u8(&self) -> P<Ty> {
-        let u8 = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::u8));
+        let u8 = self.cx.path_ident(self.span, Ident::new(sym::u8, self.span));
         let ty_u8 = self.cx.ty_path(u8);
         self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable)
     }
diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs
index 6140f0d..c56b3f3 100644
--- a/src/libsyntax_ext/global_asm.rs
+++ b/src/libsyntax_ext/global_asm.rs
@@ -30,7 +30,7 @@
                 id: ast::DUMMY_NODE_ID,
                 node: ast::ItemKind::GlobalAsm(P(global_asm)),
                 vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
-                span: cx.with_legacy_ctxt(sp),
+                span: cx.with_def_site_ctxt(sp),
                 tokens: None,
             })])
         }
diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs
index 31d32d2..a5dcfb9 100644
--- a/src/libsyntax_ext/proc_macro_harness.rs
+++ b/src/libsyntax_ext/proc_macro_harness.rs
@@ -340,12 +340,12 @@
                         Vec::new(),
                         ast::ItemKind::ExternCrate(None));
 
-    let bridge = Ident::from_str_and_span("bridge", span);
-    let client = Ident::from_str_and_span("client", span);
-    let proc_macro_ty = Ident::from_str_and_span("ProcMacro", span);
-    let custom_derive = Ident::from_str_and_span("custom_derive", span);
-    let attr = Ident::from_str_and_span("attr", span);
-    let bang = Ident::from_str_and_span("bang", span);
+    let bridge = cx.ident_of("bridge", span);
+    let client = cx.ident_of("client", span);
+    let proc_macro_ty = cx.ident_of("ProcMacro", span);
+    let custom_derive = cx.ident_of("custom_derive", span);
+    let attr = cx.ident_of("attr", span);
+    let bang = cx.ident_of("bang", span);
 
     let decls = {
         let local_path = |sp: Span, name| {
@@ -378,7 +378,7 @@
 
     let decls_static = cx.item_static(
         span,
-        Ident::from_str_and_span("_DECLS", span),
+        cx.ident_of("_DECLS", span),
         cx.ty_rptr(span,
             cx.ty(span, ast::TyKind::Slice(
                 cx.ty_path(cx.path(span,
diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs
index be5aca7..0910c00 100644
--- a/src/libsyntax_ext/test.rs
+++ b/src/libsyntax_ext/test.rs
@@ -98,20 +98,20 @@
 
     // creates test::$name
     let test_path = |name| {
-        cx.path(sp, vec![test_id, cx.ident_of(name)])
+        cx.path(sp, vec![test_id, cx.ident_of(name, sp)])
     };
 
     // creates test::ShouldPanic::$name
     let should_panic_path = |name| {
-        cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic"), cx.ident_of(name)])
+        cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic", sp), cx.ident_of(name, sp)])
     };
 
     // creates $name: $expr
-    let field = |name, expr| cx.field_imm(sp, cx.ident_of(name), expr);
+    let field = |name, expr| cx.field_imm(sp, cx.ident_of(name, sp), expr);
 
     let test_fn = if is_bench {
         // A simple ident for a lambda
-        let b = ast::Ident::from_str_and_span("b", attr_sp);
+        let b = cx.ident_of("b", attr_sp);
 
         cx.expr_call(sp, cx.expr_path(test_path("StaticBenchFn")), vec![
             // |b| self::test::assert_test_result(
diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs
index b93c11f..56de0c9 100644
--- a/src/libsyntax_ext/test_harness.rs
+++ b/src/libsyntax_ext/test_harness.rs
@@ -250,7 +250,7 @@
 
     // test::test_main_static(...)
     let mut test_runner = cx.test_runner.clone().unwrap_or(
-        ecx.path(sp, vec![test_id, Ident::from_str_and_span("test_main_static", sp)]));
+        ecx.path(sp, vec![test_id, ecx.ident_of("test_main_static", sp)]));
 
     test_runner.span = sp;
 
@@ -288,7 +288,7 @@
     // Honor the reexport_test_harness_main attribute
     let main_id = match cx.reexport_test_harness_main {
         Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())),
-        None => Ident::from_str_and_span("main", sp),
+        None => Ident::new(sym::main, sp),
     };
 
     let main = P(ast::Item {
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 9a296f1..ca177eb 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -526,13 +526,6 @@
         self.with_ctxt_from_mark(expn_id, Transparency::Transparent)
     }
 
-    /// Span with a context reproducing `macro_rules` hygiene (hygienic locals, unhygienic items).
-    /// FIXME: This should be eventually replaced either with `with_def_site_ctxt` (preferably),
-    /// or with `with_call_site_ctxt` (where necessary).
-    pub fn with_legacy_ctxt(&self, expn_id: ExpnId) -> Span {
-        self.with_ctxt_from_mark(expn_id, Transparency::SemiTransparent)
-    }
-
     /// Produces a span with the same location as `self` and context produced by a macro with the
     /// given ID and transparency, assuming that macro was defined directly and not produced by
     /// some other macro (which is the case for built-in and procedural macros).
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index ab32d44..597ae83 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -765,7 +765,7 @@
         Ident::with_dummy_span(string.as_symbol())
     }
 
-    /// Maps a string to an identifier with an empty span.
+    /// Maps a string to an identifier with a dummy span.
     pub fn from_str(string: &str) -> Ident {
         Ident::with_dummy_span(Symbol::intern(string))
     }
diff --git a/src/test/ui/allocator/hygiene.rs b/src/test/ui/allocator/hygiene.rs
new file mode 100644
index 0000000..9bd8406
--- /dev/null
+++ b/src/test/ui/allocator/hygiene.rs
@@ -0,0 +1,31 @@
+// run-pass
+// no-prefer-dynamic
+// aux-build:custom.rs
+// aux-build:helper.rs
+
+#![allow(nonstandard_style)]
+
+extern crate custom;
+extern crate helper;
+
+use custom::A;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+#[allow(dead_code)]
+struct u8;
+#[allow(dead_code)]
+struct usize;
+#[allow(dead_code)]
+static arg0: () = ();
+
+#[global_allocator]
+pub static GLOBAL: A = A(AtomicUsize::new(0));
+
+fn main() {
+    let n = GLOBAL.0.load(Ordering::SeqCst);
+    let s = Box::new(0);
+    helper::work_with(&s);
+    assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1);
+    drop(s);
+    assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
+}
diff --git a/src/test/ui/syntax-extension-minor.rs b/src/test/ui/syntax-extension-minor.rs
index 0206a76..2d6710a 100644
--- a/src/test/ui/syntax-extension-minor.rs
+++ b/src/test/ui/syntax-extension-minor.rs
@@ -1,3 +1,5 @@
+// run-pass
+
 #![feature(concat_idents)]
 
 pub fn main() {
@@ -5,10 +7,8 @@
     let _: concat_idents!(F, oo) = Foo; // Test that `concat_idents!` can be used in type positions
 
     let asdf_fdsa = "<.<".to_string();
-    // this now fails (correctly, I claim) because hygiene prevents
-    // the assembled identifier from being a reference to the binding.
+    // concat_idents should have call-site hygiene.
     assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string());
-    //~^ ERROR cannot find value `asdf_fdsa` in this scope
 
     assert_eq!(stringify!(use_mention_distinction), "use_mention_distinction");
 }
diff --git a/src/test/ui/syntax-extension-minor.stderr b/src/test/ui/syntax-extension-minor.stderr
deleted file mode 100644
index 2d8056d..0000000
--- a/src/test/ui/syntax-extension-minor.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0425]: cannot find value `asdf_fdsa` in this scope
-  --> $DIR/syntax-extension-minor.rs:10:13
-   |
-LL |     assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string());
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0425`.