diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index cb1cb3c74dbb5..e32dae49131ab 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -221,9 +221,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
             sess,
             &codegen_results,
             outputs,
-        );
-
-        Ok(())
+        )
     }
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 26fd1cfbcd08e..aa4db1622b233 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -292,9 +292,7 @@ impl CodegenBackend for LlvmCodegenBackend {
 
         // Run the linker on any artifacts that resulted from the LLVM run.
         // This should produce either a finished executable or library.
-        link_binary::<LlvmArchiveBuilder<'_>>(sess, &codegen_results, outputs);
-
-        Ok(())
+        link_binary::<LlvmArchiveBuilder<'_>>(sess, &codegen_results, outputs)
     }
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index f9efa448c93fa..773a1c500b2f6 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1,9 +1,9 @@
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_data_structures::temp_dir::MaybeTempDir;
-use rustc_errors::Handler;
+use rustc_errors::{ErrorReported, Handler};
 use rustc_fs_util::fix_windows_verbatim_for_gcc;
 use rustc_hir::def_id::CrateNum;
-use rustc_middle::middle::cstore::{DllCallingConvention, DllImport};
+use rustc_middle::middle::cstore::DllImport;
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
 use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
@@ -35,7 +35,6 @@ use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, Se
 use tempfile::Builder as TempFileBuilder;
 
 use std::ffi::OsString;
-use std::iter::FromIterator;
 use std::path::{Path, PathBuf};
 use std::process::{ExitStatus, Output, Stdio};
 use std::{ascii, char, env, fmt, fs, io, mem, str};
@@ -54,7 +53,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
     sess: &'a Session,
     codegen_results: &CodegenResults,
     outputs: &OutputFilenames,
-) {
+) -> Result<(), ErrorReported> {
     let _timer = sess.timer("link_binary");
     let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
     for &crate_type in sess.crate_types().iter() {
@@ -95,11 +94,17 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
             match crate_type {
                 CrateType::Rlib => {
                     let _timer = sess.timer("link_rlib");
-                    link_rlib::<B>(sess, codegen_results, RlibFlavor::Normal, &out_filename, &path)
-                        .build();
+                    link_rlib::<B>(
+                        sess,
+                        codegen_results,
+                        RlibFlavor::Normal,
+                        &out_filename,
+                        &path,
+                    )?
+                    .build();
                 }
                 CrateType::Staticlib => {
-                    link_staticlib::<B>(sess, codegen_results, &out_filename, &path);
+                    link_staticlib::<B>(sess, codegen_results, &out_filename, &path)?;
                 }
                 _ => {
                     link_natively::<B>(
@@ -145,6 +150,8 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
             }
         }
     });
+
+    Ok(())
 }
 
 pub fn each_linked_rlib(
@@ -220,7 +227,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
     flavor: RlibFlavor,
     out_filename: &Path,
     tmpdir: &MaybeTempDir,
-) -> B {
+) -> Result<B, ErrorReported> {
     info!("preparing rlib to {:?}", out_filename);
     let mut ab = <B as ArchiveBuilder>::new(sess, out_filename, None);
 
@@ -259,7 +266,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
     }
 
     for (raw_dylib_name, raw_dylib_imports) in
-        collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)
+        collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)?
     {
         ab.inject_dll_import_lib(&raw_dylib_name, &raw_dylib_imports, tmpdir);
     }
@@ -312,7 +319,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
             }
         }
     }
-    return ab;
+    return Ok(ab);
 
     // For rlibs we "pack" rustc metadata into a dummy object file. When rustc
     // creates a dylib crate type it will pass `--whole-archive` (or the
@@ -454,65 +461,40 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
 fn collate_raw_dylibs(
     sess: &Session,
     used_libraries: &[NativeLib],
-) -> Vec<(String, Vec<DllImport>)> {
-    let mut dylib_table: FxHashMap<String, FxHashSet<DllImport>> = FxHashMap::default();
+) -> Result<Vec<(String, Vec<DllImport>)>, ErrorReported> {
+    // Use index maps to preserve original order of imports and libraries.
+    let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::default();
 
     for lib in used_libraries {
         if lib.kind == NativeLibKind::RawDylib {
-            let name = lib.name.unwrap_or_else(||
-                bug!("`link` attribute with kind = \"raw-dylib\" and no name should have caused error earlier")
-            );
-            let name = if matches!(lib.verbatim, Some(true)) {
-                name.to_string()
-            } else {
-                format!("{}.dll", name)
-            };
-            dylib_table.entry(name).or_default().extend(lib.dll_imports.iter().cloned());
-        }
-    }
-
-    // Rustc already signals an error if we have two imports with the same name but different
-    // calling conventions (or function signatures), so we don't have pay attention to those
-    // when ordering.
-    // FIXME: when we add support for ordinals, figure out if we need to do anything if we
-    // have two DllImport values with the same name but different ordinals.
-    let mut result: Vec<(String, Vec<DllImport>)> = dylib_table
-        .into_iter()
-        .map(|(lib_name, import_table)| {
-            let mut imports = Vec::from_iter(import_table.into_iter());
-            imports.sort_unstable_by_key(|x: &DllImport| x.name.as_str());
-            (lib_name, imports)
-        })
-        .collect::<Vec<_>>();
-    result.sort_unstable_by(|a: &(String, Vec<DllImport>), b: &(String, Vec<DllImport>)| {
-        a.0.cmp(&b.0)
-    });
-    let result = result;
-
-    // Check for multiple imports with the same name but different calling conventions or
-    // (when relevant) argument list sizes.  Rustc only signals an error for this if the
-    // declarations are at the same scope level; if one shadows the other, we only get a lint
-    // warning.
-    for (library, imports) in &result {
-        let mut import_table: FxHashMap<Symbol, DllCallingConvention> = FxHashMap::default();
-        for import in imports {
-            if let Some(old_convention) =
-                import_table.insert(import.name, import.calling_convention)
-            {
-                if import.calling_convention != old_convention {
-                    sess.span_fatal(
-                        import.span,
-                        &format!(
-                            "multiple definitions of external function `{}` from library `{}` have different calling conventions",
-                            import.name,
-                            library,
-                    ));
+            let ext = if matches!(lib.verbatim, Some(true)) { "" } else { ".dll" };
+            let name = format!("{}{}", lib.name.expect("unnamed raw-dylib library"), ext);
+            let imports = dylib_table.entry(name.clone()).or_default();
+            for import in &lib.dll_imports {
+                if let Some(old_import) = imports.insert(import.name, import) {
+                    // FIXME: when we add support for ordinals, figure out if we need to do anything
+                    // if we have two DllImport values with the same name but different ordinals.
+                    if import.calling_convention != old_import.calling_convention {
+                        sess.span_err(
+                            import.span,
+                            &format!(
+                                "multiple declarations of external function `{}` from \
+                                 library `{}` have different calling conventions",
+                                import.name, name,
+                            ),
+                        );
+                    }
                 }
             }
         }
     }
-
-    result
+    sess.compile_status()?;
+    Ok(dylib_table
+        .into_iter()
+        .map(|(name, imports)| {
+            (name, imports.into_iter().map(|(_, import)| import.clone()).collect())
+        })
+        .collect())
 }
 
 /// Create a static archive.
@@ -531,9 +513,9 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
     codegen_results: &CodegenResults,
     out_filename: &Path,
     tempdir: &MaybeTempDir,
-) {
+) -> Result<(), ErrorReported> {
     let mut ab =
-        link_rlib::<B>(sess, codegen_results, RlibFlavor::StaticlibBase, out_filename, tempdir);
+        link_rlib::<B>(sess, codegen_results, RlibFlavor::StaticlibBase, out_filename, tempdir)?;
     let mut all_native_libs = vec![];
 
     let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| {
@@ -581,6 +563,8 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
             print_native_static_libs(sess, &all_native_libs);
         }
     }
+
+    Ok(())
 }
 
 fn escape_stdout_stderr_string(s: &[u8]) -> String {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 6877d6ef542c7..a4913a32e81ef 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1581,7 +1581,7 @@ impl EncodeContext<'a, 'tcx> {
     fn encode_native_libraries(&mut self) -> Lazy<[NativeLib]> {
         empty_proc_macro!(self);
         let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
-        self.lazy(used_libraries.iter().cloned())
+        self.lazy(used_libraries.iter())
     }
 
     fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> {
diff --git a/compiler/rustc_middle/src/middle/cstore.rs b/compiler/rustc_middle/src/middle/cstore.rs
index 4c35b49bcefd7..8150e67929509 100644
--- a/compiler/rustc_middle/src/middle/cstore.rs
+++ b/compiler/rustc_middle/src/middle/cstore.rs
@@ -64,7 +64,7 @@ pub enum LinkagePreference {
     RequireStatic,
 }
 
-#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
+#[derive(Debug, Encodable, Decodable, HashStable)]
 pub struct NativeLib {
     pub kind: NativeLibKind,
     pub name: Option<Symbol>,
@@ -75,7 +75,7 @@ pub struct NativeLib {
     pub dll_imports: Vec<DllImport>,
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Encodable, Decodable, Hash, HashStable)]
+#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
 pub struct DllImport {
     pub name: Symbol,
     pub ordinal: Option<u16>,
@@ -92,7 +92,7 @@ pub struct DllImport {
 ///
 /// The usize value, where present, indicates the size of the function's argument list
 /// in bytes.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Encodable, Decodable, Hash, HashStable)]
+#[derive(Clone, PartialEq, Debug, Encodable, Decodable, HashStable)]
 pub enum DllCallingConvention {
     C,
     Stdcall(usize),
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index b0156daf17eff..6b51adc6aafdd 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -281,11 +281,10 @@ pub struct CaptureInfo<'tcx> {
 }
 
 pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String {
-    let name = match place.base {
+    let mut curr_string: String = match place.base {
         HirPlaceBase::Upvar(upvar_id) => tcx.hir().name(upvar_id.var_path.hir_id).to_string(),
         _ => bug!("Capture_information should only contain upvars"),
     };
-    let mut curr_string = name;
 
     for (i, proj) in place.projections.iter().enumerate() {
         match proj.kind {
@@ -314,7 +313,7 @@ pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) ->
         }
     }
 
-    curr_string.to_string()
+    curr_string
 }
 
 #[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, TypeFoldable, Copy, HashStable)]
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index 12d0c14a3d51a..d35868881558e 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -66,6 +66,10 @@ crate fn compare_impl_method<'tcx>(
     {
         return;
     }
+
+    if let Err(ErrorReported) = compare_const_param_types(tcx, impl_m, trait_m, trait_item_span) {
+        return;
+    }
 }
 
 fn compare_predicate_entailment<'tcx>(
@@ -929,6 +933,68 @@ fn compare_synthetic_generics<'tcx>(
     if error_found { Err(ErrorReported) } else { Ok(()) }
 }
 
+fn compare_const_param_types<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    impl_m: &ty::AssocItem,
+    trait_m: &ty::AssocItem,
+    trait_item_span: Option<Span>,
+) -> Result<(), ErrorReported> {
+    let const_params_of = |def_id| {
+        tcx.generics_of(def_id).params.iter().filter_map(|param| match param.kind {
+            GenericParamDefKind::Const { .. } => Some(param.def_id),
+            _ => None,
+        })
+    };
+    let const_params_impl = const_params_of(impl_m.def_id);
+    let const_params_trait = const_params_of(trait_m.def_id);
+
+    for (const_param_impl, const_param_trait) in iter::zip(const_params_impl, const_params_trait) {
+        let impl_ty = tcx.type_of(const_param_impl);
+        let trait_ty = tcx.type_of(const_param_trait);
+        if impl_ty != trait_ty {
+            let (impl_span, impl_ident) = match tcx.hir().get_if_local(const_param_impl) {
+                Some(hir::Node::GenericParam(hir::GenericParam { span, name, .. })) => (
+                    span,
+                    match name {
+                        hir::ParamName::Plain(ident) => Some(ident),
+                        _ => None,
+                    },
+                ),
+                other => bug!(
+                    "expected GenericParam, found {:?}",
+                    other.map_or_else(|| "nothing".to_string(), |n| format!("{:?}", n))
+                ),
+            };
+            let trait_span = match tcx.hir().get_if_local(const_param_trait) {
+                Some(hir::Node::GenericParam(hir::GenericParam { span, .. })) => Some(span),
+                _ => None,
+            };
+            let mut err = struct_span_err!(
+                tcx.sess,
+                *impl_span,
+                E0053,
+                "method `{}` has an incompatible const parameter type for trait",
+                trait_m.ident
+            );
+            err.span_note(
+                trait_span.map_or_else(|| trait_item_span.unwrap_or(*impl_span), |span| *span),
+                &format!(
+                    "the const parameter{} has type `{}`, but the declaration \
+                              in trait `{}` has type `{}`",
+                    &impl_ident.map_or_else(|| "".to_string(), |ident| format!(" `{}`", ident)),
+                    impl_ty,
+                    tcx.def_path_str(trait_m.def_id),
+                    trait_ty
+                ),
+            );
+            err.emit();
+            return Err(ErrorReported);
+        }
+    }
+
+    Ok(())
+}
+
 crate fn compare_const_impl<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_c: &ty::AssocItem,
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index b7af3ea8c1af4..c27db0767ac9d 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -356,7 +356,7 @@
 //! // must have the same concrete type.
 //! fn make_iter(do_insert: bool) -> impl Iterator<Item = i32> {
 //!     // Explicit returns to illustrate return types not matching
-//!     match x {
+//!     match do_insert {
 //!         true => return (0..4).chain(once(42)).chain(4..8),
 //!         false => return (0..4).chain(empty()).chain(4..8),
 //!     }
diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md
index 2e4016e24bc3f..c8af369a9695e 100644
--- a/src/doc/rustdoc/src/command-line-arguments.md
+++ b/src/doc/rustdoc/src/command-line-arguments.md
@@ -417,3 +417,10 @@ This flag is **deprecated** and **has no effect**.
 Rustdoc only supports Rust source code and Markdown input formats. If the
 file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file.
 Otherwise, it assumes that the input file is Rust.
+
+## `--nocapture`
+
+When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be
+captured by rustdoc. Instead, the output will be directed to your terminal,
+as if you had run the test executable manually. This is especially useful
+for debugging your tests!
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 80aaae1580114..1a2852dc6c724 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -14,7 +14,7 @@ use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc_middle::middle::resolve_lifetime as rl;
@@ -85,12 +85,6 @@ impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
     }
 }
 
-impl Clean<ExternalCrate> for CrateNum {
-    fn clean(&self, _cx: &mut DocContext<'_>) -> ExternalCrate {
-        ExternalCrate { crate_num: *self }
-    }
-}
-
 impl Clean<Item> for doctree::Module<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
         let mut items: Vec<Item> = vec![];
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 859746b6a2df7..2fd2d14bcabc3 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -118,7 +118,7 @@ crate struct Crate {
     crate name: Symbol,
     crate src: FileName,
     crate module: Item,
-    crate externs: Vec<(CrateNum, ExternalCrate)>,
+    crate externs: Vec<ExternalCrate>,
     crate primitives: ThinVec<(DefId, PrimitiveType)>,
     // These are later on moved into `CACHEKEY`, leaving the map empty.
     // Only here so that they can be filtered through the rustdoc passes.
@@ -133,14 +133,14 @@ crate struct TraitWithExtraInfo {
     crate is_notable: bool,
 }
 
-#[derive(Clone, Debug)]
+#[derive(Copy, Clone, Debug)]
 crate struct ExternalCrate {
     crate crate_num: CrateNum,
 }
 
 impl ExternalCrate {
     #[inline]
-    fn def_id(&self) -> DefId {
+    crate fn def_id(&self) -> DefId {
         DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }
     }
 
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index dea016a467d64..bdd5350aab2cb 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -1,9 +1,9 @@
 use crate::clean::auto_trait::AutoTraitFinder;
 use crate::clean::blanket_impl::BlanketImplFinder;
 use crate::clean::{
-    inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime,
-    Path, PathSegment, PolyTrait, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
-    Visibility,
+    inline, Clean, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item,
+    ItemKind, Lifetime, Path, PathSegment, PolyTrait, Primitive, PrimitiveType, ResolvedPath, Type,
+    TypeBinding, Visibility,
 };
 use crate::core::DocContext;
 use crate::formats::item_type::ItemType;
@@ -35,11 +35,11 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate {
 
     let mut externs = Vec::new();
     for &cnum in cx.tcx.crates(()).iter() {
-        externs.push((cnum, cnum.clean(cx)));
+        externs.push(ExternalCrate { crate_num: cnum });
         // Analyze doc-reachability for extern items
         LibEmbargoVisitor::new(cx).visit_lib(cnum);
     }
-    externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
+    externs.sort_unstable_by_key(|e| e.crate_num);
 
     // Clean the crate, translating the entire librustc_ast AST to one that is
     // understood by rustdoc.
@@ -61,7 +61,7 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate {
         _ => unreachable!(),
     }
 
-    let local_crate = LOCAL_CRATE.clean(cx);
+    let local_crate = ExternalCrate { crate_num: LOCAL_CRATE };
     let src = local_crate.src(cx.tcx);
     let name = local_crate.name(cx.tcx);
     let primitives = local_crate.primitives(cx.tcx);
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 4cf647a81ae4b..adbdde0d92cd6 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -156,6 +156,8 @@ crate struct Options {
     crate run_check: bool,
     /// Whether doctests should emit unused externs
     crate json_unused_externs: bool,
+    /// Whether to skip capturing stdout and stderr of tests.
+    crate nocapture: bool,
 }
 
 impl fmt::Debug for Options {
@@ -199,6 +201,7 @@ impl fmt::Debug for Options {
             .field("enable-per-target-ignores", &self.enable_per_target_ignores)
             .field("run_check", &self.run_check)
             .field("no_run", &self.no_run)
+            .field("nocapture", &self.nocapture)
             .finish()
     }
 }
@@ -627,6 +630,7 @@ impl Options {
         let run_check = matches.opt_present("check");
         let generate_redirect_map = matches.opt_present("generate-redirect-map");
         let show_type_layout = matches.opt_present("show-type-layout");
+        let nocapture = matches.opt_present("nocapture");
 
         let (lint_opts, describe_lints, lint_cap, _) =
             get_cmd_lint_options(matches, error_format, &debugging_opts);
@@ -665,6 +669,7 @@ impl Options {
             test_builder,
             run_check,
             no_run,
+            nocapture,
             render_options: RenderOptions {
                 output,
                 external_html,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index c5ca396e72029..5ce7c49278d23 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -107,6 +107,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
 
     let mut test_args = options.test_args.clone();
     let display_warnings = options.display_warnings;
+    let nocapture = options.nocapture;
     let externs = options.externs.clone();
     let json_unused_externs = options.json_unused_externs;
 
@@ -166,6 +167,9 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
     };
 
     test_args.insert(0, "rustdoctest".to_string());
+    if nocapture {
+        test_args.push("--nocapture".to_string());
+    }
 
     test::test_main(&test_args, tests, Some(test::Options::new().display_output(display_warnings)));
 
@@ -456,7 +460,16 @@ fn run_test(
         cmd.current_dir(run_directory);
     }
 
-    match cmd.output() {
+    let result = if options.nocapture {
+        cmd.status().map(|status| process::Output {
+            status,
+            stdout: Vec::new(),
+            stderr: Vec::new(),
+        })
+    } else {
+        cmd.output()
+    };
+    match result {
         Err(e) => return Err(TestFailure::ExecutionError(e)),
         Ok(out) => {
             if should_panic && out.status.success() {
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index e7d6e5ac2c24b..5ea2cdc2ad909 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -151,19 +151,18 @@ impl Cache {
 
         // Cache where all our extern crates are located
         // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code
-        for &(n, ref e) in &krate.externs {
+        for &e in &krate.externs {
             let name = e.name(tcx);
             let extern_url = extern_html_root_urls.get(&*name.as_str()).map(|u| &**u);
-            let did = DefId { krate: n, index: CRATE_DEF_INDEX };
-            self.extern_locations.insert(n, e.location(extern_url, &dst, tcx));
-            self.external_paths.insert(did, (vec![name.to_string()], ItemType::Module));
+            self.extern_locations.insert(e.crate_num, e.location(extern_url, &dst, tcx));
+            self.external_paths.insert(e.def_id(), (vec![name.to_string()], ItemType::Module));
         }
 
         // Cache where all known primitives have their documentation located.
         //
         // Favor linking to as local extern as possible, so iterate all crates in
         // reverse topological order.
-        for &(_, ref e) in krate.externs.iter().rev() {
+        for &e in krate.externs.iter().rev() {
             for &(def_id, prim) in &e.primitives(tcx) {
                 self.primitive_locations.insert(prim, def_id);
             }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index d4d87819c0d7a..19deaa11388d8 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -604,6 +604,9 @@ fn opts() -> Vec<RustcOptGroup> {
         unstable("show-type-layout", |o| {
             o.optflagmulti("", "show-type-layout", "Include the memory layout of types in the docs")
         }),
+        unstable("nocapture", |o| {
+            o.optflag("", "nocapture", "Don't capture stdout and stderr of tests")
+        }),
     ]
 }
 
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 45966c0058df4..6c8b95c04c9e4 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -136,6 +136,9 @@ crate fn test(mut options: Options) -> Result<(), String> {
     find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores, None);
 
     options.test_args.insert(0, "rustdoctest".to_string());
+    if options.nocapture {
+        options.test_args.push("--nocapture".to_string());
+    }
     test::test_main(
         &options.test_args,
         collector.tests,
diff --git a/src/test/rustdoc-ui/nocapture-fail.rs b/src/test/rustdoc-ui/nocapture-fail.rs
new file mode 100644
index 0000000000000..f878ea0962c08
--- /dev/null
+++ b/src/test/rustdoc-ui/nocapture-fail.rs
@@ -0,0 +1,11 @@
+// check-pass
+// compile-flags:--test -Zunstable-options --nocapture
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```compile_fail
+/// fn foo() {
+///     Input: 123
+/// }
+/// ```
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/nocapture-fail.stderr b/src/test/rustdoc-ui/nocapture-fail.stderr
new file mode 100644
index 0000000000000..ef03347bab1ef
--- /dev/null
+++ b/src/test/rustdoc-ui/nocapture-fail.stderr
@@ -0,0 +1,18 @@
+error: struct literal body without path
+  --> $DIR/nocapture-fail.rs:7:10
+   |
+LL |   fn foo() {
+   |  __________^
+LL | |     Input: 123
+LL | | }
+   | |_^
+   |
+help: you might have forgotten to add the struct literal inside the block
+   |
+LL | fn foo() { SomeStruct {
+LL |     Input: 123
+LL | } }
+   |
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/nocapture-fail.stdout b/src/test/rustdoc-ui/nocapture-fail.stdout
new file mode 100644
index 0000000000000..131713e3a3f2d
--- /dev/null
+++ b/src/test/rustdoc-ui/nocapture-fail.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/nocapture-fail.rs - Foo (line 6) - compile fail ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/nocapture.rs b/src/test/rustdoc-ui/nocapture.rs
new file mode 100644
index 0000000000000..321f5ca08eded
--- /dev/null
+++ b/src/test/rustdoc-ui/nocapture.rs
@@ -0,0 +1,10 @@
+// check-pass
+// compile-flags:--test -Zunstable-options --nocapture
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// println!("hello!");
+/// eprintln!("stderr");
+/// ```
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/nocapture.stderr b/src/test/rustdoc-ui/nocapture.stderr
new file mode 100644
index 0000000000000..af6415db3c724
--- /dev/null
+++ b/src/test/rustdoc-ui/nocapture.stderr
@@ -0,0 +1 @@
+stderr
diff --git a/src/test/rustdoc-ui/nocapture.stdout b/src/test/rustdoc-ui/nocapture.stdout
new file mode 100644
index 0000000000000..4880e75da7062
--- /dev/null
+++ b/src/test/rustdoc-ui/nocapture.stdout
@@ -0,0 +1,7 @@
+
+running 1 test
+hello!
+test $DIR/nocapture.rs - Foo (line 6) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/ui/const-generics/issue-86820.rs b/src/test/ui/const-generics/issue-86820.rs
new file mode 100644
index 0000000000000..04650403c6baf
--- /dev/null
+++ b/src/test/ui/const-generics/issue-86820.rs
@@ -0,0 +1,25 @@
+// Regression test for the ICE described in #86820.
+
+#![allow(unused,dead_code)]
+use std::ops::BitAnd;
+
+const C: fn() = || is_set();
+fn is_set() {
+    0xffu8.bit::<0>();
+}
+
+trait Bits {
+    fn bit<const I : u8>(self) -> bool;
+    //~^ NOTE: the const parameter `I` has type `usize`, but the declaration in trait `Bits::bit` has type `u8`
+}
+
+impl Bits for u8 {
+    fn bit<const I : usize>(self) -> bool {
+    //~^ ERROR: method `bit` has an incompatible const parameter type for trait [E0053]
+        let i = 1 << I;
+        let mask = u8::from(i);
+        mask & self == mask
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issue-86820.stderr b/src/test/ui/const-generics/issue-86820.stderr
new file mode 100644
index 0000000000000..f4396f2f2b0a2
--- /dev/null
+++ b/src/test/ui/const-generics/issue-86820.stderr
@@ -0,0 +1,15 @@
+error[E0053]: method `bit` has an incompatible const parameter type for trait
+  --> $DIR/issue-86820.rs:17:18
+   |
+LL |     fn bit<const I : usize>(self) -> bool {
+   |                  ^
+   |
+note: the const parameter `I` has type `usize`, but the declaration in trait `Bits::bit` has type `u8`
+  --> $DIR/issue-86820.rs:12:18
+   |
+LL |     fn bit<const I : u8>(self) -> bool;
+   |                  ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs
new file mode 100644
index 0000000000000..d02bebc9d61d2
--- /dev/null
+++ b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs
@@ -0,0 +1,19 @@
+// only-i686-pc-windows-msvc
+// compile-flags: --crate-type lib --emit link
+#![allow(clashing_extern_declarations)]
+#![feature(raw_dylib)]
+//~^ WARN the feature `raw_dylib` is incomplete
+#[link(name = "foo", kind = "raw-dylib")]
+extern "C" {
+    fn f(x: i32);
+}
+
+pub fn lib_main() {
+    #[link(name = "foo", kind = "raw-dylib")]
+    extern "stdcall" {
+        fn f(x: i32);
+        //~^ ERROR multiple declarations of external function `f` from library `foo.dll` have different calling conventions
+    }
+
+    unsafe { f(42); }
+}
diff --git a/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr
new file mode 100644
index 0000000000000..a9cfd6b23f9f8
--- /dev/null
+++ b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr
@@ -0,0 +1,17 @@
+warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/multiple-declarations.rs:4:12
+   |
+LL | #![feature(raw_dylib)]
+   |            ^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
+
+error: multiple declarations of external function `f` from library `foo.dll` have different calling conventions
+  --> $DIR/multiple-declarations.rs:14:9
+   |
+LL |         fn f(x: i32);
+   |         ^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.rs b/src/test/ui/type-alias-impl-trait/issue-63355.rs
new file mode 100644
index 0000000000000..8762d189c7389
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-63355.rs
@@ -0,0 +1,50 @@
+#![feature(min_type_alias_impl_trait)]
+#![feature(type_alias_impl_trait)]
+#![allow(incomplete_features)]
+
+pub trait Foo {}
+
+pub trait Bar {
+    type Foo: Foo;
+
+    fn foo() -> Self::Foo;
+}
+
+pub trait Baz {
+    type Foo: Foo;
+    type Bar: Bar<Foo = Self::Foo>;
+
+    fn foo() -> Self::Foo;
+    fn bar() -> Self::Bar;
+}
+
+impl Foo for () {}
+
+impl Bar for () {
+    type Foo = FooImpl;
+
+    fn foo() -> Self::Foo {
+        ()
+    }
+}
+
+// FIXME(#86731): The below is illegal use of `min_type_alias_impl_trait`
+// but the compiler doesn't report it, we should fix it.
+pub type FooImpl = impl Foo;
+pub type BarImpl = impl Bar<Foo = FooImpl>;
+//~^ ERROR: type mismatch resolving `<() as Bar>::Foo == ()`
+
+impl Baz for () {
+    type Foo = FooImpl;
+    type Bar = BarImpl;
+
+    fn foo() -> Self::Foo {
+        ()
+    }
+
+    fn bar() -> Self::Bar {
+        ()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.stderr b/src/test/ui/type-alias-impl-trait/issue-63355.stderr
new file mode 100644
index 0000000000000..dc5370a2666b7
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-63355.stderr
@@ -0,0 +1,14 @@
+error[E0271]: type mismatch resolving `<() as Bar>::Foo == ()`
+  --> $DIR/issue-63355.rs:34:20
+   |
+LL | pub type FooImpl = impl Foo;
+   |                    -------- the found opaque type
+LL | pub type BarImpl = impl Bar<Foo = FooImpl>;
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found opaque type
+   |
+   = note: expected unit type `()`
+            found opaque type `impl Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.