about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-07-19 10:10:08 +0000
committerbors <bors@rust-lang.org>2021-07-19 10:10:08 +0000
commit8df945c4717ffaf923b57bf30c473df6fc98bc85 (patch)
tree8929ee5e23a7bd91146213570268566f37deb884
parent83f08223a90b71f59e5dc5f38e384a49a76c8452 (diff)
parent6cb69ea790ad635acb3a8d4826e03ac29ca10351 (diff)
downloadrust-8df945c4717ffaf923b57bf30c473df6fc98bc85.tar.gz
rust-8df945c4717ffaf923b57bf30c473df6fc98bc85.zip
Auto merge of #87269 - GuillaumeGomez:rollup-qukedv0, r=GuillaumeGomez
Rollup of 8 pull requests

Successful merges:

 - #86230 (Add --nocapture option to rustdoc)
 - #87210 (Rustdoc accessibility: make the sidebar headers actual headers)
 - #87227 (Move asm! and global_asm! to core::arch)
 - #87236 (Simplify command-line argument initialization on unix)
 - #87251 (Fix "item info" width)
 - #87256 (Extend HIR-based WF checking to associated type defaults)
 - #87259 (triagebot shortcut config)
 - #87268 (Don't create references to uninitialized data in `List::from_arena`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_middle/src/ty/list.rs12
-rw-r--r--compiler/rustc_typeck/src/hir_wf_check.rs6
-rw-r--r--library/core/src/lib.rs32
-rw-r--r--library/core/src/macros/mod.rs38
-rw-r--r--library/core/src/prelude/v1.rs22
-rw-r--r--library/std/src/lib.rs6
-rw-r--r--library/std/src/prelude/v1.rs24
-rw-r--r--library/std/src/sys/unix/args.rs24
-rw-r--r--library/std/src/sys/unix/mod.rs1
-rw-r--r--src/doc/rustdoc/src/command-line-arguments.md7
-rw-r--r--src/librustdoc/config.rs5
-rw-r--r--src/librustdoc/doctest.rs15
-rw-r--r--src/librustdoc/html/render/context.rs4
-rw-r--r--src/librustdoc/html/render/mod.rs54
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css7
-rw-r--r--src/librustdoc/lib.rs3
-rw-r--r--src/librustdoc/markdown.rs3
-rw-r--r--src/test/rustdoc-gui/item-info-width.goml7
-rw-r--r--src/test/rustdoc-gui/sidebar-mobile.goml2
-rw-r--r--src/test/rustdoc-gui/src/lib2/lib.rs3
-rw-r--r--src/test/rustdoc-ui/nocapture-fail.rs12
-rw-r--r--src/test/rustdoc-ui/nocapture-fail.stderr18
-rw-r--r--src/test/rustdoc-ui/nocapture-fail.stdout6
-rw-r--r--src/test/rustdoc-ui/nocapture.rs10
-rw-r--r--src/test/rustdoc-ui/nocapture.stderr1
-rw-r--r--src/test/rustdoc-ui/nocapture.stdout7
-rw-r--r--src/test/rustdoc/deref-typedef.rs2
-rw-r--r--src/test/rustdoc/negative-impl-sidebar.rs2
-rw-r--r--src/test/rustdoc/sidebar-items.rs14
-rw-r--r--src/test/rustdoc/sidebar-links-to-foreign-impl.rs2
-rw-r--r--src/test/rustdoc/typedef.rs2
-rw-r--r--src/test/ui/associated-types/defaults-wf.stderr4
-rw-r--r--src/test/ui/wf/wf-trait-associated-type-trait.rs2
-rw-r--r--src/test/ui/wf/wf-trait-associated-type-trait.stderr6
-rw-r--r--triagebot.toml2
35 files changed, 239 insertions, 126 deletions
diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs
index 44dfcbf1866..1dceda6c7aa 100644
--- a/compiler/rustc_middle/src/ty/list.rs
+++ b/compiler/rustc_middle/src/ty/list.rs
@@ -63,17 +63,17 @@ impl<T: Copy> List<T> {
 
         let (layout, _offset) =
             Layout::new::<usize>().extend(Layout::for_value::<[T]>(slice)).unwrap();
-        let mem = arena.dropless.alloc_raw(layout);
+        let mem = arena.dropless.alloc_raw(layout) as *mut List<T>;
         unsafe {
-            let result = &mut *(mem as *mut List<T>);
             // Write the length
-            result.len = slice.len();
+            ptr::addr_of_mut!((*mem).len).write(slice.len());
 
             // Write the elements
-            let arena_slice = slice::from_raw_parts_mut(result.data.as_mut_ptr(), result.len);
-            arena_slice.copy_from_slice(slice);
+            ptr::addr_of_mut!((*mem).data)
+                .cast::<T>()
+                .copy_from_nonoverlapping(slice.as_ptr(), slice.len());
 
-            result
+            &mut *mem
         }
     }
 
diff --git a/compiler/rustc_typeck/src/hir_wf_check.rs b/compiler/rustc_typeck/src/hir_wf_check.rs
index fa9c44bb891..a8ec7b79e57 100644
--- a/compiler/rustc_typeck/src/hir_wf_check.rs
+++ b/compiler/rustc_typeck/src/hir_wf_check.rs
@@ -121,7 +121,11 @@ fn diagnostic_hir_wf_check<'tcx>(
 
     let ty = match tcx.hir().get(hir_id) {
         hir::Node::ImplItem(item) => match item.kind {
-            hir::ImplItemKind::TyAlias(ref ty) => Some(ty),
+            hir::ImplItemKind::TyAlias(ty) => Some(ty),
+            _ => None,
+        },
+        hir::Node::TraitItem(item) => match item.kind {
+            hir::TraitItemKind::Type(_, ty) => ty,
             _ => None,
         },
         _ => None,
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 8bbce7e552c..540cdf124ee 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -316,5 +316,35 @@ pub mod primitive;
 #[unstable(feature = "stdsimd", issue = "48556")]
 mod core_arch;
 
+#[doc = include_str!("../../stdarch/crates/core_arch/src/core_arch_docs.md")]
 #[stable(feature = "simd_arch", since = "1.27.0")]
-pub use core_arch::arch;
+pub mod arch {
+    #[stable(feature = "simd_arch", since = "1.27.0")]
+    pub use crate::core_arch::arch::*;
+
+    /// Inline assembly.
+    ///
+    /// Read the [unstable book] for the usage.
+    ///
+    /// [unstable book]: ../../unstable-book/library-features/asm.html
+    #[unstable(
+        feature = "asm",
+        issue = "72016",
+        reason = "inline assembly is not stable enough for use and is subject to change"
+    )]
+    #[rustc_builtin_macro]
+    pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) {
+        /* compiler built-in */
+    }
+
+    /// Module-level inline assembly.
+    #[unstable(
+        feature = "global_asm",
+        issue = "35119",
+        reason = "`global_asm!` is not stable enough for use and is subject to change"
+    )]
+    #[rustc_builtin_macro]
+    pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) {
+        /* compiler built-in */
+    }
+}
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 57eedde9164..3ca8f27c79a 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1312,27 +1312,6 @@ pub(crate) mod builtin {
         ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }};
     }
 
-    /// Inline assembly.
-    ///
-    /// Read the [unstable book] for the usage.
-    ///
-    /// [unstable book]: ../unstable-book/library-features/asm.html
-    #[unstable(
-        feature = "asm",
-        issue = "72016",
-        reason = "inline assembly is not stable enough for use and is subject to change"
-    )]
-    #[rustc_builtin_macro]
-    #[macro_export]
-    macro_rules! asm {
-        ("assembly template",
-            $(operands,)*
-            $(options($(option),*))?
-        ) => {
-            /* compiler built-in */
-        };
-    }
-
     /// LLVM-style inline assembly.
     ///
     /// Read the [unstable book] for the usage.
@@ -1355,23 +1334,6 @@ pub(crate) mod builtin {
         };
     }
 
-    /// Module-level inline assembly.
-    #[unstable(
-        feature = "global_asm",
-        issue = "35119",
-        reason = "`global_asm!` is not stable enough for use and is subject to change"
-    )]
-    #[rustc_builtin_macro]
-    #[macro_export]
-    macro_rules! global_asm {
-        ("assembly template",
-            $(operands,)*
-            $(options($(option),*))?
-        ) => {
-            /* compiler built-in */
-        };
-    }
-
     /// Prints passed tokens into the standard output.
     #[unstable(
         feature = "log_syntax",
diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs
index c89fe57cb05..6b51ef5b012 100644
--- a/library/core/src/prelude/v1.rs
+++ b/library/core/src/prelude/v1.rs
@@ -55,11 +55,27 @@ pub use crate::hash::macros::Hash;
 #[allow(deprecated)]
 #[doc(no_inline)]
 pub use crate::{
-    asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
-    format_args_nl, global_asm, include, include_bytes, include_str, line, llvm_asm, log_syntax,
-    module_path, option_env, stringify, trace_macros,
+    assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
+    format_args_nl, include, include_bytes, include_str, line, llvm_asm, log_syntax, module_path,
+    option_env, stringify, trace_macros,
 };
 
+#[unstable(
+    feature = "asm",
+    issue = "72016",
+    reason = "inline assembly is not stable enough for use and is subject to change"
+)]
+#[doc(no_inline)]
+pub use crate::arch::asm;
+
+#[unstable(
+    feature = "global_asm",
+    issue = "35119",
+    reason = "`global_asm!` is not stable enough for use and is subject to change"
+)]
+#[doc(no_inline)]
+pub use crate::arch::global_asm;
+
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow(deprecated, deprecated_in_future)]
 #[doc(no_inline)]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index a157a222c43..cfbfe7cc191 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -556,9 +556,9 @@ pub use core::{
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow(deprecated)]
 pub use core::{
-    asm, assert, assert_matches, cfg, column, compile_error, concat, concat_idents, env, file,
-    format_args, format_args_nl, global_asm, include, include_bytes, include_str, line, llvm_asm,
-    log_syntax, module_path, option_env, stringify, trace_macros,
+    assert, assert_matches, cfg, column, compile_error, concat, concat_idents, env, file,
+    format_args, format_args_nl, include, include_bytes, include_str, line, llvm_asm, log_syntax,
+    module_path, option_env, stringify, trace_macros,
 };
 
 #[stable(feature = "core_primitive", since = "1.43.0")]
diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs
index 4a3c3ba1635..772044f0149 100644
--- a/library/std/src/prelude/v1.rs
+++ b/library/std/src/prelude/v1.rs
@@ -39,12 +39,28 @@ pub use crate::result::Result::{self, Err, Ok};
 #[allow(deprecated)]
 #[doc(no_inline)]
 pub use core::prelude::v1::{
-    asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
-    format_args_nl, global_asm, include, include_bytes, include_str, line, llvm_asm, log_syntax,
-    module_path, option_env, stringify, trace_macros, Clone, Copy, Debug, Default, Eq, Hash, Ord,
-    PartialEq, PartialOrd,
+    assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
+    format_args_nl, include, include_bytes, include_str, line, llvm_asm, log_syntax, module_path,
+    option_env, stringify, trace_macros, Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq,
+    PartialOrd,
 };
 
+#[unstable(
+    feature = "asm",
+    issue = "72016",
+    reason = "inline assembly is not stable enough for use and is subject to change"
+)]
+#[doc(no_inline)]
+pub use core::prelude::v1::asm;
+
+#[unstable(
+    feature = "global_asm",
+    issue = "35119",
+    reason = "`global_asm!` is not stable enough for use and is subject to change"
+)]
+#[doc(no_inline)]
+pub use core::prelude::v1::global_asm;
+
 // FIXME: Attribute and internal derive macros are not documented because for them rustdoc generates
 // dead links which fail link checker testing.
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs
index fc423e393d4..ad93fa610c4 100644
--- a/library/std/src/sys/unix/args.rs
+++ b/library/std/src/sys/unix/args.rs
@@ -14,11 +14,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
     imp::init(argc, argv)
 }
 
-/// One-time global cleanup.
-pub unsafe fn cleanup() {
-    imp::cleanup()
-}
-
 /// Returns the command line arguments
 pub fn args() -> Args {
     imp::args()
@@ -82,16 +77,10 @@ mod imp {
     use crate::ptr;
     use crate::sync::atomic::{AtomicIsize, AtomicPtr, Ordering};
 
-    use crate::sys_common::mutex::StaticMutex;
-
     static ARGC: AtomicIsize = AtomicIsize::new(0);
     static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
-    // We never call `ENV_LOCK.init()`, so it is UB to attempt to
-    // acquire this mutex reentrantly!
-    static LOCK: StaticMutex = StaticMutex::new();
 
     unsafe fn really_init(argc: isize, argv: *const *const u8) {
-        let _guard = LOCK.lock();
         ARGC.store(argc, Ordering::Relaxed);
         ARGV.store(argv as *mut _, Ordering::Relaxed);
     }
@@ -127,21 +116,16 @@ mod imp {
         init_wrapper
     };
 
-    pub unsafe fn cleanup() {
-        let _guard = LOCK.lock();
-        ARGC.store(0, Ordering::Relaxed);
-        ARGV.store(ptr::null_mut(), Ordering::Relaxed);
-    }
-
     pub fn args() -> Args {
         Args { iter: clone().into_iter() }
     }
 
     fn clone() -> Vec<OsString> {
         unsafe {
-            let _guard = LOCK.lock();
-            let argc = ARGC.load(Ordering::Relaxed);
+            // Load ARGC and ARGV without a lock. If the store to either ARGV or
+            // ARGC isn't visible yet, we'll return an empty argument list.
             let argv = ARGV.load(Ordering::Relaxed);
+            let argc = if argv.is_null() { 0 } else { ARGC.load(Ordering::Relaxed) };
             (0..argc)
                 .map(|i| {
                     let cstr = CStr::from_ptr(*argv.offset(i) as *const libc::c_char);
@@ -159,8 +143,6 @@ mod imp {
 
     pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
 
-    pub fn cleanup() {}
-
     #[cfg(target_os = "macos")]
     pub fn args() -> Args {
         use crate::os::unix::prelude::*;
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 2da71b2a448..9e553ec7682 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -123,7 +123,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
 // SAFETY: must be called only once during runtime cleanup.
 // NOTE: this is not guaranteed to run, for example when the program aborts.
 pub unsafe fn cleanup() {
-    args::cleanup();
     stack_overflow::cleanup();
 }
 
diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md
index 2e4016e24bc..c8af369a969 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/config.rs b/src/librustdoc/config.rs
index 4cf647a81ae..adbdde0d92c 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 c5ca396e720..5ce7c49278d 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/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 61057ff515b..b6c3220901f 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -539,7 +539,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         };
         let sidebar = if let Some(ref version) = self.cache.crate_version {
             format!(
-                "<p class=\"location\">Crate {}</p>\
+                "<h2 class=\"location\">Crate {}</h2>\
                      <div class=\"block version\">\
                          <p>Version {}</p>\
                      </div>\
@@ -567,7 +567,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         page.root_path = "./";
 
         let mut style_files = self.shared.style_files.clone();
-        let sidebar = "<p class=\"location\">Settings</p><div class=\"sidebar-elems\"></div>";
+        let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>";
         style_files.push(StylePath { path: PathBuf::from("settings.css"), disabled: false });
         let v = layout::render(
             &self.shared.templates,
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 7de023cabef..68c59612ccc 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1654,7 +1654,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
     {
         write!(
             buffer,
-            "<p class=\"location\">{}{}</p>",
+            "<h2 class=\"location\">{}{}</h2>",
             match *it.kind {
                 clean::StructItem(..) => "Struct ",
                 clean::TraitItem(..) => "Trait ",
@@ -1718,7 +1718,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
     // to navigate the documentation (though slightly inefficiently).
 
     if !it.is_mod() {
-        buffer.write_str("<p class=\"location\">Other items in<br>");
+        buffer.write_str("<h2 class=\"location\">Other items in<br>");
         for (i, name) in cx.current.iter().take(parentlen).enumerate() {
             if i > 0 {
                 buffer.write_str("::<wbr>");
@@ -1730,7 +1730,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
                 *name
             );
         }
-        buffer.write_str("</p>");
+        buffer.write_str("</h2>");
     }
 
     // Sidebar refers to the enclosing module, not this module.
@@ -1841,7 +1841,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
                 ret.sort();
 
                 out.push_str(
-                    "<a class=\"sidebar-title\" href=\"#implementations\">Methods</a>\
+                    "<h3 class=\"sidebar-title\"><a href=\"#implementations\">Methods</a></h3>\
                      <div class=\"sidebar-links\">",
                 );
                 for line in ret {
@@ -1906,24 +1906,24 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
 
             if !concrete_format.is_empty() {
                 out.push_str(
-                    "<a class=\"sidebar-title\" href=\"#trait-implementations\">\
-                        Trait Implementations</a>",
+                    "<h3 class=\"sidebar-title\"><a href=\"#trait-implementations\">\
+                        Trait Implementations</a></h3>",
                 );
                 write_sidebar_links(out, concrete_format);
             }
 
             if !synthetic_format.is_empty() {
                 out.push_str(
-                    "<a class=\"sidebar-title\" href=\"#synthetic-implementations\">\
-                        Auto Trait Implementations</a>",
+                    "<h3 class=\"sidebar-title\"><a href=\"#synthetic-implementations\">\
+                        Auto Trait Implementations</a></h3>",
                 );
                 write_sidebar_links(out, synthetic_format);
             }
 
             if !blanket_format.is_empty() {
                 out.push_str(
-                    "<a class=\"sidebar-title\" href=\"#blanket-implementations\">\
-                        Blanket Implementations</a>",
+                    "<h3 class=\"sidebar-title\"><a href=\"#blanket-implementations\">\
+                        Blanket Implementations</a></h3>",
                 );
                 write_sidebar_links(out, blanket_format);
             }
@@ -1975,7 +1975,7 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
             if !ret.is_empty() {
                 write!(
                     out,
-                    "<a class=\"sidebar-title\" href=\"#deref-methods\">Methods from {}&lt;Target={}&gt;</a>",
+                    "<h3 class=\"sidebar-title\"><a href=\"#deref-methods\">Methods from {}&lt;Target={}&gt;</a></h3>",
                     Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print(cx))),
                     Escape(&format!("{:#}", real_target.print(cx))),
                 );
@@ -1998,7 +1998,7 @@ fn sidebar_struct(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, s: &clea
     if !fields.is_empty() {
         if let CtorKind::Fictive = s.struct_type {
             sidebar.push_str(
-                "<a class=\"sidebar-title\" href=\"#fields\">Fields</a>\
+                "<h3 class=\"sidebar-title\"><a href=\"#fields\">Fields</a></h3>\
                 <div class=\"sidebar-links\">",
             );
 
@@ -2075,8 +2075,8 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
     print_sidebar_section(
         buf,
         &t.items,
-        "<a class=\"sidebar-title\" href=\"#associated-types\">\
-            Associated Types</a><div class=\"sidebar-links\">",
+        "<h3 class=\"sidebar-title\"><a href=\"#associated-types\">\
+            Associated Types</a></h3><div class=\"sidebar-links\">",
         |m| m.is_associated_type(),
         |out, sym| write!(out, "<a href=\"#associatedtype.{0}\">{0}</a>", sym),
         "</div>",
@@ -2085,8 +2085,8 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
     print_sidebar_section(
         buf,
         &t.items,
-        "<a class=\"sidebar-title\" href=\"#associated-const\">\
-            Associated Constants</a><div class=\"sidebar-links\">",
+        "<h3 class=\"sidebar-title\"><a href=\"#associated-const\">\
+            Associated Constants</a></h3><div class=\"sidebar-links\">",
         |m| m.is_associated_const(),
         |out, sym| write!(out, "<a href=\"#associatedconstant.{0}\">{0}</a>", sym),
         "</div>",
@@ -2095,8 +2095,8 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
     print_sidebar_section(
         buf,
         &t.items,
-        "<a class=\"sidebar-title\" href=\"#required-methods\">\
-            Required Methods</a><div class=\"sidebar-links\">",
+        "<h3 class=\"sidebar-title\"><a href=\"#required-methods\">\
+            Required Methods</a></h3><div class=\"sidebar-links\">",
         |m| m.is_ty_method(),
         |out, sym| write!(out, "<a href=\"#tymethod.{0}\">{0}</a>", sym),
         "</div>",
@@ -2105,8 +2105,8 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
     print_sidebar_section(
         buf,
         &t.items,
-        "<a class=\"sidebar-title\" href=\"#provided-methods\">\
-            Provided Methods</a><div class=\"sidebar-links\">",
+        "<h3 class=\"sidebar-title\"><a href=\"#provided-methods\">\
+            Provided Methods</a></h3><div class=\"sidebar-links\">",
         |m| m.is_method(),
         |out, sym| write!(out, "<a href=\"#method.{0}\">{0}</a>", sym),
         "</div>",
@@ -2128,8 +2128,8 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
         if !res.is_empty() {
             res.sort();
             buf.push_str(
-                "<a class=\"sidebar-title\" href=\"#foreign-impls\">\
-                    Implementations on Foreign Types</a>\
+                "<h3 class=\"sidebar-title\"><a href=\"#foreign-impls\">\
+                    Implementations on Foreign Types</a></h3>\
                  <div class=\"sidebar-links\">",
             );
             for (name, id) in res.into_iter() {
@@ -2141,11 +2141,11 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
 
     sidebar_assoc_items(cx, buf, it);
 
-    buf.push_str("<a class=\"sidebar-title\" href=\"#implementors\">Implementors</a>");
+    buf.push_str("<h3 class=\"sidebar-title\"><a href=\"#implementors\">Implementors</a></h3>");
     if t.is_auto {
         buf.push_str(
-            "<a class=\"sidebar-title\" \
-                href=\"#synthetic-implementors\">Auto Implementors</a>",
+            "<h3 class=\"sidebar-title\"><a \
+                href=\"#synthetic-implementors\">Auto Implementors</a></h3>",
         );
     }
 
@@ -2188,7 +2188,7 @@ fn sidebar_union(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, u: &clean
 
     if !fields.is_empty() {
         sidebar.push_str(
-            "<a class=\"sidebar-title\" href=\"#fields\">Fields</a>\
+            "<h3 class=\"sidebar-title\"><a href=\"#fields\">Fields</a></h3>\
             <div class=\"sidebar-links\">",
         );
 
@@ -2220,7 +2220,7 @@ fn sidebar_enum(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, e: &clean:
     if !variants.is_empty() {
         variants.sort_unstable();
         sidebar.push_str(&format!(
-            "<a class=\"sidebar-title\" href=\"#variants\">Variants</a>\
+            "<h3 class=\"sidebar-title\"><a href=\"#variants\">Variants</a></h3>\
              <div class=\"sidebar-links\">{}</div>",
             variants.join(""),
         ));
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index b86f012c0e1..e608ad05b17 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -342,6 +342,8 @@ nav.sub {
 	margin: 30px 10px 20px 10px;
 	text-align: center;
 	word-wrap: break-word;
+	font-weight: inherit;
+	padding: 0;
 }
 
 .sidebar .version {
@@ -394,6 +396,8 @@ nav.sub {
 	text-align: center;
 	font-size: 17px;
 	margin-bottom: 5px;
+	font-weight: inherit;
+	padding: 0;
 }
 
 .sidebar-links {
@@ -921,6 +925,9 @@ body.blur > :not(#help) {
 	padding: 0 20px 20px 17px;;
 }
 
+.item-info .stab {
+	display: table;
+}
 .stab {
 	border-width: 1px;
 	border-style: solid;
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index d4d87819c0d..19deaa11388 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 45966c0058d..6c8b95c04c9 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-gui/item-info-width.goml b/src/test/rustdoc-gui/item-info-width.goml
new file mode 100644
index 00000000000..44b79e60912
--- /dev/null
+++ b/src/test/rustdoc-gui/item-info-width.goml
@@ -0,0 +1,7 @@
+// This test ensures that the item information don't take 100% of the width if unnecessary.
+goto: file://|DOC_PATH|/lib2/struct.Foo.html
+// We set a fixed size so there is no chance of "random" resize.
+size: (1100, 800)
+// We check that ".item-info" is bigger than its content.
+assert-css: (".item-info", {"width": "807px"})
+assert-css: (".item-info .stab", {"width": "343px"})
diff --git a/src/test/rustdoc-gui/sidebar-mobile.goml b/src/test/rustdoc-gui/sidebar-mobile.goml
index f0c9361d080..7138f916675 100644
--- a/src/test/rustdoc-gui/sidebar-mobile.goml
+++ b/src/test/rustdoc-gui/sidebar-mobile.goml
@@ -13,7 +13,7 @@ click: ".sidebar-menu"
 assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"})
 // Force the sidebar open by focusing a link inside it.
 // This makes it easier for keyboard users to get to it.
-focus: ".sidebar-title"
+focus: ".sidebar-title a"
 assert-css: (".sidebar-elems", {"display": "block", "left": "0px"})
 // When we tab out of the sidebar, close it.
 focus: ".search-input"
diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs
index 0466909479b..cd00348cad3 100644
--- a/src/test/rustdoc-gui/src/lib2/lib.rs
+++ b/src/test/rustdoc-gui/src/lib2/lib.rs
@@ -1,5 +1,7 @@
 // ignore-tidy-linelength
 
+#![feature(doc_cfg)]
+
 pub mod module {
     pub mod sub_module {
         pub mod sub_sub_module {
@@ -14,6 +16,7 @@ pub fn foobar() {}
 
 pub type Alias = u32;
 
+#[doc(cfg(feature = "foo-method"))]
 pub struct Foo {
     pub x: Alias,
 }
diff --git a/src/test/rustdoc-ui/nocapture-fail.rs b/src/test/rustdoc-ui/nocapture-fail.rs
new file mode 100644
index 00000000000..7706bd1f3e3
--- /dev/null
+++ b/src/test/rustdoc-ui/nocapture-fail.rs
@@ -0,0 +1,12 @@
+// check-pass
+// compile-flags:--test -Zunstable-options --nocapture
+// normalize-stderr-test: "src/test/rustdoc-ui" -> "$$DIR"
+// 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 00000000000..16a5ac47cd2
--- /dev/null
+++ b/src/test/rustdoc-ui/nocapture-fail.stderr
@@ -0,0 +1,18 @@
+error: struct literal body without path
+  --> $DIR/nocapture-fail.rs:8: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 00000000000..754f77db53c
--- /dev/null
+++ b/src/test/rustdoc-ui/nocapture-fail.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/nocapture-fail.rs - Foo (line 7) - 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 00000000000..321f5ca08ed
--- /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 00000000000..af6415db3c7
--- /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 00000000000..4880e75da70
--- /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/rustdoc/deref-typedef.rs b/src/test/rustdoc/deref-typedef.rs
index 3fc48b46d74..d42ff384b29 100644
--- a/src/test/rustdoc/deref-typedef.rs
+++ b/src/test/rustdoc/deref-typedef.rs
@@ -6,7 +6,7 @@
 // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)'
 // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)'
 // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)'
-// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods"]' 'Methods from Deref<Target=FooJ>'
+// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods"]' 'Methods from Deref<Target=FooJ>'
 // @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a'
 // @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b'
 // @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c'
diff --git a/src/test/rustdoc/negative-impl-sidebar.rs b/src/test/rustdoc/negative-impl-sidebar.rs
index 3414d954077..d63ab346045 100644
--- a/src/test/rustdoc/negative-impl-sidebar.rs
+++ b/src/test/rustdoc/negative-impl-sidebar.rs
@@ -4,6 +4,6 @@
 pub struct Foo;
 
 // @has foo/struct.Foo.html
-// @has - '//*[@class="sidebar-title"][@href="#trait-implementations"]' 'Trait Implementations'
+// @has - '//*[@class="sidebar-title"]/a[@href="#trait-implementations"]' 'Trait Implementations'
 // @has - '//*[@class="sidebar-links"]/a' '!Sync'
 impl !Sync for Foo {}
diff --git a/src/test/rustdoc/sidebar-items.rs b/src/test/rustdoc/sidebar-items.rs
index 3ba6dbacc8d..5da660b4df3 100644
--- a/src/test/rustdoc/sidebar-items.rs
+++ b/src/test/rustdoc/sidebar-items.rs
@@ -1,13 +1,13 @@
 #![crate_name = "foo"]
 
 // @has foo/trait.Foo.html
-// @has - '//*[@class="sidebar-title"][@href="#required-methods"]' 'Required Methods'
+// @has - '//*[@class="sidebar-title"]/a[@href="#required-methods"]' 'Required Methods'
 // @has - '//*[@class="sidebar-links"]/a' 'bar'
-// @has - '//*[@class="sidebar-title"][@href="#provided-methods"]' 'Provided Methods'
+// @has - '//*[@class="sidebar-title"]/a[@href="#provided-methods"]' 'Provided Methods'
 // @has - '//*[@class="sidebar-links"]/a' 'foo'
-// @has - '//*[@class="sidebar-title"][@href="#associated-const"]' 'Associated Constants'
+// @has - '//*[@class="sidebar-title"]/a[@href="#associated-const"]' 'Associated Constants'
 // @has - '//*[@class="sidebar-links"]/a' 'BAR'
-// @has - '//*[@class="sidebar-title"][@href="#associated-types"]' 'Associated Types'
+// @has - '//*[@class="sidebar-title"]/a[@href="#associated-types"]' 'Associated Types'
 // @has - '//*[@class="sidebar-links"]/a' 'Output'
 pub trait Foo {
     const BAR: u32 = 0;
@@ -18,7 +18,7 @@ pub trait Foo {
 }
 
 // @has foo/struct.Bar.html
-// @has - '//*[@class="sidebar-title"][@href="#fields"]' 'Fields'
+// @has - '//*[@class="sidebar-title"]/a[@href="#fields"]' 'Fields'
 // @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f"]' 'f'
 // @has - '//*[@class="sidebar-links"]/a[@href="#structfield.u"]' 'u'
 // @!has - '//*[@class="sidebar-links"]/a' 'waza'
@@ -29,7 +29,7 @@ pub struct Bar {
 }
 
 // @has foo/enum.En.html
-// @has - '//*[@class="sidebar-title"][@href="#variants"]' 'Variants'
+// @has - '//*[@class="sidebar-title"]/a[@href="#variants"]' 'Variants'
 // @has - '//*[@class="sidebar-links"]/a' 'foo'
 // @has - '//*[@class="sidebar-links"]/a' 'bar'
 pub enum En {
@@ -38,7 +38,7 @@ pub enum En {
 }
 
 // @has foo/union.MyUnion.html
-// @has - '//*[@class="sidebar-title"][@href="#fields"]' 'Fields'
+// @has - '//*[@class="sidebar-title"]/a[@href="#fields"]' 'Fields'
 // @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f1"]' 'f1'
 // @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f2"]' 'f2'
 // @!has - '//*[@class="sidebar-links"]/a' 'waza'
diff --git a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs
index d256fbe8de0..e73c5b4f640 100644
--- a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs
+++ b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs
@@ -3,7 +3,7 @@
 #![crate_name = "foo"]
 
 // @has foo/trait.Foo.html
-// @has - '//*[@class="sidebar-title"][@href="#foreign-impls"]' 'Implementations on Foreign Types'
+// @has - '//*[@class="sidebar-title"]/a[@href="#foreign-impls"]' 'Implementations on Foreign Types'
 // @has - '//h2[@id="foreign-impls"]' 'Implementations on Foreign Types'
 // @has - '//*[@class="sidebar-links"]/a[@href="#impl-Foo-for-u32"]' 'u32'
 // @has - '//div[@id="impl-Foo-for-u32"]//code' 'impl Foo for u32'
diff --git a/src/test/rustdoc/typedef.rs b/src/test/rustdoc/typedef.rs
index 21a7fdda769..479cd91a9dc 100644
--- a/src/test/rustdoc/typedef.rs
+++ b/src/test/rustdoc/typedef.rs
@@ -12,7 +12,7 @@ impl MyStruct {
 // @has - '//*[@class="impl has-srclink"]//code' 'impl MyAlias'
 // @has - '//*[@class="impl has-srclink"]//code' 'impl MyTrait for MyAlias'
 // @has - 'Alias docstring'
-// @has - '//*[@class="sidebar"]//p[@class="location"]' 'Type Definition MyAlias'
+// @has - '//*[@class="sidebar"]//*[@class="location"]' 'Type Definition MyAlias'
 // @has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Methods'
 // @has - '//*[@class="sidebar"]//a[@href="#trait-implementations"]' 'Trait Implementations'
 /// Alias docstring
diff --git a/src/test/ui/associated-types/defaults-wf.stderr b/src/test/ui/associated-types/defaults-wf.stderr
index d4fa5be742f..73ef567ffae 100644
--- a/src/test/ui/associated-types/defaults-wf.stderr
+++ b/src/test/ui/associated-types/defaults-wf.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/defaults-wf.rs:7:5
+  --> $DIR/defaults-wf.rs:7:15
    |
 LL |     type Ty = Vec<[u8]>;
-   |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |               ^^^^^^^^^ doesn't have a size known at compile-time
    | 
   ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
    |
diff --git a/src/test/ui/wf/wf-trait-associated-type-trait.rs b/src/test/ui/wf/wf-trait-associated-type-trait.rs
index ddc0b323a11..d67e110edee 100644
--- a/src/test/ui/wf/wf-trait-associated-type-trait.rs
+++ b/src/test/ui/wf/wf-trait-associated-type-trait.rs
@@ -8,7 +8,7 @@ struct IsCopy<T:Copy> { x: T }
 
 trait SomeTrait {
     type Type1;
-    type Type2 = IsCopy<Self::Type1>;
+    type Type2 = (IsCopy<Self::Type1>, bool);
     //~^ ERROR E0277
 }
 
diff --git a/src/test/ui/wf/wf-trait-associated-type-trait.stderr b/src/test/ui/wf/wf-trait-associated-type-trait.stderr
index a139186ebb6..d1c2c65043d 100644
--- a/src/test/ui/wf/wf-trait-associated-type-trait.stderr
+++ b/src/test/ui/wf/wf-trait-associated-type-trait.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `<Self as SomeTrait>::Type1: Copy` is not satisfied
-  --> $DIR/wf-trait-associated-type-trait.rs:11:5
+  --> $DIR/wf-trait-associated-type-trait.rs:11:19
    |
 LL | struct IsCopy<T:Copy> { x: T }
    |                 ---- required by this bound in `IsCopy`
 ...
-LL |     type Type2 = IsCopy<Self::Type1>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `<Self as SomeTrait>::Type1`
+LL |     type Type2 = (IsCopy<Self::Type1>, bool);
+   |                   ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `<Self as SomeTrait>::Type1`
    |
 help: consider further restricting the associated type
    |
diff --git a/triagebot.toml b/triagebot.toml
index 968b80414bc..bf30927448a 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -117,3 +117,5 @@ format = "rustc"
 project-name = "Rust"
 changelog-path = "RELEASES.md"
 changelog-branch = "master"
+
+[shortcut]