about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-03-07 02:36:07 +0000
committerbors <bors@rust-lang.org>2021-03-07 02:36:07 +0000
commit66ec64ccf31883cd2c28d045912a76179c0c6ed2 (patch)
treec91086d0e3c6cff3ed331adc66931e17281701f8 /src
parentdfe519b344b60e54a2028d3366ca366a228537e3 (diff)
parent6220e00ea9a790fb83cf391e2093c260db6d47a1 (diff)
downloadrust-66ec64ccf31883cd2c28d045912a76179c0c6ed2.tar.gz
rust-66ec64ccf31883cd2c28d045912a76179c0c6ed2.zip
Auto merge of #82851 - JohnTitor:rollup-me5ko8g, r=JohnTitor
Rollup of 13 pull requests

Successful merges:

 - #77916 (Change built-in kernel targets to be os = none throughout)
 - #82130 (Make some Option, Result methods unstably const)
 - #82292 (Prevent specialized ZipImpl from calling `__iterator_get_unchecked` twice with the same index)
 - #82402 (Remove RefCell around `module_trait_cache`)
 - #82592 (Improve transmute docs with further clarifications)
 - #82651 (Cleanup rustdoc warnings)
 - #82720 (Fix diagnostic suggests adding type `[type error]`)
 - #82751 (improve offset_from docs)
 - #82793 (Move some tests to more suitable subdirs)
 - #82803 (rustdoc: Add an unstable option to print all unversioned files)
 - #82808 (Sync rustc_codegen_cranelift)
 - #82822 (Fix typo)
 - #82837 (tweak MaybeUninit docs)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'src')
-rw-r--r--src/doc/rustc/src/platform-support.md4
-rw-r--r--src/librustdoc/clean/types.rs18
-rw-r--r--src/librustdoc/config.rs12
-rw-r--r--src/librustdoc/core.rs73
-rw-r--r--src/librustdoc/html/render/mod.rs1
-rw-r--r--src/librustdoc/html/render/write_shared.rs39
-rw-r--r--src/librustdoc/lib.rs21
-rw-r--r--src/librustdoc/passes/check_code_block_syntax.rs9
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs67
-rw-r--r--src/librustdoc/passes/doc_test_lints.rs2
-rw-r--r--src/librustdoc/passes/html_tags.rs9
-rw-r--r--src/librustdoc/passes/mod.rs5
-rw-r--r--src/librustdoc/passes/non_autolinks.rs4
-rw-r--r--src/test/run-make-fulldeps/print-unversioned-files/Makefile4
-rw-r--r--src/test/run-make-fulldeps/print-unversioned-files/unversioned-files.txt15
-rw-r--r--src/test/rustdoc-ui/deprecated-attrs.rs20
-rw-r--r--src/test/rustdoc-ui/deprecated-attrs.stderr41
-rw-r--r--src/test/ui/abi/nullable-pointer-ffi-compat.rs (renamed from src/test/ui/nullable-pointer-ffi-compat.rs)0
-rw-r--r--src/test/ui/associated-types/issue-76179.rs (renamed from src/test/ui/issues/issue-76179.rs)0
-rw-r--r--src/test/ui/async-await/issue-74047.rs (renamed from src/test/ui/issue-74047.rs)0
-rw-r--r--src/test/ui/async-await/issue-74047.stderr (renamed from src/test/ui/issue-74047.stderr)0
-rw-r--r--src/test/ui/borrowck/issue-42344.rs (renamed from src/test/ui/issues/issue-42344.rs)0
-rw-r--r--src/test/ui/borrowck/issue-42344.stderr (renamed from src/test/ui/issues/issue-42344.stderr)0
-rw-r--r--src/test/ui/consts/auxiliary/issue-17718-aux.rs (renamed from src/test/ui/issues/auxiliary/issue-17718-aux.rs)0
-rw-r--r--src/test/ui/consts/issue-17718.rs (renamed from src/test/ui/issues/issue-17718.rs)0
-rw-r--r--src/test/ui/consts/issue-3521.fixed (renamed from src/test/ui/issues/issue-3521.fixed)0
-rw-r--r--src/test/ui/consts/issue-3521.rs (renamed from src/test/ui/issues/issue-3521.rs)0
-rw-r--r--src/test/ui/consts/issue-3521.stderr (renamed from src/test/ui/issues/issue-3521.stderr)0
-rw-r--r--src/test/ui/issues/issue-2633-2.rs14
-rw-r--r--src/test/ui/issues/issue-2633.rs31
-rw-r--r--src/test/ui/lint/lint-expr-stmt-attrs-for-early-lints.rs (renamed from src/test/ui/lint-expr-stmt-attrs-for-early-lints.rs)0
-rw-r--r--src/test/ui/nll/issue-52992.rs (renamed from src/test/ui/issues/issue-52992.rs)0
-rw-r--r--src/test/ui/parser/issue-7222.rs (renamed from src/test/ui/issues/issue-7222.rs)0
-rw-r--r--src/test/ui/parser/item-free-const-no-body-semantic-fail.rs1
-rw-r--r--src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr8
-rw-r--r--src/test/ui/parser/item-free-static-no-body-semantic-fail.rs2
-rw-r--r--src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr18
-rw-r--r--src/test/ui/regions/issue-6157.rs (renamed from src/test/ui/issue-6157.rs)0
-rw-r--r--src/test/ui/resolve/issue-2330.rs (renamed from src/test/ui/issues/issue-2330.rs)0
-rw-r--r--src/test/ui/resolve/issue-2330.stderr (renamed from src/test/ui/issues/issue-2330.stderr)0
-rw-r--r--src/test/ui/statics/issue-15261.rs (renamed from src/test/ui/issues/issue-15261.rs)0
-rw-r--r--src/test/ui/statics/issue-44373-2.rs (renamed from src/test/ui/issues/issue-44373-2.rs)0
-rw-r--r--src/test/ui/statics/issue-44373.rs (renamed from src/test/ui/issues/issue-44373.rs)0
-rw-r--r--src/test/ui/statics/issue-44373.stderr (renamed from src/test/ui/issues/issue-44373.stderr)0
-rw-r--r--src/test/ui/traits/impl-bounds-checking.rs (renamed from src/test/ui/impl-bounds-checking.rs)0
-rw-r--r--src/test/ui/traits/impl-bounds-checking.stderr (renamed from src/test/ui/impl-bounds-checking.stderr)0
-rw-r--r--src/test/ui/traits/issue-28576.rs (renamed from src/test/ui/issues/issue-28576.rs)0
-rw-r--r--src/test/ui/traits/issue-28576.stderr (renamed from src/test/ui/issues/issue-28576.stderr)0
-rw-r--r--src/test/ui/traits/issue-33140.rs (renamed from src/test/ui/issues/issue-33140.rs)0
-rw-r--r--src/test/ui/traits/issue-33140.stderr (renamed from src/test/ui/issues/issue-33140.stderr)0
-rw-r--r--src/test/ui/traits/object/issue-33140-traitobject-crate.rs (renamed from src/test/ui/issues/issue-33140-traitobject-crate.rs)0
-rw-r--r--src/test/ui/traits/object/issue-33140-traitobject-crate.stderr (renamed from src/test/ui/issues/issue-33140-traitobject-crate.stderr)0
-rw-r--r--src/test/ui/try-block/try-block.rs (renamed from src/test/ui/try-block.rs)0
-rw-r--r--src/test/ui/tuple/tup.rs (renamed from src/test/ui/tup.rs)0
-rw-r--r--src/test/ui/typeck/issue-79040.rs5
-rw-r--r--src/test/ui/typeck/issue-79040.stderr19
-rw-r--r--src/test/ui/unboxed-closures/issue-18661.rs (renamed from src/test/ui/issues/issue-18661.rs)0
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
58 files changed, 248 insertions, 196 deletions
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index d3b88c019f0..611117788da 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -217,13 +217,13 @@ target | std | host | notes
 `thumbv4t-none-eabi` | * |  | ARMv4T T32
 `x86_64-apple-ios-macabi` | ✓ |  | Apple Catalyst on x86_64
 `x86_64-apple-tvos` | * | | x86 64-bit tvOS
-`x86_64-linux-kernel` | * |  | Linux kernel modules
+`x86_64-unknown-none-linuxkernel` | * |  | Linux kernel modules
 `x86_64-sun-solaris` | ? |  | Deprecated target for 64-bit Solaris 10/11, illumos
 `x86_64-pc-windows-msvc` | ✓ |  | 64-bit Windows XP support
 `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD
 `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku
 `x86_64-unknown-hermit` | ? |  |
-`x86_64-unknown-hermit-kernel` | ? |  | HermitCore kernel
+`x86_64-unknown-none-hermitkernel` | ? |  | HermitCore kernel
 `x86_64-unknown-l4re-uclibc` | ? |  |
 `x86_64-unknown-openbsd` | ✓ | ✓ | 64-bit OpenBSD
 `x86_64-unknown-uefi` | ? |  |
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index e560843383e..a94ee918c24 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1615,24 +1615,6 @@ impl PrimitiveType {
         CELL.get_or_init(move || {
             use self::PrimitiveType::*;
 
-            /// A macro to create a FxHashMap.
-            ///
-            /// Example:
-            ///
-            /// ```
-            /// let letters = map!{"a" => "b", "c" => "d"};
-            /// ```
-            ///
-            /// Trailing commas are allowed.
-            /// Commas between elements are required (even if the expression is a block).
-            macro_rules! map {
-                ($( $key: expr => $val: expr ),* $(,)*) => {{
-                    let mut map = ::rustc_data_structures::fx::FxHashMap::default();
-                    $( map.insert($key, $val); )*
-                    map
-                }}
-            }
-
             let single = |a: Option<DefId>| a.into_iter().collect();
             let both = |a: Option<DefId>, b: Option<DefId>| -> ArrayVec<_> {
                 a.into_iter().chain(b).collect()
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index de6942968ea..ecb6378f31f 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -315,6 +315,13 @@ impl Options {
             return Err(0);
         }
 
+        if matches.opt_strs("print").iter().any(|opt| opt == "unversioned-files") {
+            for file in crate::html::render::FILES_UNVERSIONED.keys() {
+                println!("{}", file);
+            }
+            return Err(0);
+        }
+
         let color = config::parse_color(&matches);
         let (json_rendered, _artifacts) = config::parse_json(&matches);
         let error_format = config::parse_error_format(&matches, color, json_rendered);
@@ -658,9 +665,8 @@ fn check_deprecated_options(matches: &getopts::Matches, diag: &rustc_errors::Han
             {
                 continue;
             }
-            let mut err =
-                diag.struct_warn(&format!("the '{}' flag is considered deprecated", flag));
-            err.warn(
+            let mut err = diag.struct_warn(&format!("the `{}` flag is deprecated", flag));
+            err.note(
                 "see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \
                  for more information",
             );
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 9cb0649b314..e9c32396e84 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -22,7 +22,7 @@ use rustc_session::DiagnosticOutput;
 use rustc_session::Session;
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
-use rustc_span::DUMMY_SP;
+use rustc_span::{Span, DUMMY_SP};
 
 use std::cell::RefCell;
 use std::collections::hash_map::Entry;
@@ -76,7 +76,7 @@ crate struct DocContext<'tcx> {
     ///
     /// See `collect_intra_doc_links::traits_implemented_by` for more details.
     /// `map<module, set<trait>>`
-    crate module_trait_cache: RefCell<FxHashMap<DefId, FxHashSet<DefId>>>,
+    crate module_trait_cache: FxHashMap<DefId, FxHashSet<DefId>>,
     /// This same cache is used throughout rustdoc, including in [`crate::html::render`].
     crate cache: Cache,
     /// Used by [`clean::inline`] to tell if an item has already been inlined.
@@ -169,13 +169,13 @@ impl<'tcx> DocContext<'tcx> {
 
     /// Like `hir().local_def_id_to_hir_id()`, but skips calling it on fake DefIds.
     /// (This avoids a slice-index-out-of-bounds panic.)
-    crate fn as_local_hir_id(&self, def_id: DefId) -> Option<HirId> {
+    crate fn as_local_hir_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<HirId> {
         if MAX_DEF_IDX.with(|m| {
             m.borrow().get(&def_id.krate).map(|&idx| idx <= def_id.index).unwrap_or(false)
         }) {
             None
         } else {
-            def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
+            def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
         }
     }
 }
@@ -389,7 +389,7 @@ crate fn run_global_ctxt(
     tcx: TyCtxt<'_>,
     resolver: Rc<RefCell<interface::BoxedResolver>>,
     mut default_passes: passes::DefaultPassOption,
-    mut manual_passes: Vec<String>,
+    manual_passes: Vec<String>,
     render_options: RenderOptions,
     output_format: OutputFormat,
 ) -> (clean::Crate, RenderOptions, Cache) {
@@ -450,7 +450,7 @@ crate fn run_global_ctxt(
             .cloned()
             .filter(|trait_def_id| tcx.trait_is_auto(*trait_def_id))
             .collect(),
-        module_trait_cache: RefCell::new(FxHashMap::default()),
+        module_trait_cache: FxHashMap::default(),
         cache: Cache::new(access_levels, render_options.document_private),
         inlined: FxHashSet::default(),
         output_format,
@@ -479,7 +479,7 @@ crate fn run_global_ctxt(
                 https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html";
             tcx.struct_lint_node(
                 crate::lint::MISSING_CRATE_LEVEL_DOCS,
-                ctxt.as_local_hir_id(m.def_id).unwrap(),
+                DocContext::as_local_hir_id(tcx, m.def_id).unwrap(),
                 |lint| {
                     let mut diag =
                         lint.build("no documentation found for this crate's top-level module");
@@ -490,21 +490,44 @@ crate fn run_global_ctxt(
         }
     }
 
-    fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler) {
-        let mut msg = diag
-            .struct_warn(&format!("the `#![doc({})]` attribute is considered deprecated", name));
-        msg.warn(
+    fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler, sp: Span) {
+        let mut msg =
+            diag.struct_span_warn(sp, &format!("the `#![doc({})]` attribute is deprecated", name));
+        msg.note(
             "see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \
              for more information",
         );
 
         if name == "no_default_passes" {
             msg.help("you may want to use `#![doc(document_private_items)]`");
+        } else if name.starts_with("plugins") {
+            msg.warn("`#![doc(plugins = \"...\")]` no longer functions; see CVE-2018-1000622 <https://nvd.nist.gov/vuln/detail/CVE-2018-1000622>");
         }
 
         msg.emit();
     }
 
+    let parse_pass = |name: &str, sp: Option<Span>| {
+        if let Some(pass) = passes::find_pass(name) {
+            Some(ConditionalPass::always(pass))
+        } else {
+            let msg = &format!("ignoring unknown pass `{}`", name);
+            let mut warning = if let Some(sp) = sp {
+                tcx.sess.struct_span_warn(sp, msg)
+            } else {
+                tcx.sess.struct_warn(msg)
+            };
+            if name == "collapse-docs" {
+                warning.note("the `collapse-docs` pass was removed in #80261 <https://github.com/rust-lang/rust/pull/80261>");
+            }
+            warning.emit();
+            None
+        }
+    };
+
+    let mut manual_passes: Vec<_> =
+        manual_passes.into_iter().flat_map(|name| parse_pass(&name, None)).collect();
+
     // Process all of the crate attributes, extracting plugin metadata along
     // with the passes which we are supposed to run.
     for attr in krate.module.as_ref().unwrap().attrs.lists(sym::doc) {
@@ -513,29 +536,25 @@ crate fn run_global_ctxt(
         let name = attr.name_or_empty();
         if attr.is_word() {
             if name == sym::no_default_passes {
-                report_deprecated_attr("no_default_passes", diag);
+                report_deprecated_attr("no_default_passes", diag, attr.span());
                 if default_passes == passes::DefaultPassOption::Default {
                     default_passes = passes::DefaultPassOption::None;
                 }
             }
         } else if let Some(value) = attr.value_str() {
-            let sink = match name {
+            match name {
                 sym::passes => {
-                    report_deprecated_attr("passes = \"...\"", diag);
-                    &mut manual_passes
+                    report_deprecated_attr("passes = \"...\"", diag, attr.span());
                 }
                 sym::plugins => {
-                    report_deprecated_attr("plugins = \"...\"", diag);
-                    eprintln!(
-                        "WARNING: `#![doc(plugins = \"...\")]` \
-                         no longer functions; see CVE-2018-1000622"
-                    );
+                    report_deprecated_attr("plugins = \"...\"", diag, attr.span());
                     continue;
                 }
                 _ => continue,
             };
             for name in value.as_str().split_whitespace() {
-                sink.push(name.to_string());
+                let span = attr.name_value_literal_span().unwrap_or(attr.span());
+                manual_passes.extend(parse_pass(name, Some(span)));
             }
         }
 
@@ -544,17 +563,7 @@ crate fn run_global_ctxt(
         }
     }
 
-    let passes = passes::defaults(default_passes).iter().copied().chain(
-        manual_passes.into_iter().flat_map(|name| {
-            if let Some(pass) = passes::find_pass(&name) {
-                Some(ConditionalPass::always(pass))
-            } else {
-                error!("unknown pass {}, skipping", name);
-                None
-            }
-        }),
-    );
-
+    let passes = passes::defaults(default_passes).iter().copied().chain(manual_passes);
     info!("Executing passes");
 
     for p in passes {
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 50cae50c2c3..9b9ec2581cf 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -33,6 +33,7 @@ mod print_item;
 mod write_shared;
 
 crate use context::*;
+crate use write_shared::FILES_UNVERSIONED;
 
 use std::cell::{Cell, RefCell};
 use std::collections::VecDeque;
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index cbf0f9a4927..02ad01aa29a 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -3,6 +3,7 @@ use std::fmt::Write;
 use std::fs::{self, File};
 use std::io::prelude::*;
 use std::io::{self, BufReader};
+use std::lazy::SyncLazy as Lazy;
 use std::path::{Component, Path, PathBuf};
 
 use itertools::Itertools;
@@ -18,6 +19,26 @@ use crate::error::Error;
 use crate::formats::FormatRenderer;
 use crate::html::{layout, static_files};
 
+crate static FILES_UNVERSIONED: Lazy<FxHashMap<&str, &[u8]>> = Lazy::new(|| {
+    map! {
+        "FiraSans-Regular.woff2" => static_files::fira_sans::REGULAR2,
+        "FiraSans-Medium.woff2" => static_files::fira_sans::MEDIUM2,
+        "FiraSans-Regular.woff" => static_files::fira_sans::REGULAR,
+        "FiraSans-Medium.woff" => static_files::fira_sans::MEDIUM,
+        "FiraSans-LICENSE.txt" => static_files::fira_sans::LICENSE,
+        "SourceSerifPro-Regular.ttf.woff" => static_files::source_serif_pro::REGULAR,
+        "SourceSerifPro-Bold.ttf.woff" => static_files::source_serif_pro::BOLD,
+        "SourceSerifPro-It.ttf.woff" => static_files::source_serif_pro::ITALIC,
+        "SourceSerifPro-LICENSE.md" => static_files::source_serif_pro::LICENSE,
+        "SourceCodePro-Regular.woff" => static_files::source_code_pro::REGULAR,
+        "SourceCodePro-Semibold.woff" => static_files::source_code_pro::SEMIBOLD,
+        "SourceCodePro-LICENSE.txt" => static_files::source_code_pro::LICENSE,
+        "LICENSE-MIT.txt" => static_files::LICENSE_MIT,
+        "LICENSE-APACHE.txt" => static_files::LICENSE_APACHE,
+        "COPYRIGHT.txt" => static_files::COPYRIGHT,
+    }
+});
+
 pub(super) fn write_shared(
     cx: &Context<'_>,
     krate: &Crate,
@@ -212,21 +233,9 @@ themePicker.onblur = handleThemeButtonsBlur;
         static_files::NORMALIZE_CSS,
         options.enable_minification,
     )?;
-    write(cx.dst.join("FiraSans-Regular.woff2"), static_files::fira_sans::REGULAR2)?;
-    write(cx.dst.join("FiraSans-Medium.woff2"), static_files::fira_sans::MEDIUM2)?;
-    write(cx.dst.join("FiraSans-Regular.woff"), static_files::fira_sans::REGULAR)?;
-    write(cx.dst.join("FiraSans-Medium.woff"), static_files::fira_sans::MEDIUM)?;
-    write(cx.dst.join("FiraSans-LICENSE.txt"), static_files::fira_sans::LICENSE)?;
-    write(cx.dst.join("SourceSerifPro-Regular.ttf.woff"), static_files::source_serif_pro::REGULAR)?;
-    write(cx.dst.join("SourceSerifPro-Bold.ttf.woff"), static_files::source_serif_pro::BOLD)?;
-    write(cx.dst.join("SourceSerifPro-It.ttf.woff"), static_files::source_serif_pro::ITALIC)?;
-    write(cx.dst.join("SourceSerifPro-LICENSE.md"), static_files::source_serif_pro::LICENSE)?;
-    write(cx.dst.join("SourceCodePro-Regular.woff"), static_files::source_code_pro::REGULAR)?;
-    write(cx.dst.join("SourceCodePro-Semibold.woff"), static_files::source_code_pro::SEMIBOLD)?;
-    write(cx.dst.join("SourceCodePro-LICENSE.txt"), static_files::source_code_pro::LICENSE)?;
-    write(cx.dst.join("LICENSE-MIT.txt"), static_files::LICENSE_MIT)?;
-    write(cx.dst.join("LICENSE-APACHE.txt"), static_files::LICENSE_APACHE)?;
-    write(cx.dst.join("COPYRIGHT.txt"), static_files::COPYRIGHT)?;
+    for (file, contents) in &*FILES_UNVERSIONED {
+        write(cx.dst.join(file), contents)?;
+    }
 
     fn collect(path: &Path, krate: &str, key: &str) -> io::Result<(Vec<String>, Vec<String>)> {
         let mut ret = Vec::new();
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index e447b49c11a..9e843245442 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -71,6 +71,24 @@ use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGro
 use rustc_session::getopts;
 use rustc_session::{early_error, early_warn};
 
+/// A macro to create a FxHashMap.
+///
+/// Example:
+///
+/// ```
+/// let letters = map!{"a" => "b", "c" => "d"};
+/// ```
+///
+/// Trailing commas are allowed.
+/// Commas between elements are required (even if the expression is a block).
+macro_rules! map {
+    ($( $key: expr => $val: expr ),* $(,)*) => {{
+        let mut map = ::rustc_data_structures::fx::FxHashMap::default();
+        $( map.insert($key, $val); )*
+        map
+    }}
+}
+
 #[macro_use]
 mod externalfiles;
 
@@ -506,6 +524,9 @@ fn opts() -> Vec<RustcOptGroup> {
                 "Generate JSON file at the top level instead of generating HTML redirection files",
             )
         }),
+        unstable("print", |o| {
+            o.optmulti("", "print", "Rustdoc information to print on stdout", "[unversioned-files]")
+        }),
     ]
 }
 
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index c85490864ec..98886139f30 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -48,9 +48,12 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
         let buffer = buffer.borrow();
 
         if buffer.has_errors || is_empty {
-            let mut diag = if let Some(sp) =
-                super::source_span_for_markdown_range(self.cx, &dox, &code_block.range, &item.attrs)
-            {
+            let mut diag = if let Some(sp) = super::source_span_for_markdown_range(
+                self.cx.tcx,
+                &dox,
+                &code_block.range,
+                &item.attrs,
+            ) {
                 let (warning_message, suggest_using_text) = if buffer.has_errors {
                     ("could not parse code block as Rust code", true)
                 } else {
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 38efecb393b..ec5994b762b 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -484,13 +484,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
     /// Resolves a string as a path within a particular namespace. Returns an
     /// optional URL fragment in the case of variants and methods.
     fn resolve<'path>(
-        &self,
+        &mut self,
         path_str: &'path str,
         ns: Namespace,
         module_id: DefId,
         extra_fragment: &Option<String>,
     ) -> Result<(Res, Option<String>), ErrorKind<'path>> {
-        let cx = &self.cx;
+        let tcx = self.cx.tcx;
 
         if let Some(res) = self.resolve_path(path_str, ns, module_id) {
             match res {
@@ -498,7 +498,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                 // item a separate function.
                 Res::Def(DefKind::AssocFn | DefKind::AssocConst, _) => assert_eq!(ns, ValueNS),
                 Res::Def(DefKind::AssocTy, _) => assert_eq!(ns, TypeNS),
-                Res::Def(DefKind::Variant, _) => return handle_variant(cx, res, extra_fragment),
+                Res::Def(DefKind::Variant, _) => {
+                    return handle_variant(self.cx, res, extra_fragment);
+                }
                 // Not a trait item; just return what we found.
                 Res::Primitive(ty) => {
                     if extra_fragment.is_some() {
@@ -565,13 +567,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             ) => {
                 debug!("looking for associated item named {} for item {:?}", item_name, did);
                 // Checks if item_name belongs to `impl SomeItem`
-                let assoc_item = cx
-                    .tcx
+                let assoc_item = tcx
                     .inherent_impls(did)
                     .iter()
                     .flat_map(|&imp| {
-                        cx.tcx.associated_items(imp).find_by_name_and_namespace(
-                            cx.tcx,
+                        tcx.associated_items(imp).find_by_name_and_namespace(
+                            tcx,
                             Ident::with_dummy_span(item_name),
                             ns,
                             imp,
@@ -587,7 +588,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                     // something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
                     .or_else(|| {
                         let kind =
-                            resolve_associated_trait_item(did, module_id, item_name, ns, &self.cx);
+                            resolve_associated_trait_item(did, module_id, item_name, ns, self.cx);
                         debug!("got associated item kind {:?}", kind);
                         kind
                     });
@@ -611,7 +612,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                     debug!("looking for variants or fields named {} for {:?}", item_name, did);
                     // FIXME(jynelson): why is this different from
                     // `variant_field`?
-                    match cx.tcx.type_of(did).kind() {
+                    match tcx.type_of(did).kind() {
                         ty::Adt(def, _) => {
                             let field = if def.is_enum() {
                                 def.all_fields().find(|item| item.ident.name == item_name)
@@ -652,10 +653,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                     None
                 }
             }
-            Res::Def(DefKind::Trait, did) => cx
-                .tcx
+            Res::Def(DefKind::Trait, did) => tcx
                 .associated_items(did)
-                .find_by_name_and_namespace(cx.tcx, Ident::with_dummy_span(item_name), ns, did)
+                .find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, did)
                 .map(|item| {
                     let kind = match item.kind {
                         ty::AssocKind::Const => "associatedconstant",
@@ -699,7 +699,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
     /// This returns the `Res` even if it was erroneous for some reason
     /// (such as having invalid URL fragments or being in the wrong namespace).
     fn check_full_res(
-        &self,
+        &mut self,
         ns: Namespace,
         path_str: &str,
         module_id: DefId,
@@ -733,7 +733,7 @@ fn resolve_associated_trait_item(
     module: DefId,
     item_name: Symbol,
     ns: Namespace,
-    cx: &DocContext<'_>,
+    cx: &mut DocContext<'_>,
 ) -> Option<(ty::AssocKind, DefId)> {
     // FIXME: this should also consider blanket impls (`impl<T> X for T`). Unfortunately
     // `get_auto_trait_and_blanket_impls` is broken because the caching behavior is wrong. In the
@@ -758,10 +758,10 @@ fn resolve_associated_trait_item(
 ///
 /// NOTE: this cannot be a query because more traits could be available when more crates are compiled!
 /// So it is not stable to serialize cross-crate.
-fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> FxHashSet<DefId> {
-    let mut cache = cx.module_trait_cache.borrow_mut();
-    let in_scope_traits = cache.entry(module).or_insert_with(|| {
-        cx.enter_resolver(|resolver| {
+fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -> FxHashSet<DefId> {
+    let mut resolver = cx.resolver.borrow_mut();
+    let in_scope_traits = cx.module_trait_cache.entry(module).or_insert_with(|| {
+        resolver.access(|resolver| {
             let parent_scope = &ParentScope::module(resolver.get_module(module), resolver);
             resolver
                 .traits_in_scope(None, parent_scope, SyntaxContext::root(), None)
@@ -771,13 +771,14 @@ fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> Fx
         })
     });
 
-    let ty = cx.tcx.type_of(type_);
+    let tcx = cx.tcx;
+    let ty = tcx.type_of(type_);
     let iter = in_scope_traits.iter().flat_map(|&trait_| {
         trace!("considering explicit impl for trait {:?}", trait_);
 
         // Look at each trait implementation to see if it's an impl for `did`
-        cx.tcx.find_map_relevant_impl(trait_, ty, |impl_| {
-            let trait_ref = cx.tcx.impl_trait_ref(impl_).expect("this is not an inherent impl");
+        tcx.find_map_relevant_impl(trait_, ty, |impl_| {
+            let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl");
             // Check if these are the same type.
             let impl_type = trait_ref.self_ty();
             trace!(
@@ -1146,7 +1147,7 @@ impl LinkCollector<'_, '_> {
                 suggest_disambiguator(resolved, diag, path_str, dox, sp, &ori_link.range);
             };
             report_diagnostic(
-                self.cx,
+                self.cx.tcx,
                 BROKEN_INTRA_DOC_LINKS,
                 &msg,
                 &item,
@@ -1220,7 +1221,7 @@ impl LinkCollector<'_, '_> {
                         && !self.cx.tcx.features().intra_doc_pointers
                     {
                         let span = super::source_span_for_markdown_range(
-                            self.cx,
+                            self.cx.tcx,
                             dox,
                             &ori_link.range,
                             &item.attrs,
@@ -1308,7 +1309,7 @@ impl LinkCollector<'_, '_> {
     /// After parsing the disambiguator, resolve the main part of the link.
     // FIXME(jynelson): wow this is just so much
     fn resolve_with_disambiguator(
-        &self,
+        &mut self,
         key: &ResolutionInfo,
         diag: DiagnosticInfo<'_>,
     ) -> Option<(Res, Option<String>)> {
@@ -1674,7 +1675,7 @@ impl Suggestion {
 /// parameter of the callback will contain it, and the primary span of the diagnostic will be set
 /// to it.
 fn report_diagnostic(
-    cx: &DocContext<'_>,
+    tcx: TyCtxt<'_>,
     lint: &'static Lint,
     msg: &str,
     item: &Item,
@@ -1682,7 +1683,7 @@ fn report_diagnostic(
     link_range: &Range<usize>,
     decorate: impl FnOnce(&mut DiagnosticBuilder<'_>, Option<rustc_span::Span>),
 ) {
-    let hir_id = match cx.as_local_hir_id(item.def_id) {
+    let hir_id = match DocContext::as_local_hir_id(tcx, item.def_id) {
         Some(hir_id) => hir_id,
         None => {
             // If non-local, no need to check anything.
@@ -1694,10 +1695,10 @@ fn report_diagnostic(
     let attrs = &item.attrs;
     let sp = span_of_attrs(attrs).unwrap_or(item.source.span());
 
-    cx.tcx.struct_span_lint_hir(lint, hir_id, sp, |lint| {
+    tcx.struct_span_lint_hir(lint, hir_id, sp, |lint| {
         let mut diag = lint.build(msg);
 
-        let span = super::source_span_for_markdown_range(cx, dox, link_range, attrs);
+        let span = super::source_span_for_markdown_range(tcx, dox, link_range, attrs);
 
         if let Some(sp) = span {
             diag.set_span(sp);
@@ -1732,7 +1733,7 @@ fn report_diagnostic(
 /// handled earlier. For example, if passed `Item::Crate(std)` and `path_str`
 /// `std::io::Error::x`, this will resolve `std::io::Error`.
 fn resolution_failure(
-    collector: &LinkCollector<'_, '_>,
+    collector: &mut LinkCollector<'_, '_>,
     item: &Item,
     path_str: &str,
     disambiguator: Option<Disambiguator>,
@@ -1742,7 +1743,7 @@ fn resolution_failure(
 ) {
     let tcx = collector.cx.tcx;
     report_diagnostic(
-        collector.cx,
+        tcx,
         BROKEN_INTRA_DOC_LINKS,
         &format!("unresolved link to `{}`", path_str),
         item,
@@ -1973,7 +1974,7 @@ fn anchor_failure(
         ),
     };
 
-    report_diagnostic(cx, BROKEN_INTRA_DOC_LINKS, &msg, item, dox, &link_range, |diag, sp| {
+    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, item, dox, &link_range, |diag, sp| {
         if let Some(sp) = sp {
             diag.span_label(sp, "contains invalid anchor");
         }
@@ -2013,7 +2014,7 @@ fn ambiguity_error(
         }
     }
 
-    report_diagnostic(cx, BROKEN_INTRA_DOC_LINKS, &msg, item, dox, &link_range, |diag, sp| {
+    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, item, dox, &link_range, |diag, sp| {
         if let Some(sp) = sp {
             diag.span_label(sp, "ambiguous link");
         } else {
@@ -2066,7 +2067,7 @@ fn privacy_error(cx: &DocContext<'_>, item: &Item, path_str: &str, dox: &str, li
     let msg =
         format!("public documentation for `{}` links to private item `{}`", item_name, path_str);
 
-    report_diagnostic(cx, PRIVATE_INTRA_DOC_LINKS, &msg, item, dox, &link.range, |diag, sp| {
+    report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, &msg, item, dox, &link.range, |diag, sp| {
         if let Some(sp) = sp {
             diag.span_label(sp, "this item is private");
         }
diff --git a/src/librustdoc/passes/doc_test_lints.rs b/src/librustdoc/passes/doc_test_lints.rs
index 2fa9179515d..951258db9e2 100644
--- a/src/librustdoc/passes/doc_test_lints.rs
+++ b/src/librustdoc/passes/doc_test_lints.rs
@@ -82,7 +82,7 @@ crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> boo
 }
 
 crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
-    let hir_id = match cx.as_local_hir_id(item.def_id) {
+    let hir_id = match DocContext::as_local_hir_id(cx.tcx, item.def_id) {
         Some(hir_id) => hir_id,
         None => {
             // If non-local, no need to check anything.
diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs
index 27e669aa44f..23364b6fec9 100644
--- a/src/librustdoc/passes/html_tags.rs
+++ b/src/librustdoc/passes/html_tags.rs
@@ -167,7 +167,8 @@ fn extract_tags(
 
 impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> {
     fn fold_item(&mut self, item: Item) -> Option<Item> {
-        let hir_id = match self.cx.as_local_hir_id(item.def_id) {
+        let tcx = self.cx.tcx;
+        let hir_id = match DocContext::as_local_hir_id(tcx, item.def_id) {
             Some(hir_id) => hir_id,
             None => {
                 // If non-local, no need to check anything.
@@ -176,13 +177,13 @@ impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> {
         };
         let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
         if !dox.is_empty() {
-            let cx = &self.cx;
             let report_diag = |msg: &str, range: &Range<usize>| {
-                let sp = match super::source_span_for_markdown_range(cx, &dox, range, &item.attrs) {
+                let sp = match super::source_span_for_markdown_range(tcx, &dox, range, &item.attrs)
+                {
                     Some(sp) => sp,
                     None => span_of_attrs(&item.attrs).unwrap_or(item.source.span()),
                 };
-                cx.tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| {
+                tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| {
                     lint.build(msg).emit()
                 });
             };
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 5813732facb..4c639c8496d 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -1,6 +1,7 @@
 //! Contains information about "passes", used to modify crate information during the documentation
 //! process.
 
+use rustc_middle::ty::TyCtxt;
 use rustc_span::{InnerSpan, Span, DUMMY_SP};
 use std::ops::Range;
 
@@ -167,7 +168,7 @@ crate fn span_of_attrs(attrs: &clean::Attributes) -> Option<Span> {
 /// attributes are not all sugared doc comments. It's difficult to calculate the correct span in
 /// that case due to escaping and other source features.
 crate fn source_span_for_markdown_range(
-    cx: &DocContext<'_>,
+    tcx: TyCtxt<'_>,
     markdown: &str,
     md_range: &Range<usize>,
     attrs: &clean::Attributes,
@@ -179,7 +180,7 @@ crate fn source_span_for_markdown_range(
         return None;
     }
 
-    let snippet = cx.sess().source_map().span_to_snippet(span_of_attrs(attrs)?).ok()?;
+    let snippet = tcx.sess.source_map().span_to_snippet(span_of_attrs(attrs)?).ok()?;
 
     let starting_line = markdown[..md_range.start].matches('\n').count();
     let ending_line = starting_line + markdown[md_range.start..md_range.end].matches('\n').count();
diff --git a/src/librustdoc/passes/non_autolinks.rs b/src/librustdoc/passes/non_autolinks.rs
index 09a1959fa11..16ad940c627 100644
--- a/src/librustdoc/passes/non_autolinks.rs
+++ b/src/librustdoc/passes/non_autolinks.rs
@@ -60,7 +60,7 @@ crate fn check_non_autolinks(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
 
 impl<'a, 'tcx> DocFolder for NonAutolinksLinter<'a, 'tcx> {
     fn fold_item(&mut self, item: Item) -> Option<Item> {
-        let hir_id = match self.cx.as_local_hir_id(item.def_id) {
+        let hir_id = match DocContext::as_local_hir_id(self.cx.tcx, item.def_id) {
             Some(hir_id) => hir_id,
             None => {
                 // If non-local, no need to check anything.
@@ -70,7 +70,7 @@ impl<'a, 'tcx> DocFolder for NonAutolinksLinter<'a, 'tcx> {
         let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
         if !dox.is_empty() {
             let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| {
-                let sp = super::source_span_for_markdown_range(cx, &dox, &range, &item.attrs)
+                let sp = super::source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
                     .or_else(|| span_of_attrs(&item.attrs))
                     .unwrap_or(item.source.span());
                 cx.tcx.struct_span_lint_hir(crate::lint::NON_AUTOLINKS, hir_id, sp, |lint| {
diff --git a/src/test/run-make-fulldeps/print-unversioned-files/Makefile b/src/test/run-make-fulldeps/print-unversioned-files/Makefile
new file mode 100644
index 00000000000..e368f61cddf
--- /dev/null
+++ b/src/test/run-make-fulldeps/print-unversioned-files/Makefile
@@ -0,0 +1,4 @@
+-include ../tools.mk
+
+all:
+	$(RUSTDOC) -Z unstable-options --print unversioned-files | sort | diff - unversioned-files.txt
diff --git a/src/test/run-make-fulldeps/print-unversioned-files/unversioned-files.txt b/src/test/run-make-fulldeps/print-unversioned-files/unversioned-files.txt
new file mode 100644
index 00000000000..c5a9bf24381
--- /dev/null
+++ b/src/test/run-make-fulldeps/print-unversioned-files/unversioned-files.txt
@@ -0,0 +1,15 @@
+COPYRIGHT.txt
+FiraSans-LICENSE.txt
+FiraSans-Medium.woff
+FiraSans-Medium.woff2
+FiraSans-Regular.woff
+FiraSans-Regular.woff2
+LICENSE-APACHE.txt
+LICENSE-MIT.txt
+SourceCodePro-LICENSE.txt
+SourceCodePro-Regular.woff
+SourceCodePro-Semibold.woff
+SourceSerifPro-Bold.ttf.woff
+SourceSerifPro-It.ttf.woff
+SourceSerifPro-LICENSE.md
+SourceSerifPro-Regular.ttf.woff
diff --git a/src/test/rustdoc-ui/deprecated-attrs.rs b/src/test/rustdoc-ui/deprecated-attrs.rs
index ca626afbe53..5febc5eb9cd 100644
--- a/src/test/rustdoc-ui/deprecated-attrs.rs
+++ b/src/test/rustdoc-ui/deprecated-attrs.rs
@@ -1,7 +1,17 @@
 // check-pass
+// compile-flags: --passes unknown-pass
+// error-pattern: ignoring unknown pass `unknown-pass`
 
-#![doc(no_default_passes, passes = "unindent-comments")]
-
-struct SomeStruct;
-
-pub struct OtherStruct;
+#![doc(no_default_passes)]
+//~^ WARNING attribute is deprecated
+//~| NOTE see issue #44136
+//~| HELP use `#![doc(document_private_items)]`
+#![doc(passes = "collapse-docs unindent-comments")]
+//~^ WARNING attribute is deprecated
+//~| NOTE see issue #44136
+//~| WARNING ignoring unknown pass
+//~| NOTE `collapse-docs` pass was removed
+#![doc(plugins = "xxx")]
+//~^ WARNING attribute is deprecated
+//~| NOTE see issue #44136
+//~| WARNING no longer functions; see CVE
diff --git a/src/test/rustdoc-ui/deprecated-attrs.stderr b/src/test/rustdoc-ui/deprecated-attrs.stderr
index f68fb467448..b855cedf522 100644
--- a/src/test/rustdoc-ui/deprecated-attrs.stderr
+++ b/src/test/rustdoc-ui/deprecated-attrs.stderr
@@ -1,11 +1,42 @@
-warning: the `#![doc(no_default_passes)]` attribute is considered deprecated
+warning: the `passes` flag is deprecated
    |
-   = warning: see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information
+   = note: see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information
+
+warning: ignoring unknown pass `unknown-pass`
+
+warning: the `#![doc(no_default_passes)]` attribute is deprecated
+  --> $DIR/deprecated-attrs.rs:5:8
+   |
+LL | #![doc(no_default_passes)]
+   |        ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information
    = help: you may want to use `#![doc(document_private_items)]`
 
-warning: the `#![doc(passes = "...")]` attribute is considered deprecated
+warning: the `#![doc(passes = "...")]` attribute is deprecated
+  --> $DIR/deprecated-attrs.rs:9:8
+   |
+LL | #![doc(passes = "collapse-docs unindent-comments")]
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information
+
+warning: ignoring unknown pass `collapse-docs`
+  --> $DIR/deprecated-attrs.rs:9:17
+   |
+LL | #![doc(passes = "collapse-docs unindent-comments")]
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `collapse-docs` pass was removed in #80261 <https://github.com/rust-lang/rust/pull/80261>
+
+warning: the `#![doc(plugins = "...")]` attribute is deprecated
+  --> $DIR/deprecated-attrs.rs:14:8
+   |
+LL | #![doc(plugins = "xxx")]
+   |        ^^^^^^^^^^^^^^^
    |
-   = warning: see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information
+   = note: see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information
+   = warning: `#![doc(plugins = "...")]` no longer functions; see CVE-2018-1000622 <https://nvd.nist.gov/vuln/detail/CVE-2018-1000622>
 
-warning: 2 warnings emitted
+warning: 5 warnings emitted
 
diff --git a/src/test/ui/nullable-pointer-ffi-compat.rs b/src/test/ui/abi/nullable-pointer-ffi-compat.rs
index 0647a18c3c4..0647a18c3c4 100644
--- a/src/test/ui/nullable-pointer-ffi-compat.rs
+++ b/src/test/ui/abi/nullable-pointer-ffi-compat.rs
diff --git a/src/test/ui/issues/issue-76179.rs b/src/test/ui/associated-types/issue-76179.rs
index 0e086968b90..0e086968b90 100644
--- a/src/test/ui/issues/issue-76179.rs
+++ b/src/test/ui/associated-types/issue-76179.rs
diff --git a/src/test/ui/issue-74047.rs b/src/test/ui/async-await/issue-74047.rs
index 2e4f3e675c3..2e4f3e675c3 100644
--- a/src/test/ui/issue-74047.rs
+++ b/src/test/ui/async-await/issue-74047.rs
diff --git a/src/test/ui/issue-74047.stderr b/src/test/ui/async-await/issue-74047.stderr
index 28174825d8b..28174825d8b 100644
--- a/src/test/ui/issue-74047.stderr
+++ b/src/test/ui/async-await/issue-74047.stderr
diff --git a/src/test/ui/issues/issue-42344.rs b/src/test/ui/borrowck/issue-42344.rs
index a7636edf2f8..a7636edf2f8 100644
--- a/src/test/ui/issues/issue-42344.rs
+++ b/src/test/ui/borrowck/issue-42344.rs
diff --git a/src/test/ui/issues/issue-42344.stderr b/src/test/ui/borrowck/issue-42344.stderr
index 5cffa1b5121..5cffa1b5121 100644
--- a/src/test/ui/issues/issue-42344.stderr
+++ b/src/test/ui/borrowck/issue-42344.stderr
diff --git a/src/test/ui/issues/auxiliary/issue-17718-aux.rs b/src/test/ui/consts/auxiliary/issue-17718-aux.rs
index 91abdbff868..91abdbff868 100644
--- a/src/test/ui/issues/auxiliary/issue-17718-aux.rs
+++ b/src/test/ui/consts/auxiliary/issue-17718-aux.rs
diff --git a/src/test/ui/issues/issue-17718.rs b/src/test/ui/consts/issue-17718.rs
index c6341d80844..c6341d80844 100644
--- a/src/test/ui/issues/issue-17718.rs
+++ b/src/test/ui/consts/issue-17718.rs
diff --git a/src/test/ui/issues/issue-3521.fixed b/src/test/ui/consts/issue-3521.fixed
index f76106dfff1..f76106dfff1 100644
--- a/src/test/ui/issues/issue-3521.fixed
+++ b/src/test/ui/consts/issue-3521.fixed
diff --git a/src/test/ui/issues/issue-3521.rs b/src/test/ui/consts/issue-3521.rs
index c425a22df91..c425a22df91 100644
--- a/src/test/ui/issues/issue-3521.rs
+++ b/src/test/ui/consts/issue-3521.rs
diff --git a/src/test/ui/issues/issue-3521.stderr b/src/test/ui/consts/issue-3521.stderr
index aa42772f12d..aa42772f12d 100644
--- a/src/test/ui/issues/issue-3521.stderr
+++ b/src/test/ui/consts/issue-3521.stderr
diff --git a/src/test/ui/issues/issue-2633-2.rs b/src/test/ui/issues/issue-2633-2.rs
deleted file mode 100644
index 02c1a166301..00000000000
--- a/src/test/ui/issues/issue-2633-2.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-pass
-// pretty-expanded FIXME #23616
-
-#![feature(box_syntax)]
-
-
-fn a_val(x: Box<isize>, y: Box<isize>) -> isize {
-    *x + *y
-}
-
-pub fn main() {
-    let z: Box<_> = box 22;
-    a_val(z.clone(), z.clone());
-}
diff --git a/src/test/ui/issues/issue-2633.rs b/src/test/ui/issues/issue-2633.rs
deleted file mode 100644
index 7e8cea75fc8..00000000000
--- a/src/test/ui/issues/issue-2633.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
-
-#[derive(Copy, Clone)]
-struct cat {
-    meow: extern "Rust" fn(),
-}
-
-fn meow() {
-    println!("meow")
-}
-
-fn cat() -> cat {
-    cat {
-        meow: meow,
-    }
-}
-
-#[derive(Copy, Clone)]
-struct KittyInfo {kitty: cat}
-
-// Code compiles and runs successfully if we add a + before the first arg
-fn nyan(kitty: cat, _kitty_info: KittyInfo) {
-    (kitty.meow)();
-}
-
-pub fn main() {
-    let kitty = cat();
-    nyan(kitty, KittyInfo {kitty: kitty});
-}
diff --git a/src/test/ui/lint-expr-stmt-attrs-for-early-lints.rs b/src/test/ui/lint/lint-expr-stmt-attrs-for-early-lints.rs
index 07a32904a5e..07a32904a5e 100644
--- a/src/test/ui/lint-expr-stmt-attrs-for-early-lints.rs
+++ b/src/test/ui/lint/lint-expr-stmt-attrs-for-early-lints.rs
diff --git a/src/test/ui/issues/issue-52992.rs b/src/test/ui/nll/issue-52992.rs
index 530d1a61b31..530d1a61b31 100644
--- a/src/test/ui/issues/issue-52992.rs
+++ b/src/test/ui/nll/issue-52992.rs
diff --git a/src/test/ui/issues/issue-7222.rs b/src/test/ui/parser/issue-7222.rs
index 64907316626..64907316626 100644
--- a/src/test/ui/issues/issue-7222.rs
+++ b/src/test/ui/parser/issue-7222.rs
diff --git a/src/test/ui/parser/item-free-const-no-body-semantic-fail.rs b/src/test/ui/parser/item-free-const-no-body-semantic-fail.rs
index 613b3c98561..15a15a207b1 100644
--- a/src/test/ui/parser/item-free-const-no-body-semantic-fail.rs
+++ b/src/test/ui/parser/item-free-const-no-body-semantic-fail.rs
@@ -4,4 +4,3 @@ fn main() {}
 
 const A: u8; //~ ERROR free constant item without body
 const B; //~ ERROR free constant item without body
-//~^ ERROR missing type for `const` item
diff --git a/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr b/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr
index 4e97229fa1a..aa75e5cee01 100644
--- a/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr
+++ b/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr
@@ -14,11 +14,5 @@ LL | const B;
    |        |
    |        help: provide a definition for the constant: `= <expr>;`
 
-error: missing type for `const` item
-  --> $DIR/item-free-const-no-body-semantic-fail.rs:6:7
-   |
-LL | const B;
-   |       ^ help: provide a type for the item: `B: [type error]`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/item-free-static-no-body-semantic-fail.rs b/src/test/ui/parser/item-free-static-no-body-semantic-fail.rs
index 780479e3d26..61d3eab24d8 100644
--- a/src/test/ui/parser/item-free-static-no-body-semantic-fail.rs
+++ b/src/test/ui/parser/item-free-static-no-body-semantic-fail.rs
@@ -4,8 +4,6 @@ fn main() {}
 
 static A: u8; //~ ERROR free static item without body
 static B; //~ ERROR free static item without body
-//~^ ERROR missing type for `static` item
 
 static mut C: u8; //~ ERROR free static item without body
 static mut D; //~ ERROR free static item without body
-//~^ ERROR missing type for `static mut` item
diff --git a/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr b/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr
index 60b7bb34c69..7b408323674 100644
--- a/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr
+++ b/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr
@@ -15,7 +15,7 @@ LL | static B;
    |         help: provide a definition for the static: `= <expr>;`
 
 error: free static item without body
-  --> $DIR/item-free-static-no-body-semantic-fail.rs:9:1
+  --> $DIR/item-free-static-no-body-semantic-fail.rs:8:1
    |
 LL | static mut C: u8;
    | ^^^^^^^^^^^^^^^^-
@@ -23,24 +23,12 @@ LL | static mut C: u8;
    |                 help: provide a definition for the static: `= <expr>;`
 
 error: free static item without body
-  --> $DIR/item-free-static-no-body-semantic-fail.rs:10:1
+  --> $DIR/item-free-static-no-body-semantic-fail.rs:9:1
    |
 LL | static mut D;
    | ^^^^^^^^^^^^-
    |             |
    |             help: provide a definition for the static: `= <expr>;`
 
-error: missing type for `static` item
-  --> $DIR/item-free-static-no-body-semantic-fail.rs:6:8
-   |
-LL | static B;
-   |        ^ help: provide a type for the item: `B: [type error]`
-
-error: missing type for `static mut` item
-  --> $DIR/item-free-static-no-body-semantic-fail.rs:10:12
-   |
-LL | static mut D;
-   |            ^ help: provide a type for the item: `D: [type error]`
-
-error: aborting due to 6 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issue-6157.rs b/src/test/ui/regions/issue-6157.rs
index b7a44ed8623..b7a44ed8623 100644
--- a/src/test/ui/issue-6157.rs
+++ b/src/test/ui/regions/issue-6157.rs
diff --git a/src/test/ui/issues/issue-2330.rs b/src/test/ui/resolve/issue-2330.rs
index 4560caba0cf..4560caba0cf 100644
--- a/src/test/ui/issues/issue-2330.rs
+++ b/src/test/ui/resolve/issue-2330.rs
diff --git a/src/test/ui/issues/issue-2330.stderr b/src/test/ui/resolve/issue-2330.stderr
index 877cf68b586..877cf68b586 100644
--- a/src/test/ui/issues/issue-2330.stderr
+++ b/src/test/ui/resolve/issue-2330.stderr
diff --git a/src/test/ui/issues/issue-15261.rs b/src/test/ui/statics/issue-15261.rs
index ec413f6d1d2..ec413f6d1d2 100644
--- a/src/test/ui/issues/issue-15261.rs
+++ b/src/test/ui/statics/issue-15261.rs
diff --git a/src/test/ui/issues/issue-44373-2.rs b/src/test/ui/statics/issue-44373-2.rs
index 194ce1dca77..194ce1dca77 100644
--- a/src/test/ui/issues/issue-44373-2.rs
+++ b/src/test/ui/statics/issue-44373-2.rs
diff --git a/src/test/ui/issues/issue-44373.rs b/src/test/ui/statics/issue-44373.rs
index 0d011d096bd..0d011d096bd 100644
--- a/src/test/ui/issues/issue-44373.rs
+++ b/src/test/ui/statics/issue-44373.rs
diff --git a/src/test/ui/issues/issue-44373.stderr b/src/test/ui/statics/issue-44373.stderr
index 6f92fbb1eb6..6f92fbb1eb6 100644
--- a/src/test/ui/issues/issue-44373.stderr
+++ b/src/test/ui/statics/issue-44373.stderr
diff --git a/src/test/ui/impl-bounds-checking.rs b/src/test/ui/traits/impl-bounds-checking.rs
index 5e65a27bf14..5e65a27bf14 100644
--- a/src/test/ui/impl-bounds-checking.rs
+++ b/src/test/ui/traits/impl-bounds-checking.rs
diff --git a/src/test/ui/impl-bounds-checking.stderr b/src/test/ui/traits/impl-bounds-checking.stderr
index 8698ed6e875..8698ed6e875 100644
--- a/src/test/ui/impl-bounds-checking.stderr
+++ b/src/test/ui/traits/impl-bounds-checking.stderr
diff --git a/src/test/ui/issues/issue-28576.rs b/src/test/ui/traits/issue-28576.rs
index 972c839b648..972c839b648 100644
--- a/src/test/ui/issues/issue-28576.rs
+++ b/src/test/ui/traits/issue-28576.rs
diff --git a/src/test/ui/issues/issue-28576.stderr b/src/test/ui/traits/issue-28576.stderr
index 203cd0630eb..203cd0630eb 100644
--- a/src/test/ui/issues/issue-28576.stderr
+++ b/src/test/ui/traits/issue-28576.stderr
diff --git a/src/test/ui/issues/issue-33140.rs b/src/test/ui/traits/issue-33140.rs
index 9bdac4b8375..9bdac4b8375 100644
--- a/src/test/ui/issues/issue-33140.rs
+++ b/src/test/ui/traits/issue-33140.rs
diff --git a/src/test/ui/issues/issue-33140.stderr b/src/test/ui/traits/issue-33140.stderr
index 9a900d2fc94..9a900d2fc94 100644
--- a/src/test/ui/issues/issue-33140.stderr
+++ b/src/test/ui/traits/issue-33140.stderr
diff --git a/src/test/ui/issues/issue-33140-traitobject-crate.rs b/src/test/ui/traits/object/issue-33140-traitobject-crate.rs
index 46b68f1c9fe..46b68f1c9fe 100644
--- a/src/test/ui/issues/issue-33140-traitobject-crate.rs
+++ b/src/test/ui/traits/object/issue-33140-traitobject-crate.rs
diff --git a/src/test/ui/issues/issue-33140-traitobject-crate.stderr b/src/test/ui/traits/object/issue-33140-traitobject-crate.stderr
index 781decb5ae2..781decb5ae2 100644
--- a/src/test/ui/issues/issue-33140-traitobject-crate.stderr
+++ b/src/test/ui/traits/object/issue-33140-traitobject-crate.stderr
diff --git a/src/test/ui/try-block.rs b/src/test/ui/try-block/try-block.rs
index c29ccc70427..c29ccc70427 100644
--- a/src/test/ui/try-block.rs
+++ b/src/test/ui/try-block/try-block.rs
diff --git a/src/test/ui/tup.rs b/src/test/ui/tuple/tup.rs
index 160477b0b0a..160477b0b0a 100644
--- a/src/test/ui/tup.rs
+++ b/src/test/ui/tuple/tup.rs
diff --git a/src/test/ui/typeck/issue-79040.rs b/src/test/ui/typeck/issue-79040.rs
new file mode 100644
index 00000000000..af2a9c1ba87
--- /dev/null
+++ b/src/test/ui/typeck/issue-79040.rs
@@ -0,0 +1,5 @@
+fn main() {
+    const FOO = "hello" + 1; //~ ERROR cannot add `{integer}` to `&str`
+    //~^ ERROR cannot add `{integer}` to `&str`
+    println!("{}", FOO);
+}
diff --git a/src/test/ui/typeck/issue-79040.stderr b/src/test/ui/typeck/issue-79040.stderr
new file mode 100644
index 00000000000..32049e5d968
--- /dev/null
+++ b/src/test/ui/typeck/issue-79040.stderr
@@ -0,0 +1,19 @@
+error[E0369]: cannot add `{integer}` to `&str`
+  --> $DIR/issue-79040.rs:2:25
+   |
+LL |     const FOO = "hello" + 1;
+   |                 ------- ^ - {integer}
+   |                 |
+   |                 &str
+
+error[E0369]: cannot add `{integer}` to `&str`
+  --> $DIR/issue-79040.rs:2:25
+   |
+LL |     const FOO = "hello" + 1;
+   |                 ------- ^ - {integer}
+   |                 |
+   |                 &str
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/issues/issue-18661.rs b/src/test/ui/unboxed-closures/issue-18661.rs
index e2427243235..e2427243235 100644
--- a/src/test/ui/issues/issue-18661.rs
+++ b/src/test/ui/unboxed-closures/issue-18661.rs
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 659d5ae03c9..c69bdca7611 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -8,7 +8,7 @@ use std::path::Path;
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
 const ROOT_ENTRY_LIMIT: usize = 1418;
-const ISSUES_ENTRY_LIMIT: usize = 2582;
+const ISSUES_ENTRY_LIMIT: usize = 2565;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     let dirs = walkdir::WalkDir::new(&path.join("test/ui"))