about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-10-02 17:19:40 +0000
committerbors <bors@rust-lang.org>2018-10-02 17:19:40 +0000
commit87e19575c471eab82e2831a181b88575fda44c1c (patch)
tree57d6307df89cf30e811c41b3cb61f1bb7d1b8bd6 /src
parenta18eb4852a0a0f8054e358567f129eb7f11cfd7d (diff)
parent2280d5990cfbc09946e091ef0489eec047567356 (diff)
Auto merge of #54750 - pietroalbini:beta-backports, r=pietroalbini
[beta] Rollup backports

Merged and approved:

* #54650: Don't lint non-extern-prelude extern crate's in Rust 2018.
* #54338: Use full name to identify a macro in a `FileName`.
* #54518: resolve: Do not block derive helper resolutions on single import resolutions
* #54581: Accept trailing comma in `cfg_attr`

r? @ghost
Diffstat (limited to 'src')
-rw-r--r--src/librustc/hir/map/definitions.rs25
-rw-r--r--src/librustc/session/mod.rs18
-rw-r--r--src/librustc/ty/query/on_disk_cache.rs1
-rw-r--r--src/librustc_metadata/creader.rs1
-rw-r--r--src/librustc_metadata/cstore.rs5
-rw-r--r--src/librustc_metadata/cstore_impl.rs8
-rw-r--r--src/librustc_metadata/decoder.rs4
-rw-r--r--src/librustc_resolve/lib.rs20
-rw-r--r--src/librustc_resolve/macros.rs22
-rw-r--r--src/librustc_resolve/resolve_imports.rs6
-rw-r--r--src/librustc_typeck/check_unused.rs16
-rw-r--r--src/libsyntax/config.rs1
-rw-r--r--src/libsyntax_pos/lib.rs2
-rw-r--r--src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs6
-rw-r--r--src/test/ui-fulldeps/custom-derive/auxiliary/plugin.rs10
-rw-r--r--src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.rs13
-rw-r--r--src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr20
-rw-r--r--src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import.rs29
-rw-r--r--src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr13
-rw-r--r--src/test/ui-fulldeps/unnecessary-extern-crate.rs22
-rw-r--r--src/test/ui-fulldeps/unnecessary-extern-crate.stderr64
-rw-r--r--src/test/ui/cfg-attr-trailing-comma.rs13
-rw-r--r--src/test/ui/cfg-attr-trailing-comma.stderr14
-rw-r--r--src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr2
-rw-r--r--src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr2
-rw-r--r--src/test/ui/imports/local-modularized-tricky-fail-1.stderr2
-rw-r--r--src/test/ui/macro_backtrace/main.stderr10
-rw-r--r--src/test/ui/rust-2018/remove-extern-crate.fixed6
-rw-r--r--src/test/ui/rust-2018/remove-extern-crate.rs6
-rw-r--r--src/test/ui/rust-2018/remove-extern-crate.stderr8
30 files changed, 223 insertions, 146 deletions
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index c85cee73660..fa4bf1511b8 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -287,6 +287,31 @@ impl DefPath {
         s
     }
 
+    /// Return filename friendly string of the DefPah with the
+    /// crate-prefix.
+    pub fn to_string_friendly<F>(&self, crate_imported_name: F) -> String
+        where F: FnOnce(CrateNum) -> Symbol
+    {
+        let crate_name_str = crate_imported_name(self.krate).as_str();
+        let mut s = String::with_capacity(crate_name_str.len() + self.data.len() * 16);
+
+        write!(s, "::{}", crate_name_str).unwrap();
+
+        for component in &self.data {
+            if component.disambiguator == 0 {
+                write!(s, "::{}", component.data.as_interned_str()).unwrap();
+            } else {
+                write!(s,
+                       "{}[{}]",
+                       component.data.as_interned_str(),
+                       component.disambiguator)
+                    .unwrap();
+            }
+        }
+
+        s
+    }
+
     /// Return filename friendly string of the DefPah without
     /// the crate-prefix. This method is useful if you don't have
     /// a TyCtxt available.
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 619262abb0b..18fc3538537 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -37,7 +37,7 @@ use syntax::parse;
 use syntax::parse::ParseSess;
 use syntax::{ast, source_map};
 use syntax::feature_gate::AttributeType;
-use syntax_pos::{MultiSpan, Span};
+use syntax_pos::{MultiSpan, Span, symbol::Symbol};
 use util::profiling::SelfProfiler;
 
 use rustc_target::spec::PanicStrategy;
@@ -164,6 +164,10 @@ pub struct Session {
 
     /// Cap lint level specified by a driver specifically.
     pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
+
+    /// All the crate names specified with `--extern`, and the builtin ones.
+    /// Starting with the Rust 2018 edition, absolute paths resolve in this set.
+    pub extern_prelude: FxHashSet<Symbol>,
 }
 
 pub struct PerfStats {
@@ -1109,6 +1113,17 @@ pub fn build_session_(
     };
     let working_dir = file_path_mapping.map_prefix(working_dir);
 
+    let mut extern_prelude: FxHashSet<Symbol> =
+        sopts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect();
+
+    // HACK(eddyb) this ignores the `no_{core,std}` attributes.
+    // FIXME(eddyb) warn (somewhere) if core/std is used with `no_{core,std}`.
+    // if !attr::contains_name(&krate.attrs, "no_core") {
+    // if !attr::contains_name(&krate.attrs, "no_std") {
+    extern_prelude.insert(Symbol::intern("core"));
+    extern_prelude.insert(Symbol::intern("std"));
+    extern_prelude.insert(Symbol::intern("meta"));
+
     let sess = Session {
         target: target_cfg,
         host,
@@ -1183,6 +1198,7 @@ pub fn build_session_(
         has_global_allocator: Once::new(),
         has_panic_handler: Once::new(),
         driver_lint_caps: FxHashMap(),
+        extern_prelude,
     };
 
     validate_commandline_args_with_session_available(&sess);
diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs
index 0e4d2f1f647..296602e21ba 100644
--- a/src/librustc/ty/query/on_disk_cache.rs
+++ b/src/librustc/ty/query/on_disk_cache.rs
@@ -606,6 +606,7 @@ impl<'a, 'tcx, 'x> SpecializedDecoder<interpret::AllocId> for CacheDecoder<'a, '
         alloc_decoding_session.decode_alloc_id(self)
     }
 }
+
 impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
     fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
         let tag: u8 = Decodable::decode(self)?;
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 6eef2397f9c..fa2debf2c0d 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -256,6 +256,7 @@ impl<'a> CrateLoader<'a> {
 
         let cmeta = cstore::CrateMetadata {
             name: crate_root.name,
+            imported_name: ident,
             extern_crate: Lock::new(None),
             def_path_table: Lrc::new(def_path_table),
             trait_impls,
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index aad632f8918..ec48a4a4c69 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -53,8 +53,13 @@ pub struct ImportedSourceFile {
 }
 
 pub struct CrateMetadata {
+    /// Original name of the crate.
     pub name: Symbol,
 
+    /// Name of the crate as imported.  I.e. if imported with
+    /// `extern crate foo as bar;` this will be `bar`.
+    pub imported_name: Symbol,
+
     /// Information about the extern crate that caused this crate to
     /// be loaded. If this is `None`, then the crate was injected
     /// (e.g., by the allocator)
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 4382a3c12c9..4bea8558ffe 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -441,8 +441,7 @@ impl cstore::CStore {
         let data = self.get_crate_data(id.krate);
         if let Some(ref proc_macros) = data.proc_macros {
             return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone());
-        } else if data.name == "proc_macro" &&
-                  self.get_crate_data(id.krate).item_name(id.index) == "quote" {
+        } else if data.name == "proc_macro" && data.item_name(id.index) == "quote" {
             use syntax::ext::base::SyntaxExtension;
             use syntax_ext::proc_macro_impl::BangProcMacro;
 
@@ -454,8 +453,9 @@ impl cstore::CStore {
             return LoadedMacro::ProcMacro(Lrc::new(ext));
         }
 
-        let (name, def) = data.get_macro(id.index);
-        let source_name = FileName::Macros(name.to_string());
+        let def = data.get_macro(id.index);
+        let macro_full_name = data.def_path(id.index).to_string_friendly(|_| data.imported_name);
+        let source_name = FileName::Macros(macro_full_name);
 
         let source_file = sess.parse_sess.source_map().new_source_file(source_name, def.body);
         let local_span = Span::new(source_file.start_pos, source_file.end_pos, NO_EXPANSION);
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 43b03cb863c..044d23270aa 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -1101,10 +1101,10 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_macro(&self, id: DefIndex) -> (InternedString, MacroDef) {
+    pub fn get_macro(&self, id: DefIndex) -> MacroDef {
         let entry = self.entry(id);
         match entry.kind {
-            EntryKind::MacroDef(macro_def) => (self.item_name(id), macro_def.decode(self)),
+            EntryKind::MacroDef(macro_def) => macro_def.decode(self),
             _ => bug!(),
         }
     }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 168603d4179..e393aa99218 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1350,7 +1350,6 @@ pub struct Resolver<'a, 'b: 'a> {
     graph_root: Module<'a>,
 
     prelude: Option<Module<'a>>,
-    extern_prelude: FxHashSet<Name>,
 
     /// n.b. This is used only for better diagnostics, not name resolution itself.
     has_self: FxHashSet<DefId>,
@@ -1663,17 +1662,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
         DefCollector::new(&mut definitions, Mark::root())
             .collect_root(crate_name, session.local_crate_disambiguator());
 
-        let mut extern_prelude: FxHashSet<Name> =
-            session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect();
-
-        // HACK(eddyb) this ignore the `no_{core,std}` attributes.
-        // FIXME(eddyb) warn (elsewhere) if core/std is used with `no_{core,std}`.
-        // if !attr::contains_name(&krate.attrs, "no_core") {
-        // if !attr::contains_name(&krate.attrs, "no_std") {
-        extern_prelude.insert(Symbol::intern("core"));
-        extern_prelude.insert(Symbol::intern("std"));
-        extern_prelude.insert(Symbol::intern("meta"));
-
         let mut invocations = FxHashMap();
         invocations.insert(Mark::root(),
                            arenas.alloc_invocation_data(InvocationData::root(graph_root)));
@@ -1692,7 +1680,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
             // AST.
             graph_root,
             prelude: None,
-            extern_prelude,
 
             has_self: FxHashSet(),
             field_names: FxHashMap(),
@@ -1963,7 +1950,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
 
         if !module.no_implicit_prelude {
             // `record_used` means that we don't try to load crates during speculative resolution
-            if record_used && ns == TypeNS && self.extern_prelude.contains(&ident.name) {
+            if record_used && ns == TypeNS && self.session.extern_prelude.contains(&ident.name) {
                 let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span);
                 let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
                 self.populate_module_if_necessary(&crate_root);
@@ -3950,7 +3937,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                     } else {
                         // Items from the prelude
                         if !module.no_implicit_prelude {
-                            names.extend(self.extern_prelude.iter().cloned());
+                            names.extend(self.session.extern_prelude.iter().cloned());
                             if let Some(prelude) = self.prelude {
                                 add_module_candidates(prelude, &mut names);
                             }
@@ -4396,8 +4383,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
         );
 
         if self.session.rust_2018() {
-            let extern_prelude_names = self.extern_prelude.clone();
-            for &name in extern_prelude_names.iter() {
+            for &name in &self.session.extern_prelude {
                 let ident = Ident::with_empty_ctxt(name);
                 match self.crate_loader.maybe_process_path_extern(name, ident.span) {
                     Some(crate_id) => {
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 35d96b9302b..b320ef032f2 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -575,6 +575,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
         // 5. Standard library prelude (de-facto closed, controlled).
         // 6. Language prelude (closed, controlled).
         // (Macro NS)
+        // 0. Derive helpers (open, not controlled). All ambiguities with other names
+        //    are currently reported as errors. They should be higher in priority than preludes
+        //    and probably even names in modules according to the "general principles" above. They
+        //    also should be subject to restricted shadowing because are effectively produced by
+        //    derives (you need to resolve the derive first to add helpers into scope), but they
+        //    should be available before the derive is expanded for compatibility.
+        //    It's mess in general, so we are being conservative for now.
         // 1. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
         //    (open, not controlled).
         // 2. `macro_use` prelude (open, the open part is from macro expansions, not controlled).
@@ -583,13 +590,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
         // 2b. Standard library prelude is currently implemented as `macro-use` (closed, controlled)
         // 3. Language prelude: builtin macros (closed, controlled, except for legacy plugins).
         // 4. Language prelude: builtin attributes (closed, controlled).
-        // N (unordered). Derive helpers (open, not controlled). All ambiguities with other names
-        //    are currently reported as errors. They should be higher in priority than preludes
-        //    and maybe even names in modules according to the "general principles" above. They
-        //    also should be subject to restricted shadowing because are effectively produced by
-        //    derives (you need to resolve the derive first to add helpers into scope), but they
-        //    should be available before the derive is expanded for compatibility.
-        //    It's mess in general, so we are being conservative for now.
 
         assert!(ns == TypeNS  || ns == MacroNS);
         assert!(force || !record_used); // `record_used` implies `force`
@@ -621,7 +621,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
         }
 
         // Go through all the scopes and try to resolve the name.
-        let mut where_to_resolve = WhereToResolve::Module(parent_scope.module);
+        let mut where_to_resolve = WhereToResolve::DeriveHelpers;
         let mut use_prelude = !parent_scope.module.no_implicit_prelude;
         loop {
             let result = match where_to_resolve {
@@ -681,7 +681,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                     result
                 }
                 WhereToResolve::ExternPrelude => {
-                    if use_prelude && self.extern_prelude.contains(&ident.name) {
+                    if use_prelude && self.session.extern_prelude.contains(&ident.name) {
                         let crate_id =
                             self.crate_loader.process_path_extern(ident.name, ident.span);
                         let crate_root =
@@ -751,8 +751,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                     }
                     WhereToResolve::MacroUsePrelude => WhereToResolve::BuiltinMacros,
                     WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs,
-                    WhereToResolve::BuiltinAttrs => WhereToResolve::DeriveHelpers,
-                    WhereToResolve::DeriveHelpers => break, // nowhere else to search
+                    WhereToResolve::BuiltinAttrs => break, // nowhere else to search
+                    WhereToResolve::DeriveHelpers => WhereToResolve::Module(parent_scope.module),
                     WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude,
                     WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude,
                     WhereToResolve::StdLibPrelude => WhereToResolve::BuiltinTypes,
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index dc4a76db692..e689e6d70fd 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -199,7 +199,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
                     if !(
                         ns == TypeNS &&
                         !ident.is_path_segment_keyword() &&
-                        self.extern_prelude.contains(&ident.name)
+                        self.session.extern_prelude.contains(&ident.name)
                     ) {
                         // ... unless the crate name is not in the `extern_prelude`.
                         return binding;
@@ -218,7 +218,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
                 } else if
                     ns == TypeNS &&
                     !ident.is_path_segment_keyword() &&
-                    self.extern_prelude.contains(&ident.name)
+                    self.session.extern_prelude.contains(&ident.name)
                 {
                     let crate_id =
                         self.crate_loader.process_path_extern(ident.name, ident.span);
@@ -735,7 +735,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
         let uniform_paths_feature = self.session.features_untracked().uniform_paths;
         for ((span, _, ns), results) in uniform_paths_canaries {
             let name = results.name;
-            let external_crate = if ns == TypeNS && self.extern_prelude.contains(&name) {
+            let external_crate = if ns == TypeNS && self.session.extern_prelude.contains(&name) {
                 let crate_id =
                     self.crate_loader.process_path_extern(name, span);
                 Some(Def::Mod(DefId { krate: crate_id, index: CRATE_DEF_INDEX }))
diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs
index 5967bd1ba3e..4b3f08a10ff 100644
--- a/src/librustc_typeck/check_unused.rs
+++ b/src/librustc_typeck/check_unused.rs
@@ -130,15 +130,13 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
     });
 
     for extern_crate in &crates_to_lint {
-        assert!(extern_crate.def_id.is_local());
+        let id = tcx.hir.as_local_node_id(extern_crate.def_id).unwrap();
+        let item = tcx.hir.expect_item(id);
 
         // If the crate is fully unused, we suggest removing it altogether.
         // We do this in any edition.
         if extern_crate.warn_if_unused {
             if let Some(&span) = unused_extern_crates.get(&extern_crate.def_id) {
-                assert_eq!(extern_crate.def_id.krate, LOCAL_CRATE);
-                let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index);
-                let id = tcx.hir.hir_to_node_id(hir_id);
                 let msg = "unused extern crate";
                 tcx.struct_span_lint_node(lint, id, span, msg)
                     .span_suggestion_short_with_applicability(
@@ -157,6 +155,13 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
             continue;
         }
 
+        // If the extern crate isn't in the extern prelude,
+        // there is no way it can be written as an `use`.
+        let orig_name = extern_crate.orig_name.unwrap_or(item.name);
+        if !tcx.sess.extern_prelude.contains(&orig_name) {
+            continue;
+        }
+
         // If the extern crate has any attributes, they may have funky
         // semantics we can't faithfully represent using `use` (most
         // notably `#[macro_use]`). Ignore it.
@@ -165,9 +170,6 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
         }
 
         // Otherwise, we can convert it into a `use` of some kind.
-        let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index);
-        let id = tcx.hir.hir_to_node_id(hir_id);
-        let item = tcx.hir.expect_item(id);
         let msg = "`extern crate` is not idiomatic in the new edition";
         let help = format!(
             "convert it to a `{}`",
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index 63b70b12248..bc4b7385d8a 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -89,6 +89,7 @@ impl<'a> StripUnconfigured<'a> {
             parser.expect(&token::Comma)?;
             let lo = parser.span.lo();
             let (path, tokens) = parser.parse_meta_item_unrestricted()?;
+            parser.eat(&token::Comma); // Optional trailing comma
             parser.expect(&token::CloseDelim(token::Paren))?;
             Ok((cfg, path, tokens, parser.prev_span.with_lo(lo)))
         }) {
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index bd70344b018..67fd847a2ae 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -87,7 +87,7 @@ scoped_thread_local!(pub static GLOBALS: Globals);
 #[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
 pub enum FileName {
     Real(PathBuf),
-    /// e.g. "std" macros
+    /// A macro.  This includes the full name of the macro, so that there are no clashes.
     Macros(String),
     /// call to `quote!`
     QuoteExpansion,
diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs
index 83bbb7c13c4..d0aed8b1624 100644
--- a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs
+++ b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs
@@ -11,13 +11,11 @@
 // aux-build:derive-b.rs
 // ignore-stage1
 
-#![allow(warnings)]
-
 #[macro_use]
 extern crate derive_b;
 
-#[B] //~ ERROR `B` is a derive mode
-#[C]
+#[B]
+#[C] //~ ERROR attribute `C` is currently unknown to the compiler
 #[B(D)]
 #[B(E = "foo")]
 #[B(arbitrary tokens)]
diff --git a/src/test/ui-fulldeps/custom-derive/auxiliary/plugin.rs b/src/test/ui-fulldeps/custom-derive/auxiliary/plugin.rs
index 7be909c3c9e..124bc05b7a3 100644
--- a/src/test/ui-fulldeps/custom-derive/auxiliary/plugin.rs
+++ b/src/test/ui-fulldeps/custom-derive/auxiliary/plugin.rs
@@ -25,3 +25,13 @@ pub fn derive_foo(input: TokenStream) -> TokenStream {
 pub fn derive_bar(input: TokenStream) -> TokenStream {
     panic!("lolnope");
 }
+
+#[proc_macro_derive(WithHelper, attributes(helper))]
+pub fn with_helper(input: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
+
+#[proc_macro_attribute]
+pub fn helper(_: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.rs b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.rs
new file mode 100644
index 00000000000..b750a8bb0d9
--- /dev/null
+++ b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.rs
@@ -0,0 +1,13 @@
+// aux-build:plugin.rs
+// ignore-stage1
+
+#[macro_use(WithHelper)]
+extern crate plugin;
+
+use plugin::helper;
+
+#[derive(WithHelper)]
+#[helper] //~ ERROR `helper` is ambiguous
+struct S;
+
+fn main() {}
diff --git a/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr
new file mode 100644
index 00000000000..059629c0b62
--- /dev/null
+++ b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr
@@ -0,0 +1,20 @@
+error[E0659]: `helper` is ambiguous
+  --> $DIR/helper-attr-blocked-by-import-ambig.rs:10:3
+   |
+LL | #[helper] //~ ERROR `helper` is ambiguous
+   |   ^^^^^^ ambiguous name
+   |
+note: `helper` could refer to the name defined here
+  --> $DIR/helper-attr-blocked-by-import-ambig.rs:9:10
+   |
+LL | #[derive(WithHelper)]
+   |          ^^^^^^^^^^
+note: `helper` could also refer to the name imported here
+  --> $DIR/helper-attr-blocked-by-import-ambig.rs:7:5
+   |
+LL | use plugin::helper;
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import.rs b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import.rs
new file mode 100644
index 00000000000..03b774f6c64
--- /dev/null
+++ b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import.rs
@@ -0,0 +1,29 @@
+// compile-pass
+// aux-build:plugin.rs
+// ignore-stage1
+
+#[macro_use(WithHelper)]
+extern crate plugin;
+
+use self::one::*;
+use self::two::*;
+
+mod helper {}
+
+mod one {
+    use helper;
+
+    #[derive(WithHelper)]
+    #[helper]
+    struct One;
+}
+
+mod two {
+    use helper;
+
+    #[derive(WithHelper)]
+    #[helper]
+    struct Two;
+}
+
+fn main() {}
diff --git a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr
index cdfecb3d101..e0aeae4ba6c 100644
--- a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr
+++ b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr
@@ -4,17 +4,16 @@ error[E0659]: `my_attr` is ambiguous
 LL | #[my_attr] //~ ERROR `my_attr` is ambiguous
    |   ^^^^^^^ ambiguous name
    |
-note: `my_attr` could refer to the name imported here
-  --> $DIR/derive-helper-shadowing.rs:4:5
-   |
-LL | use derive_helper_shadowing::*;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: `my_attr` could also refer to the name defined here
+note: `my_attr` could refer to the name defined here
   --> $DIR/derive-helper-shadowing.rs:7:10
    |
 LL | #[derive(MyTrait)]
    |          ^^^^^^^
-   = note: consider adding an explicit import of `my_attr` to disambiguate
+note: `my_attr` could also refer to the name imported here
+  --> $DIR/derive-helper-shadowing.rs:4:5
+   |
+LL | use derive_helper_shadowing::*;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui-fulldeps/unnecessary-extern-crate.rs b/src/test/ui-fulldeps/unnecessary-extern-crate.rs
index df723ddf590..1cdc9229d07 100644
--- a/src/test/ui-fulldeps/unnecessary-extern-crate.rs
+++ b/src/test/ui-fulldeps/unnecessary-extern-crate.rs
@@ -20,33 +20,23 @@ extern crate alloc as x;
 //~^ ERROR unused extern crate
 //~| HELP remove
 
+extern crate proc_macro;
+
 #[macro_use]
 extern crate test;
 
 pub extern crate test as y;
-//~^ ERROR `extern crate` is not idiomatic in the new edition
-//~| HELP convert it to a `pub use`
 
 pub extern crate libc;
-//~^ ERROR `extern crate` is not idiomatic in the new edition
-//~| HELP convert it to a `pub use`
 
 pub(crate) extern crate libc as a;
-//~^ ERROR `extern crate` is not idiomatic in the new edition
-//~| HELP convert it to a `pub(crate) use`
 
 crate extern crate libc as b;
-//~^ ERROR `extern crate` is not idiomatic in the new edition
-//~| HELP convert it to a `crate use`
 
 mod foo {
     pub(in crate::foo) extern crate libc as c;
-    //~^ ERROR `extern crate` is not idiomatic in the new edition
-    //~| HELP convert it to a `pub(in crate::foo) use`
 
     pub(super) extern crate libc as d;
-    //~^ ERROR `extern crate` is not idiomatic in the new edition
-    //~| HELP convert it to a `pub(super) use`
 
     extern crate alloc;
     //~^ ERROR unused extern crate
@@ -57,12 +47,8 @@ mod foo {
     //~| HELP remove
 
     pub extern crate test;
-    //~^ ERROR `extern crate` is not idiomatic in the new edition
-    //~| HELP convert it
 
     pub extern crate test as y;
-    //~^ ERROR `extern crate` is not idiomatic in the new edition
-    //~| HELP convert it
 
     mod bar {
         extern crate alloc;
@@ -74,8 +60,6 @@ mod foo {
         //~| HELP remove
 
         pub(in crate::foo::bar) extern crate libc as e;
-        //~^ ERROR `extern crate` is not idiomatic in the new edition
-        //~| HELP convert it to a `pub(in crate::foo::bar) use`
 
         fn dummy() {
             unsafe {
@@ -96,4 +80,6 @@ mod foo {
 fn main() {
     unsafe { a::getpid(); }
     unsafe { b::getpid(); }
+
+    proc_macro::TokenStream::new();
 }
diff --git a/src/test/ui-fulldeps/unnecessary-extern-crate.stderr b/src/test/ui-fulldeps/unnecessary-extern-crate.stderr
index a4307112157..58ec5901585 100644
--- a/src/test/ui-fulldeps/unnecessary-extern-crate.stderr
+++ b/src/test/ui-fulldeps/unnecessary-extern-crate.stderr
@@ -16,83 +16,29 @@ error: unused extern crate
 LL | extern crate alloc as x;
    | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
 
-error: `extern crate` is not idiomatic in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:26:1
-   |
-LL | pub extern crate test as y;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`
-
-error: `extern crate` is not idiomatic in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:30:1
-   |
-LL | pub extern crate libc;
-   | ^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`
-
-error: `extern crate` is not idiomatic in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:34:1
-   |
-LL | pub(crate) extern crate libc as a;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(crate) use`
-
-error: `extern crate` is not idiomatic in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:38:1
-   |
-LL | crate extern crate libc as b;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `crate use`
-
-error: `extern crate` is not idiomatic in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:43:5
-   |
-LL |     pub(in crate::foo) extern crate libc as c;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(in crate::foo) use`
-
-error: `extern crate` is not idiomatic in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:47:5
-   |
-LL |     pub(super) extern crate libc as d;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(super) use`
-
 error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:51:5
+  --> $DIR/unnecessary-extern-crate.rs:41:5
    |
 LL |     extern crate alloc;
    |     ^^^^^^^^^^^^^^^^^^^ help: remove it
 
 error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:55:5
+  --> $DIR/unnecessary-extern-crate.rs:45:5
    |
 LL |     extern crate alloc as x;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
 
-error: `extern crate` is not idiomatic in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:59:5
-   |
-LL |     pub extern crate test;
-   |     ^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`
-
-error: `extern crate` is not idiomatic in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:63:5
-   |
-LL |     pub extern crate test as y;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use`
-
 error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:68:9
+  --> $DIR/unnecessary-extern-crate.rs:54:9
    |
 LL |         extern crate alloc;
    |         ^^^^^^^^^^^^^^^^^^^ help: remove it
 
 error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:72:9
+  --> $DIR/unnecessary-extern-crate.rs:58:9
    |
 LL |         extern crate alloc as x;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
 
-error: `extern crate` is not idiomatic in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:76:9
-   |
-LL |         pub(in crate::foo::bar) extern crate libc as e;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(in crate::foo::bar) use`
-
-error: aborting due to 15 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/cfg-attr-trailing-comma.rs b/src/test/ui/cfg-attr-trailing-comma.rs
new file mode 100644
index 00000000000..21e00544ca0
--- /dev/null
+++ b/src/test/ui/cfg-attr-trailing-comma.rs
@@ -0,0 +1,13 @@
+// compile-flags: --cfg TRUE
+
+#[cfg_attr(TRUE, inline,)] // OK
+fn f() {}
+
+#[cfg_attr(FALSE, inline,)] // OK
+fn g() {}
+
+#[cfg_attr(TRUE, inline,,)] //~ ERROR expected `)`, found `,`
+fn h() {}
+
+#[cfg_attr(FALSE, inline,,)] //~ ERROR expected `)`, found `,`
+fn i() {}
diff --git a/src/test/ui/cfg-attr-trailing-comma.stderr b/src/test/ui/cfg-attr-trailing-comma.stderr
new file mode 100644
index 00000000000..76a470417e9
--- /dev/null
+++ b/src/test/ui/cfg-attr-trailing-comma.stderr
@@ -0,0 +1,14 @@
+error: expected `)`, found `,`
+  --> $DIR/cfg-attr-trailing-comma.rs:9:25
+   |
+LL | #[cfg_attr(TRUE, inline,,)] //~ ERROR expected `)`, found `,`
+   |                         ^ expected `)`
+
+error: expected `)`, found `,`
+  --> $DIR/cfg-attr-trailing-comma.rs:12:26
+   |
+LL | #[cfg_attr(FALSE, inline,,)] //~ ERROR expected `)`, found `,`
+   |                          ^ expected `)`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr
index 02e7d5b7cd0..5955410aa10 100644
--- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr
+++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr
@@ -23,7 +23,7 @@ LL |     r#async = consumes_async_raw!(async); //~ ERROR no rules expected the t
    |                                   ^^^^^
 
 error: expected one of `move`, `|`, or `||`, found `<eof>`
-  --> <passes_ident macros>:1:22
+  --> <::edition_kw_macro_2015::passes_ident macros>:1:22
    |
 LL | ( $ i : ident ) => ( $ i )
    |                      ^^^ expected one of `move`, `|`, or `||` here
diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr
index 435e395c291..6ea736828f9 100644
--- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr
+++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr
@@ -23,7 +23,7 @@ LL |     r#async = consumes_async_raw!(async); //~ ERROR no rules expected the t
    |                                   ^^^^^
 
 error: expected one of `move`, `|`, or `||`, found `<eof>`
-  --> <passes_ident macros>:1:22
+  --> <::edition_kw_macro_2018::passes_ident macros>:1:22
    |
 LL | ( $ i : ident ) => ( $ i )
    |                      ^^^ expected one of `move`, `|`, or `||` here
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
index cce1fd30f1d..9c475451ce3 100644
--- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
+++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
@@ -60,7 +60,7 @@ LL |       define_panic!();
    = note: macro-expanded macros do not shadow
 
 error[E0659]: `panic` is ambiguous
-  --> <panic macros>:1:13
+  --> <::std::macros::panic macros>:1:13
    |
 LL | (  ) => ( { panic ! ( "explicit panic" ) } ) ; ( $ msg : expr ) => (
    |             ^^^^^ ambiguous name
diff --git a/src/test/ui/macro_backtrace/main.stderr b/src/test/ui/macro_backtrace/main.stderr
index 10eabca6353..8cecef508a2 100644
--- a/src/test/ui/macro_backtrace/main.stderr
+++ b/src/test/ui/macro_backtrace/main.stderr
@@ -22,7 +22,7 @@ LL | | }
 LL |       ping!();
    |       -------- in this macro invocation
    | 
-  ::: <ping macros>:1:1
+  ::: <::ping::ping macros>:1:1
    |
 LL |   (  ) => { pong ! (  ) ; }
    |   -------------------------
@@ -42,7 +42,7 @@ LL | | }
 LL |       deep!();
    |       -------- in this macro invocation (#1)
    | 
-  ::: <deep macros>:1:1
+  ::: <::ping::deep macros>:1:1
    |
 LL |   (  ) => { foo ! (  ) ; }
    |   ------------------------
@@ -50,7 +50,7 @@ LL |   (  ) => { foo ! (  ) ; }
    |   |         in this macro invocation (#2)
    |   in this expansion of `deep!` (#1)
    | 
-  ::: <foo macros>:1:1
+  ::: <::ping::foo macros>:1:1
    |
 LL |   (  ) => { bar ! (  ) ; }
    |   ------------------------
@@ -58,7 +58,7 @@ LL |   (  ) => { bar ! (  ) ; }
    |   |         in this macro invocation (#3)
    |   in this expansion of `foo!` (#2)
    | 
-  ::: <bar macros>:1:1
+  ::: <::ping::bar macros>:1:1
    |
 LL |   (  ) => { ping ! (  ) ; }
    |   -------------------------
@@ -66,7 +66,7 @@ LL |   (  ) => { ping ! (  ) ; }
    |   |         in this macro invocation (#4)
    |   in this expansion of `bar!` (#3)
    | 
-  ::: <ping macros>:1:1
+  ::: <::ping::ping macros>:1:1
    |
 LL |   (  ) => { pong ! (  ) ; }
    |   -------------------------
diff --git a/src/test/ui/rust-2018/remove-extern-crate.fixed b/src/test/ui/rust-2018/remove-extern-crate.fixed
index cdae815b200..34c7266b637 100644
--- a/src/test/ui/rust-2018/remove-extern-crate.fixed
+++ b/src/test/ui/rust-2018/remove-extern-crate.fixed
@@ -14,6 +14,7 @@
 // aux-build:remove-extern-crate.rs
 // compile-flags:--extern remove_extern_crate
 
+#![feature(alloc)]
 #![warn(rust_2018_idioms)]
 
 
@@ -22,11 +23,16 @@ use remove_extern_crate;
 #[macro_use]
 extern crate remove_extern_crate as something_else;
 
+// Shouldn't suggest changing to `use`, as the `alloc`
+// crate is not in the extern prelude - see #54381.
+extern crate alloc;
+
 fn main() {
     another_name::mem::drop(3);
     another::foo();
     remove_extern_crate::foo!();
     bar!();
+    alloc::vec![5];
 }
 
 mod another {
diff --git a/src/test/ui/rust-2018/remove-extern-crate.rs b/src/test/ui/rust-2018/remove-extern-crate.rs
index 4984da802c0..570bbb02f72 100644
--- a/src/test/ui/rust-2018/remove-extern-crate.rs
+++ b/src/test/ui/rust-2018/remove-extern-crate.rs
@@ -14,6 +14,7 @@
 // aux-build:remove-extern-crate.rs
 // compile-flags:--extern remove_extern_crate
 
+#![feature(alloc)]
 #![warn(rust_2018_idioms)]
 
 extern crate core;
@@ -22,11 +23,16 @@ use remove_extern_crate;
 #[macro_use]
 extern crate remove_extern_crate as something_else;
 
+// Shouldn't suggest changing to `use`, as the `alloc`
+// crate is not in the extern prelude - see #54381.
+extern crate alloc;
+
 fn main() {
     another_name::mem::drop(3);
     another::foo();
     remove_extern_crate::foo!();
     bar!();
+    alloc::vec![5];
 }
 
 mod another {
diff --git a/src/test/ui/rust-2018/remove-extern-crate.stderr b/src/test/ui/rust-2018/remove-extern-crate.stderr
index 064a853625f..847ba5f3544 100644
--- a/src/test/ui/rust-2018/remove-extern-crate.stderr
+++ b/src/test/ui/rust-2018/remove-extern-crate.stderr
@@ -1,24 +1,24 @@
 warning: unused extern crate
-  --> $DIR/remove-extern-crate.rs:19:1
+  --> $DIR/remove-extern-crate.rs:20:1
    |
 LL | extern crate core;
    | ^^^^^^^^^^^^^^^^^^ help: remove it
    |
 note: lint level defined here
-  --> $DIR/remove-extern-crate.rs:17:9
+  --> $DIR/remove-extern-crate.rs:18:9
    |
 LL | #![warn(rust_2018_idioms)]
    |         ^^^^^^^^^^^^^^^^
    = note: #[warn(unused_extern_crates)] implied by #[warn(rust_2018_idioms)]
 
 warning: `extern crate` is not idiomatic in the new edition
-  --> $DIR/remove-extern-crate.rs:20:1
+  --> $DIR/remove-extern-crate.rs:21:1
    |
 LL | extern crate core as another_name;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
 
 warning: `extern crate` is not idiomatic in the new edition
-  --> $DIR/remove-extern-crate.rs:33:5
+  --> $DIR/remove-extern-crate.rs:39:5
    |
 LL |     extern crate core;
    |     ^^^^^^^^^^^^^^^^^^ help: convert it to a `use`