about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-08-19 03:45:50 +0000
committerbors <bors@rust-lang.org>2021-08-19 03:45:50 +0000
commitad1eaffc7e24f497e969c47f400ad20ae383f9aa (patch)
tree73902e1b4a0079845cf5a0cd0a45e14eb7de1578
parent6d300391ede6de79469670957b508072d132a2a0 (diff)
parent9bbb57c6ab4d0693b42e6a050ba9ddf8b857a804 (diff)
Auto merge of #88143 - GuillaumeGomez:rollup-sgh318f, r=GuillaumeGomez
Rollup of 10 pull requests

Successful merges:

 - #87818 (Fix anchors display in rustdoc)
 - #87983 (Use more accurate spans when proposing adding lifetime to item)
 - #88012 (Change WASI's `RawFd` from `u32` to `c_int` (`i32`).)
 - #88031 (Make `BuildHasher` object safe)
 - #88036 (Fix dead code warning when inline const is used in pattern)
 - #88082 (Take into account jobs number for rustdoc GUI tests)
 - #88109 (Fix environment variable getter docs)
 - #88111 (Add background-color on clickable definitions in source code)
 - #88129 (Fix dataflow graphviz bug, make dataflow graphviz modules public)
 - #88136 (Move private_unused.rs test to impl-trait)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_mir/src/dataflow/framework/fmt.rs2
-rw-r--r--compiler/rustc_mir/src/dataflow/framework/mod.rs2
-rw-r--r--compiler/rustc_mir/src/dataflow/mod.rs2
-rw-r--r--compiler/rustc_mir/src/util/mod.rs2
-rw-r--r--compiler/rustc_passes/src/dead.rs7
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs86
-rw-r--r--library/core/src/hash/mod.rs5
-rw-r--r--library/core/tests/hash/mod.rs9
-rw-r--r--library/std/src/env.rs19
-rw-r--r--library/std/src/os/wasi/io.rs21
-rw-r--r--library/std/src/sys/wasi/fd.rs89
-rw-r--r--library/std/src/sys/wasi/fs.rs7
-rw-r--r--library/std/src/sys/wasi/net.rs13
-rw-r--r--library/std/src/sys/wasi/stdio.rs7
-rw-r--r--src/bootstrap/test.rs2
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css3
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css3
-rw-r--r--src/librustdoc/html/static/css/themes/light.css3
-rw-r--r--src/test/ui/error-codes/E0106.stderr2
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr2
-rw-r--r--src/test/ui/impl-header-lifetime-elision/assoc-type.stderr2
-rw-r--r--src/test/ui/impl-trait/private_unused.rs (renamed from src/test/ui/type-alias-impl-trait/private_unused.rs)0
-rw-r--r--src/test/ui/issues/issue-19707.stderr8
-rw-r--r--src/test/ui/issues/issue-26638.stderr2
-rw-r--r--src/test/ui/issues/issue-30255.stderr6
-rw-r--r--src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr4
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr2
-rw-r--r--src/test/ui/lint/dead-code/anon-const-in-pat.rs45
-rw-r--r--src/test/ui/rfc1623-2.stderr4
-rw-r--r--src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr4
-rw-r--r--src/test/ui/suggestions/issue-84592.stderr2
-rw-r--r--src/test/ui/suggestions/issue-86667.stderr4
-rw-r--r--src/test/ui/suggestions/missing-lt-for-hrtb.stderr2
-rw-r--r--src/test/ui/suggestions/return-elided-lifetime.stderr12
-rw-r--r--src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr2
-rw-r--r--src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr2
-rw-r--r--src/tools/rustdoc-gui/tester.js24
37 files changed, 303 insertions, 108 deletions
diff --git a/compiler/rustc_mir/src/dataflow/framework/fmt.rs b/compiler/rustc_mir/src/dataflow/framework/fmt.rs
index 0140a750544..35115ca9db7 100644
--- a/compiler/rustc_mir/src/dataflow/framework/fmt.rs
+++ b/compiler/rustc_mir/src/dataflow/framework/fmt.rs
@@ -33,7 +33,7 @@ pub trait DebugWithContext<C>: Eq + fmt::Debug {
         }
 
         write!(f, "\u{001f}-")?;
-        self.fmt_with(ctxt, f)
+        old.fmt_with(ctxt, f)
     }
 }
 
diff --git a/compiler/rustc_mir/src/dataflow/framework/mod.rs b/compiler/rustc_mir/src/dataflow/framework/mod.rs
index 344d7b9becd..a5badc07d10 100644
--- a/compiler/rustc_mir/src/dataflow/framework/mod.rs
+++ b/compiler/rustc_mir/src/dataflow/framework/mod.rs
@@ -42,7 +42,7 @@ mod cursor;
 mod direction;
 mod engine;
 pub mod fmt;
-mod graphviz;
+pub mod graphviz;
 pub mod lattice;
 mod visitor;
 
diff --git a/compiler/rustc_mir/src/dataflow/mod.rs b/compiler/rustc_mir/src/dataflow/mod.rs
index 03531a6b004..4ca757cf269 100644
--- a/compiler/rustc_mir/src/dataflow/mod.rs
+++ b/compiler/rustc_mir/src/dataflow/mod.rs
@@ -5,7 +5,7 @@ use rustc_span::symbol::{sym, Symbol};
 
 pub(crate) use self::drop_flag_effects::*;
 pub use self::framework::{
-    fmt, lattice, visit_results, Analysis, AnalysisDomain, Backward, BorrowckFlowState,
+    fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, BorrowckFlowState,
     BorrowckResults, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results,
     ResultsCursor, ResultsRefCursor, ResultsVisitor, SwitchIntEdgeEffects,
 };
diff --git a/compiler/rustc_mir/src/util/mod.rs b/compiler/rustc_mir/src/util/mod.rs
index b7b702431bc..3e466b5060f 100644
--- a/compiler/rustc_mir/src/util/mod.rs
+++ b/compiler/rustc_mir/src/util/mod.rs
@@ -18,4 +18,4 @@ pub use self::alignment::is_disaligned;
 pub use self::find_self_call::find_self_call;
 pub use self::generic_graph::graphviz_safe_def_name;
 pub use self::graphviz::write_mir_graphviz;
-pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere};
+pub use self::pretty::{dump_enabled, dump_mir, write_mir_fn, write_mir_pretty, PassWhere};
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 4e157b0a574..ae65222f3f2 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -15,6 +15,7 @@ use rustc_middle::middle::privacy;
 use rustc_middle::ty::{self, DefIdTree, TyCtxt};
 use rustc_session::lint;
 use rustc_span::symbol::{sym, Symbol};
+use std::mem;
 
 // Any local node that may call something in its body block should be
 // explored. For example, if it's a live Node::Item that is a
@@ -395,8 +396,14 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
     }
 
     fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
+        // When inline const blocks are used in pattern position, paths
+        // referenced by it should be considered as used.
+        let in_pat = mem::replace(&mut self.in_pat, false);
+
         self.live_symbols.insert(self.tcx.hir().local_def_id(c.hir_id));
         intravisit::walk_anon_const(self, c);
+
+        self.in_pat = in_pat;
     }
 }
 
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 7c97a17b454..a602a58e517 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2073,20 +2073,85 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                         continue;
                     }
                 });
+
+                struct Lifetime(Span, String);
+                impl Lifetime {
+                    fn is_unnamed(&self) -> bool {
+                        self.1.starts_with('&') && !self.1.starts_with("&'")
+                    }
+                    fn is_underscore(&self) -> bool {
+                        self.1.starts_with("&'_ ")
+                    }
+                    fn is_named(&self) -> bool {
+                        self.1.starts_with("&'")
+                    }
+                    fn suggestion(&self, sugg: String) -> Option<(Span, String)> {
+                        Some(
+                            match (
+                                self.is_unnamed(),
+                                self.is_underscore(),
+                                self.is_named(),
+                                sugg.starts_with("&"),
+                            ) {
+                                (true, _, _, false) => (self.span_unnamed_borrow(), sugg),
+                                (true, _, _, true) => {
+                                    (self.span_unnamed_borrow(), sugg[1..].to_string())
+                                }
+                                (_, true, _, false) => {
+                                    (self.span_underscore_borrow(), sugg.trim().to_string())
+                                }
+                                (_, true, _, true) => {
+                                    (self.span_underscore_borrow(), sugg[1..].trim().to_string())
+                                }
+                                (_, _, true, false) => {
+                                    (self.span_named_borrow(), sugg.trim().to_string())
+                                }
+                                (_, _, true, true) => {
+                                    (self.span_named_borrow(), sugg[1..].trim().to_string())
+                                }
+                                _ => return None,
+                            },
+                        )
+                    }
+                    fn span_unnamed_borrow(&self) -> Span {
+                        let lo = self.0.lo() + BytePos(1);
+                        self.0.with_lo(lo).with_hi(lo)
+                    }
+                    fn span_named_borrow(&self) -> Span {
+                        let lo = self.0.lo() + BytePos(1);
+                        self.0.with_lo(lo)
+                    }
+                    fn span_underscore_borrow(&self) -> Span {
+                        let lo = self.0.lo() + BytePos(1);
+                        let hi = lo + BytePos(2);
+                        self.0.with_lo(lo).with_hi(hi)
+                    }
+                }
+
                 for param in params {
                     if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) {
-                        if snippet.starts_with('&') && !snippet.starts_with("&'") {
-                            introduce_suggestion
-                                .push((param.span, format!("&'a {}", &snippet[1..])));
-                        } else if let Some(stripped) = snippet.strip_prefix("&'_ ") {
-                            introduce_suggestion.push((param.span, format!("&'a {}", &stripped)));
+                        if let Some((span, sugg)) =
+                            Lifetime(param.span, snippet).suggestion("'a ".to_string())
+                        {
+                            introduce_suggestion.push((span, sugg));
                         }
                     }
                 }
-                for ((span, _), sugg) in spans_with_counts.iter().copied().zip(suggs.iter()) {
-                    if let Some(sugg) = sugg {
-                        introduce_suggestion.push((span, sugg.to_string()));
-                    }
+                for (span, sugg) in spans_with_counts.iter().copied().zip(suggs.iter()).filter_map(
+                    |((span, _), sugg)| match &sugg {
+                        Some(sugg) => Some((span, sugg.to_string())),
+                        _ => None,
+                    },
+                ) {
+                    let (span, sugg) = self
+                        .tcx
+                        .sess
+                        .source_map()
+                        .span_to_snippet(span)
+                        .ok()
+                        .and_then(|snippet| Lifetime(span, snippet).suggestion(sugg.clone()))
+                        .unwrap_or((span, sugg));
+                    introduce_suggestion.push((span, sugg.to_string()));
                 }
                 err.multipart_suggestion_with_style(
                     &msg,
@@ -2159,7 +2224,8 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                 for ((span, _), snippet) in spans_with_counts.iter().copied().zip(snippets.iter()) {
                     match snippet.as_deref() {
                         Some("") => spans_suggs.push((span, "'lifetime, ".to_string())),
-                        Some("&") => spans_suggs.push((span, "&'lifetime ".to_string())),
+                        Some("&") => spans_suggs
+                            .push((span.with_lo(span.lo() + BytePos(1)), "'lifetime ".to_string())),
                         _ => {}
                     }
                 }
diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs
index 510e233b431..77161e961e7 100644
--- a/library/core/src/hash/mod.rs
+++ b/library/core/src/hash/mod.rs
@@ -520,7 +520,10 @@ pub trait BuildHasher {
     /// );
     /// ```
     #[unstable(feature = "build_hasher_simple_hash_one", issue = "86161")]
-    fn hash_one<T: Hash>(&self, x: T) -> u64 {
+    fn hash_one<T: Hash>(&self, x: T) -> u64
+    where
+        Self: Sized,
+    {
         let mut hasher = self.build_hasher();
         x.hash(&mut hasher);
         hasher.finish()
diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs
index 1566d357490..72ccdd4848a 100644
--- a/library/core/tests/hash/mod.rs
+++ b/library/core/tests/hash/mod.rs
@@ -1,7 +1,7 @@
 mod sip;
 
 use std::default::Default;
-use std::hash::{Hash, Hasher};
+use std::hash::{BuildHasher, Hash, Hasher};
 use std::rc::Rc;
 
 struct MyHasher {
@@ -139,3 +139,10 @@ fn test_indirect_hasher() {
     }
     assert_eq!(hasher.hash, 5);
 }
+
+#[test]
+fn test_build_hasher_object_safe() {
+    use std::collections::hash_map::{DefaultHasher, RandomState};
+
+    let _: &dyn BuildHasher<Hasher = DefaultHasher> = &RandomState::new();
+}
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index f9f14d0dc63..a7465200955 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -185,9 +185,13 @@ impl fmt::Debug for VarsOs {
 ///
 /// # Errors
 ///
-/// Returns `[None]` if the environment variable isn't set.
-/// Returns `[None]` if the environment variable is not valid Unicode. If this is not
-/// desired, consider using [`var_os`].
+/// This function will return an error if the environment variable isn't set.
+///
+/// This function may return an error if the environment variable's name contains
+/// the equal sign character (`=`) or the NUL character.
+///
+/// This function will return an error if the environment variable's value is
+/// not valid Unicode. If this is not desired, consider using [`var_os`].
 ///
 /// # Examples
 ///
@@ -221,8 +225,13 @@ fn _var(key: &OsStr) -> Result<String, VarError> {
 ///
 /// # Errors
 ///
-/// Returns `[None]` if the variable isn't set.
-/// May return `[None]` if the variable value contains the NUL character.
+/// This function returns an error if the environment variable isn't set.
+///
+/// This function may return an error if the environment variable's name contains
+/// the equal sign character (`=`) or the NUL character.
+///
+/// This function may return an error if the environment variable's value contains
+/// the NUL character.
 ///
 /// # Examples
 ///
diff --git a/library/std/src/os/wasi/io.rs b/library/std/src/os/wasi/io.rs
index cf4501b98cb..b6bc74da8e7 100644
--- a/library/std/src/os/wasi/io.rs
+++ b/library/std/src/os/wasi/io.rs
@@ -6,11 +6,18 @@
 use crate::fs;
 use crate::io;
 use crate::net;
+use crate::os::raw;
 use crate::sys;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 
 /// Raw file descriptors.
-pub type RawFd = u32;
+///
+/// This has type `c_int` to ease compatibility with code that also compiles on
+/// Unix configurations, however unlike Unix and POSIX, in WASI negative file
+/// descriptors are valid. Only `-1` is reserved for indicating errors. Code
+/// intending to be portable across Unix platforms and WASI should avoid
+/// assuming that negative file descriptors are invalid.
+pub type RawFd = raw::c_int;
 
 /// A trait to extract the raw WASI file descriptor from an underlying
 /// object.
@@ -161,41 +168,41 @@ impl IntoRawFd for fs::File {
 impl AsRawFd for io::Stdin {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
-        libc::STDIN_FILENO as RawFd
+        libc::STDIN_FILENO
     }
 }
 
 impl AsRawFd for io::Stdout {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
-        libc::STDOUT_FILENO as RawFd
+        libc::STDOUT_FILENO
     }
 }
 
 impl AsRawFd for io::Stderr {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
-        libc::STDERR_FILENO as RawFd
+        libc::STDERR_FILENO
     }
 }
 
 impl<'a> AsRawFd for io::StdinLock<'a> {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
-        libc::STDIN_FILENO as RawFd
+        libc::STDIN_FILENO
     }
 }
 
 impl<'a> AsRawFd for io::StdoutLock<'a> {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
-        libc::STDOUT_FILENO as RawFd
+        libc::STDOUT_FILENO
     }
 }
 
 impl<'a> AsRawFd for io::StderrLock<'a> {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
-        libc::STDERR_FILENO as RawFd
+        libc::STDERR_FILENO
     }
 }
diff --git a/library/std/src/sys/wasi/fd.rs b/library/std/src/sys/wasi/fd.rs
index ba66eba2ad3..1f6ea8d6e8d 100644
--- a/library/std/src/sys/wasi/fd.rs
+++ b/library/std/src/sys/wasi/fd.rs
@@ -5,10 +5,11 @@ use super::err2io;
 use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
 use crate::mem;
 use crate::net::Shutdown;
+use crate::os::raw::c_int;
 
 #[derive(Debug)]
 pub struct WasiFd {
-    fd: wasi::Fd,
+    fd: c_int,
 }
 
 fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] {
@@ -26,38 +27,38 @@ fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] {
 }
 
 impl WasiFd {
-    pub unsafe fn from_raw(fd: wasi::Fd) -> WasiFd {
+    pub unsafe fn from_raw(fd: c_int) -> WasiFd {
         WasiFd { fd }
     }
 
-    pub fn into_raw(self) -> wasi::Fd {
+    pub fn into_raw(self) -> c_int {
         let ret = self.fd;
         mem::forget(self);
         ret
     }
 
-    pub fn as_raw(&self) -> wasi::Fd {
+    pub fn as_raw(&self) -> c_int {
         self.fd
     }
 
     pub fn datasync(&self) -> io::Result<()> {
-        unsafe { wasi::fd_datasync(self.fd).map_err(err2io) }
+        unsafe { wasi::fd_datasync(self.fd as wasi::Fd).map_err(err2io) }
     }
 
     pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
-        unsafe { wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(err2io) }
+        unsafe { wasi::fd_pread(self.fd as wasi::Fd, iovec(bufs), offset).map_err(err2io) }
     }
 
     pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
-        unsafe { wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(err2io) }
+        unsafe { wasi::fd_pwrite(self.fd as wasi::Fd, ciovec(bufs), offset).map_err(err2io) }
     }
 
     pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        unsafe { wasi::fd_read(self.fd, iovec(bufs)).map_err(err2io) }
+        unsafe { wasi::fd_read(self.fd as wasi::Fd, iovec(bufs)).map_err(err2io) }
     }
 
     pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        unsafe { wasi::fd_write(self.fd, ciovec(bufs)).map_err(err2io) }
+        unsafe { wasi::fd_write(self.fd as wasi::Fd, ciovec(bufs)).map_err(err2io) }
     }
 
     pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
@@ -66,37 +67,37 @@ impl WasiFd {
             SeekFrom::End(pos) => (wasi::WHENCE_END, pos),
             SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos),
         };
-        unsafe { wasi::fd_seek(self.fd, offset, whence).map_err(err2io) }
+        unsafe { wasi::fd_seek(self.fd as wasi::Fd, offset, whence).map_err(err2io) }
     }
 
     pub fn tell(&self) -> io::Result<u64> {
-        unsafe { wasi::fd_tell(self.fd).map_err(err2io) }
+        unsafe { wasi::fd_tell(self.fd as wasi::Fd).map_err(err2io) }
     }
 
     // FIXME: __wasi_fd_fdstat_get
 
     pub fn set_flags(&self, flags: wasi::Fdflags) -> io::Result<()> {
-        unsafe { wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) }
+        unsafe { wasi::fd_fdstat_set_flags(self.fd as wasi::Fd, flags).map_err(err2io) }
     }
 
     pub fn set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()> {
-        unsafe { wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(err2io) }
+        unsafe { wasi::fd_fdstat_set_rights(self.fd as wasi::Fd, base, inheriting).map_err(err2io) }
     }
 
     pub fn sync(&self) -> io::Result<()> {
-        unsafe { wasi::fd_sync(self.fd).map_err(err2io) }
+        unsafe { wasi::fd_sync(self.fd as wasi::Fd).map_err(err2io) }
     }
 
     pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> {
-        unsafe { wasi::fd_advise(self.fd, offset, len, advice).map_err(err2io) }
+        unsafe { wasi::fd_advise(self.fd as wasi::Fd, offset, len, advice).map_err(err2io) }
     }
 
     pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
-        unsafe { wasi::fd_allocate(self.fd, offset, len).map_err(err2io) }
+        unsafe { wasi::fd_allocate(self.fd as wasi::Fd, offset, len).map_err(err2io) }
     }
 
     pub fn create_directory(&self, path: &str) -> io::Result<()> {
-        unsafe { wasi::path_create_directory(self.fd, path).map_err(err2io) }
+        unsafe { wasi::path_create_directory(self.fd as wasi::Fd, path).map_err(err2io) }
     }
 
     pub fn link(
@@ -107,7 +108,14 @@ impl WasiFd {
         new_path: &str,
     ) -> io::Result<()> {
         unsafe {
-            wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path).map_err(err2io)
+            wasi::path_link(
+                self.fd as wasi::Fd,
+                old_flags,
+                old_path,
+                new_fd.fd as wasi::Fd,
+                new_path,
+            )
+            .map_err(err2io)
         }
     }
 
@@ -122,7 +130,7 @@ impl WasiFd {
     ) -> io::Result<WasiFd> {
         unsafe {
             wasi::path_open(
-                self.fd,
+                self.fd as wasi::Fd,
                 dirflags,
                 path,
                 oflags,
@@ -130,25 +138,34 @@ impl WasiFd {
                 fs_rights_inheriting,
                 fs_flags,
             )
-            .map(|fd| WasiFd::from_raw(fd))
+            .map(|fd| WasiFd::from_raw(fd as c_int))
             .map_err(err2io)
         }
     }
 
     pub fn readdir(&self, buf: &mut [u8], cookie: wasi::Dircookie) -> io::Result<usize> {
-        unsafe { wasi::fd_readdir(self.fd, buf.as_mut_ptr(), buf.len(), cookie).map_err(err2io) }
+        unsafe {
+            wasi::fd_readdir(self.fd as wasi::Fd, buf.as_mut_ptr(), buf.len(), cookie)
+                .map_err(err2io)
+        }
     }
 
     pub fn readlink(&self, path: &str, buf: &mut [u8]) -> io::Result<usize> {
-        unsafe { wasi::path_readlink(self.fd, path, buf.as_mut_ptr(), buf.len()).map_err(err2io) }
+        unsafe {
+            wasi::path_readlink(self.fd as wasi::Fd, path, buf.as_mut_ptr(), buf.len())
+                .map_err(err2io)
+        }
     }
 
     pub fn rename(&self, old_path: &str, new_fd: &WasiFd, new_path: &str) -> io::Result<()> {
-        unsafe { wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io) }
+        unsafe {
+            wasi::path_rename(self.fd as wasi::Fd, old_path, new_fd.fd as wasi::Fd, new_path)
+                .map_err(err2io)
+        }
     }
 
     pub fn filestat_get(&self) -> io::Result<wasi::Filestat> {
-        unsafe { wasi::fd_filestat_get(self.fd).map_err(err2io) }
+        unsafe { wasi::fd_filestat_get(self.fd as wasi::Fd).map_err(err2io) }
     }
 
     pub fn filestat_set_times(
@@ -157,11 +174,13 @@ impl WasiFd {
         mtim: wasi::Timestamp,
         fstflags: wasi::Fstflags,
     ) -> io::Result<()> {
-        unsafe { wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags).map_err(err2io) }
+        unsafe {
+            wasi::fd_filestat_set_times(self.fd as wasi::Fd, atim, mtim, fstflags).map_err(err2io)
+        }
     }
 
     pub fn filestat_set_size(&self, size: u64) -> io::Result<()> {
-        unsafe { wasi::fd_filestat_set_size(self.fd, size).map_err(err2io) }
+        unsafe { wasi::fd_filestat_set_size(self.fd as wasi::Fd, size).map_err(err2io) }
     }
 
     pub fn path_filestat_get(
@@ -169,7 +188,7 @@ impl WasiFd {
         flags: wasi::Lookupflags,
         path: &str,
     ) -> io::Result<wasi::Filestat> {
-        unsafe { wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) }
+        unsafe { wasi::path_filestat_get(self.fd as wasi::Fd, flags, path).map_err(err2io) }
     }
 
     pub fn path_filestat_set_times(
@@ -181,21 +200,21 @@ impl WasiFd {
         fstflags: wasi::Fstflags,
     ) -> io::Result<()> {
         unsafe {
-            wasi::path_filestat_set_times(self.fd, flags, path, atim, mtim, fstflags)
+            wasi::path_filestat_set_times(self.fd as wasi::Fd, flags, path, atim, mtim, fstflags)
                 .map_err(err2io)
         }
     }
 
     pub fn symlink(&self, old_path: &str, new_path: &str) -> io::Result<()> {
-        unsafe { wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) }
+        unsafe { wasi::path_symlink(old_path, self.fd as wasi::Fd, new_path).map_err(err2io) }
     }
 
     pub fn unlink_file(&self, path: &str) -> io::Result<()> {
-        unsafe { wasi::path_unlink_file(self.fd, path).map_err(err2io) }
+        unsafe { wasi::path_unlink_file(self.fd as wasi::Fd, path).map_err(err2io) }
     }
 
     pub fn remove_directory(&self, path: &str) -> io::Result<()> {
-        unsafe { wasi::path_remove_directory(self.fd, path).map_err(err2io) }
+        unsafe { wasi::path_remove_directory(self.fd as wasi::Fd, path).map_err(err2io) }
     }
 
     pub fn sock_recv(
@@ -203,11 +222,11 @@ impl WasiFd {
         ri_data: &mut [IoSliceMut<'_>],
         ri_flags: wasi::Riflags,
     ) -> io::Result<(usize, wasi::Roflags)> {
-        unsafe { wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(err2io) }
+        unsafe { wasi::sock_recv(self.fd as wasi::Fd, iovec(ri_data), ri_flags).map_err(err2io) }
     }
 
     pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::Siflags) -> io::Result<usize> {
-        unsafe { wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(err2io) }
+        unsafe { wasi::sock_send(self.fd as wasi::Fd, ciovec(si_data), si_flags).map_err(err2io) }
     }
 
     pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> {
@@ -216,7 +235,7 @@ impl WasiFd {
             Shutdown::Write => wasi::SDFLAGS_WR,
             Shutdown::Both => wasi::SDFLAGS_WR | wasi::SDFLAGS_RD,
         };
-        unsafe { wasi::sock_shutdown(self.fd, how).map_err(err2io) }
+        unsafe { wasi::sock_shutdown(self.fd as wasi::Fd, how).map_err(err2io) }
     }
 }
 
@@ -224,6 +243,6 @@ impl Drop for WasiFd {
     fn drop(&mut self) {
         // FIXME: can we handle the return code here even though we can't on
         // unix?
-        let _ = unsafe { wasi::fd_close(self.fd) };
+        let _ = unsafe { wasi::fd_close(self.fd as wasi::Fd) };
     }
 }
diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs
index 8ffa1c88d88..55c9c652a8b 100644
--- a/library/std/src/sys/wasi/fs.rs
+++ b/library/std/src/sys/wasi/fs.rs
@@ -6,6 +6,7 @@ use crate::fmt;
 use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
 use crate::iter;
 use crate::mem::{self, ManuallyDrop};
+use crate::os::raw::c_int;
 use crate::os::wasi::ffi::{OsStrExt, OsStringExt};
 use crate::path::{Path, PathBuf};
 use crate::ptr;
@@ -454,8 +455,8 @@ impl File {
     }
 }
 
-impl FromInner<u32> for File {
-    fn from_inner(fd: u32) -> File {
+impl FromInner<c_int> for File {
+    fn from_inner(fd: c_int) -> File {
         unsafe { File { fd: WasiFd::from_raw(fd) } }
     }
 }
@@ -653,7 +654,7 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
             let relative = CStr::from_ptr(relative_path).to_bytes().to_vec();
 
             return Ok((
-                ManuallyDrop::new(WasiFd::from_raw(fd as u32)),
+                ManuallyDrop::new(WasiFd::from_raw(fd as c_int)),
                 PathBuf::from(OsString::from_vec(relative)),
             ));
         }
diff --git a/library/std/src/sys/wasi/net.rs b/library/std/src/sys/wasi/net.rs
index 06860673d90..50b7352933e 100644
--- a/library/std/src/sys/wasi/net.rs
+++ b/library/std/src/sys/wasi/net.rs
@@ -5,6 +5,7 @@ use crate::convert::TryFrom;
 use crate::fmt;
 use crate::io::{self, IoSlice, IoSliceMut};
 use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
+use crate::os::raw::c_int;
 use crate::sys::unsupported;
 use crate::sys_common::FromInner;
 use crate::time::Duration;
@@ -115,8 +116,8 @@ impl TcpStream {
     }
 }
 
-impl FromInner<u32> for TcpStream {
-    fn from_inner(fd: u32) -> TcpStream {
+impl FromInner<c_int> for TcpStream {
+    fn from_inner(fd: c_int) -> TcpStream {
         unsafe { TcpStream { fd: WasiFd::from_raw(fd) } }
     }
 }
@@ -181,8 +182,8 @@ impl TcpListener {
     }
 }
 
-impl FromInner<u32> for TcpListener {
-    fn from_inner(fd: u32) -> TcpListener {
+impl FromInner<c_int> for TcpListener {
+    fn from_inner(fd: c_int) -> TcpListener {
         unsafe { TcpListener { fd: WasiFd::from_raw(fd) } }
     }
 }
@@ -331,8 +332,8 @@ impl UdpSocket {
     }
 }
 
-impl FromInner<u32> for UdpSocket {
-    fn from_inner(fd: u32) -> UdpSocket {
+impl FromInner<c_int> for UdpSocket {
+    fn from_inner(fd: c_int) -> UdpSocket {
         unsafe { UdpSocket { fd: WasiFd::from_raw(fd) } }
     }
 }
diff --git a/library/std/src/sys/wasi/stdio.rs b/library/std/src/sys/wasi/stdio.rs
index 209d5b996e5..8782f333a1f 100644
--- a/library/std/src/sys/wasi/stdio.rs
+++ b/library/std/src/sys/wasi/stdio.rs
@@ -3,6 +3,7 @@
 use super::fd::WasiFd;
 use crate::io::{self, IoSlice, IoSliceMut};
 use crate::mem::ManuallyDrop;
+use crate::os::raw;
 
 pub struct Stdin;
 pub struct Stdout;
@@ -14,7 +15,7 @@ impl Stdin {
     }
 
     #[inline]
-    pub fn as_raw_fd(&self) -> u32 {
+    pub fn as_raw_fd(&self) -> raw::c_int {
         0
     }
 }
@@ -40,7 +41,7 @@ impl Stdout {
     }
 
     #[inline]
-    pub fn as_raw_fd(&self) -> u32 {
+    pub fn as_raw_fd(&self) -> raw::c_int {
         1
     }
 }
@@ -69,7 +70,7 @@ impl Stderr {
     }
 
     #[inline]
-    pub fn as_raw_fd(&self) -> u32 {
+    pub fn as_raw_fd(&self) -> raw::c_int {
         2
     }
 }
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 9effdb2c959..d12e86b7c1d 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -933,6 +933,8 @@ impl Step for RustdocGUI {
         let mut command = Command::new(&nodejs);
         command
             .arg(builder.build.src.join("src/tools/rustdoc-gui/tester.js"))
+            .arg("--jobs")
+            .arg(&builder.jobs().to_string())
             .arg("--doc-folder")
             .arg(out_dir.join("doc"))
             .arg("--tests-folder")
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 8dd7b2b3edc..dab6d655c6a 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -216,6 +216,9 @@ nav.main .separator {
 a {
 	color: #c5c5c5;
 }
+body.source .example-wrap pre.rust a {
+	background: #c5c5c5;
+}
 
 .docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
 .docblock-short a:not(.srclink):not(.test-arrow), .item-info a,
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index c26122e4bff..d9348be6994 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -177,6 +177,9 @@ nav.main .separator {
 a {
 	color: #ddd;
 }
+body.source .example-wrap pre.rust a {
+	background: #333;
+}
 
 .docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
 .docblock-short a:not(.srclink):not(.test-arrow), .item-info a,
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index bc18a724508..0ffe5929ea5 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -172,6 +172,9 @@ nav.main .separator {
 a {
 	color: #000;
 }
+body.source .example-wrap pre.rust a {
+	background: #eee;
+}
 
 .docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
 .docblock-short a:not(.srclink):not(.test-arrow), .item-info a,
diff --git a/src/test/ui/error-codes/E0106.stderr b/src/test/ui/error-codes/E0106.stderr
index ee9a4733fd9..fbd77d96700 100644
--- a/src/test/ui/error-codes/E0106.stderr
+++ b/src/test/ui/error-codes/E0106.stderr
@@ -59,7 +59,7 @@ LL | type MyStr = &str;
 help: consider introducing a named lifetime parameter
    |
 LL | type MyStr<'a> = &'a str;
-   |           ++++   ~~~
+   |           ++++    ++
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr
index 1594747e54c..e82cbf7e8e5 100644
--- a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr
+++ b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr
@@ -15,7 +15,7 @@ LL |     type F<T1> = &[u8];
 help: consider introducing a named lifetime parameter
    |
 LL |     type F<'a, T1> = &'a [u8];
-   |            +++       ~~~
+   |            +++        ++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr b/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr
index b752cde228d..44955c58889 100644
--- a/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr
+++ b/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr
@@ -7,7 +7,7 @@ LL |     type Output = &i32;
 help: consider introducing a named lifetime parameter
    |
 LL |     type Output<'a> = &'a i32;
-   |                ++++   ~~~
+   |                ++++    ++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/assoc-type.rs:16:20
diff --git a/src/test/ui/type-alias-impl-trait/private_unused.rs b/src/test/ui/impl-trait/private_unused.rs
index 92268f1861d..92268f1861d 100644
--- a/src/test/ui/type-alias-impl-trait/private_unused.rs
+++ b/src/test/ui/impl-trait/private_unused.rs
diff --git a/src/test/ui/issues/issue-19707.stderr b/src/test/ui/issues/issue-19707.stderr
index c3e5fcdd63b..18f69bb5775 100644
--- a/src/test/ui/issues/issue-19707.stderr
+++ b/src/test/ui/issues/issue-19707.stderr
@@ -9,11 +9,11 @@ LL | type Foo = fn(&u8, &u8) -> &u8;
 help: consider making the type lifetime-generic with a new `'a` lifetime
    |
 LL | type Foo = for<'a> fn(&'a u8, &'a u8) -> &'a u8;
-   |            +++++++    ~~~~~~  ~~~~~~     ~~~
+   |            +++++++     ++      ++         ++
 help: consider introducing a named lifetime parameter
    |
 LL | type Foo<'a> = fn(&'a u8, &'a u8) -> &'a u8;
-   |         ++++      ~~~~~~  ~~~~~~     ~~~
+   |         ++++       ++      ++         ++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-19707.rs:5:27
@@ -26,11 +26,11 @@ LL | fn bar<F: Fn(&u8, &u8) -> &u8>(f: &F) {}
 help: consider making the bound lifetime-generic with a new `'a` lifetime
    |
 LL | fn bar<F: for<'a> Fn(&'a u8, &'a u8) -> &'a u8>(f: &F) {}
-   |           +++++++    ~~~~~~  ~~~~~~     ~~~
+   |           +++++++     ++      ++         ++
 help: consider introducing a named lifetime parameter
    |
 LL | fn bar<'a, F: Fn(&'a u8, &'a u8) -> &'a u8>(f: &F) {}
-   |        +++       ~~~~~~  ~~~~~~     ~~~
+   |        +++        ++      ++         ++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr
index 5784ca9d77f..bb7cdcbb100 100644
--- a/src/test/ui/issues/issue-26638.stderr
+++ b/src/test/ui/issues/issue-26638.stderr
@@ -8,7 +8,7 @@ LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.ne
 help: consider introducing a named lifetime parameter
    |
 LL | fn parse_type<'a>(iter: Box<dyn Iterator<Item=&str>+'static>) -> &'a str { iter.next() }
-   |              ++++                                                ~~~
+   |              ++++                                                 ++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-26638.rs:4:40
diff --git a/src/test/ui/issues/issue-30255.stderr b/src/test/ui/issues/issue-30255.stderr
index 390aa31487a..e5f492af5b3 100644
--- a/src/test/ui/issues/issue-30255.stderr
+++ b/src/test/ui/issues/issue-30255.stderr
@@ -8,7 +8,7 @@ LL | fn f(a: &S, b: i32) -> &i32 {
 help: consider introducing a named lifetime parameter
    |
 LL | fn f<'a>(a: &'a S, b: i32) -> &'a i32 {
-   |     ++++    ~~~~~             ~~~
+   |     ++++     ++                ++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-30255.rs:14:34
@@ -20,7 +20,7 @@ LL | fn g(a: &S, b: bool, c: &i32) -> &i32 {
 help: consider introducing a named lifetime parameter
    |
 LL | fn g<'a>(a: &'a S, b: bool, c: &'a i32) -> &'a i32 {
-   |     ++++    ~~~~~              ~~~~~~~     ~~~
+   |     ++++     ++                 ++          ++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-30255.rs:19:44
@@ -32,7 +32,7 @@ LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 {
 help: consider introducing a named lifetime parameter
    |
 LL | fn h<'a>(a: &'a bool, b: bool, c: &'a S, d: &'a i32) -> &'a i32 {
-   |     ++++    ~~~~~~~~              ~~~~~     ~~~~~~~     ~~~
+   |     ++++     ++                    ++        ++          ++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr
index d0dc3601202..0e69cd50f6a 100644
--- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr
+++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr
@@ -20,7 +20,7 @@ LL | fn g(_x: &isize, _y: &isize) -> &isize {
 help: consider introducing a named lifetime parameter
    |
 LL | fn g<'a>(_x: &'a isize, _y: &'a isize) -> &'a isize {
-   |     ++++     ~~~~~~~~~      ~~~~~~~~~     ~~~
+   |     ++++      ++             ++            ++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:19
@@ -32,7 +32,7 @@ LL | fn h(_x: &Foo) -> &isize {
 help: consider introducing a named lifetime parameter
    |
 LL | fn h<'a>(_x: &'a Foo) -> &'a isize {
-   |     ++++     ~~~~~~~     ~~~
+   |     ++++      ++          ++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:21:20
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr
index cf365af9904..bcc3e9510ac 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr
@@ -8,7 +8,7 @@ LL | fn foo(x: &i32, y: &i32) -> &i32 {
 help: consider introducing a named lifetime parameter
    |
 LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
-   |       ++++    ~~~~~~~     ~~~~~~~     ~~~
+   |       ++++     ++          ++          ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lint/dead-code/anon-const-in-pat.rs b/src/test/ui/lint/dead-code/anon-const-in-pat.rs
new file mode 100644
index 00000000000..4c6211a279a
--- /dev/null
+++ b/src/test/ui/lint/dead-code/anon-const-in-pat.rs
@@ -0,0 +1,45 @@
+// check-pass
+#![feature(inline_const)]
+#![allow(incomplete_features)]
+#![deny(dead_code)]
+
+const fn one() -> i32 {
+    1
+}
+
+const fn two() -> i32 {
+    2
+}
+
+const fn three() -> i32 {
+    3
+}
+
+fn inline_const() {
+    // rust-lang/rust#78171: dead_code lint triggers even though function is used in const pattern
+    match 1 {
+        const { one() } => {}
+        _ => {}
+    }
+}
+
+fn inline_const_range() {
+    match 1 {
+        1 ..= const { two() } => {}
+        _ => {}
+    }
+}
+
+struct S<const C: i32>;
+
+fn const_generic_arg() {
+    match S::<3> {
+        S::<{three()}> => {}
+    }
+}
+
+fn main() {
+    inline_const();
+    inline_const_range();
+    const_generic_arg();
+}
diff --git a/src/test/ui/rfc1623-2.stderr b/src/test/ui/rfc1623-2.stderr
index 8ed606cf905..65b9f68817a 100644
--- a/src/test/ui/rfc1623-2.stderr
+++ b/src/test/ui/rfc1623-2.stderr
@@ -9,7 +9,7 @@ LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
 help: consider making the type lifetime-generic with a new `'a` lifetime
    |
 LL | static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 =
-   |                          +++++++    ~~~~~~  ~~~~~~     ~~~
+   |                          +++++++     ++      ++         ++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/rfc1623-2.rs:10:39
@@ -22,7 +22,7 @@ LL |     &(non_elidable as fn(&u8, &u8) -> &u8);
 help: consider making the type lifetime-generic with a new `'a` lifetime
    |
 LL |     &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8);
-   |                       +++++++    ~~~~~~  ~~~~~~     ~~~
+   |                       +++++++     ++      ++         ++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr b/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr
index 20468cef20b..7c0f8d199a9 100644
--- a/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr
+++ b/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr
@@ -25,11 +25,11 @@ LL | struct S2<F: Fn(&i32, &i32) -> &i32>(F);
 help: consider making the bound lifetime-generic with a new `'a` lifetime
    |
 LL | struct S2<F: for<'a> Fn(&'a i32, &'a i32) -> &'a i32>(F);
-   |              +++++++    ~~~~~~~  ~~~~~~~     ~~~
+   |              +++++++     ++       ++          ++
 help: consider introducing a named lifetime parameter
    |
 LL | struct S2<'a, F: Fn(&'a i32, &'a i32) -> &'a i32>(F);
-   |           +++       ~~~~~~~  ~~~~~~~     ~~~
+   |           +++        ++       ++          ++
 
 error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
   --> $DIR/fn-missing-lifetime-in-item.rs:3:40
diff --git a/src/test/ui/suggestions/issue-84592.stderr b/src/test/ui/suggestions/issue-84592.stderr
index fe301e41277..70c96feb1de 100644
--- a/src/test/ui/suggestions/issue-84592.stderr
+++ b/src/test/ui/suggestions/issue-84592.stderr
@@ -10,7 +10,7 @@ LL | fn two_lifetimes_needed(a: &(), b: &()) -> TwoLifetimes<'_, '_> {
 help: consider introducing a named lifetime parameter
    |
 LL | fn two_lifetimes_needed<'a>(a: &'a (), b: &'a ()) -> TwoLifetimes<'a, 'a> {
-   |                        ++++    ~~~~~~     ~~~~~~                  ~~  ~~
+   |                        ++++     ++         ++                     ~~  ~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/issue-86667.stderr b/src/test/ui/suggestions/issue-86667.stderr
index c1319165a70..14dbbfffb0e 100644
--- a/src/test/ui/suggestions/issue-86667.stderr
+++ b/src/test/ui/suggestions/issue-86667.stderr
@@ -8,7 +8,7 @@ LL | async fn a(s1: &str, s2: &str) -> &str {
 help: consider introducing a named lifetime parameter
    |
 LL | async fn a<'a>(s1: &'a str, s2: &'a str) -> &'a str {
-   |           ++++     ~~~~~~~      ~~~~~~~     ~~~
+   |           ++++      ++           ++          ++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-86667.rs:11:29
@@ -20,7 +20,7 @@ LL | fn b(s1: &str, s2: &str) -> &str {
 help: consider introducing a named lifetime parameter
    |
 LL | fn b<'a>(s1: &'a str, s2: &'a str) -> &'a str {
-   |     ++++     ~~~~~~~      ~~~~~~~     ~~~
+   |     ++++      ++           ++          ++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/suggestions/missing-lt-for-hrtb.stderr b/src/test/ui/suggestions/missing-lt-for-hrtb.stderr
index b1caaea9aed..33f9d092e6e 100644
--- a/src/test/ui/suggestions/missing-lt-for-hrtb.stderr
+++ b/src/test/ui/suggestions/missing-lt-for-hrtb.stderr
@@ -47,7 +47,7 @@ LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X);
 help: consider using one of the available lifetimes here
    |
 LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &'lifetime X);
-   |                                        ~~~~~~~~~~
+   |                                         +++++++++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/missing-lt-for-hrtb.rs:5:41
diff --git a/src/test/ui/suggestions/return-elided-lifetime.stderr b/src/test/ui/suggestions/return-elided-lifetime.stderr
index cdc3f5e85d1..f147b4463e2 100644
--- a/src/test/ui/suggestions/return-elided-lifetime.stderr
+++ b/src/test/ui/suggestions/return-elided-lifetime.stderr
@@ -80,7 +80,7 @@ LL | fn f3(s: &S) -> &i32 { loop {} }
 help: consider introducing a named lifetime parameter
    |
 LL | fn f3<'a>(s: &'a S) -> &'a i32 { loop {} }
-   |      ++++    ~~~~~     ~~~
+   |      ++++     ++        ++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/return-elided-lifetime.rs:21:26
@@ -92,7 +92,7 @@ LL | fn f3_(s: &S, t: &S) -> (&i32, &i32) { loop {} }
 help: consider introducing a named lifetime parameter
    |
 LL | fn f3_<'a>(s: &'a S, t: &'a S) -> (&'a i32, &i32) { loop {} }
-   |       ++++    ~~~~~     ~~~~~      ~~~
+   |       ++++     ++        ++         ++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/return-elided-lifetime.rs:21:32
@@ -104,7 +104,7 @@ LL | fn f3_(s: &S, t: &S) -> (&i32, &i32) { loop {} }
 help: consider introducing a named lifetime parameter
    |
 LL | fn f3_<'a>(s: &'a S, t: &'a S) -> (&i32, &'a i32) { loop {} }
-   |       ++++    ~~~~~     ~~~~~            ~~~
+   |       ++++     ++        ++               ++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/return-elided-lifetime.rs:25:42
@@ -121,7 +121,7 @@ LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &i32 { loop {} }
 help: consider using one of the available lifetimes here
    |
 LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &'lifetime i32 { loop {} }
-   |                                          ~~~~~~~~~~
+   |                                           +++++++++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/return-elided-lifetime.rs:27:44
@@ -138,7 +138,7 @@ LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} }
 help: consider using one of the available lifetimes here
    |
 LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&'lifetime i32, &i32) { loop {} }
-   |                                            ~~~~~~~~~~
+   |                                             +++++++++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/return-elided-lifetime.rs:27:50
@@ -155,7 +155,7 @@ LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} }
 help: consider using one of the available lifetimes here
    |
 LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &'lifetime i32) { loop {} }
-   |                                                  ~~~~~~~~~~
+   |                                                   +++++++++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/return-elided-lifetime.rs:31:35
diff --git a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr
index 89d36bfc926..6a104e8f94b 100644
--- a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr
+++ b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr
@@ -8,7 +8,7 @@ LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } }
 help: consider introducing a named lifetime parameter
    |
 LL | fn foo<'a>(x: &'a u32, y: &'a u32) -> &'a u32 { loop { } }
-   |       ++++    ~~~~~~~     ~~~~~~~      ~~
+   |       ++++     ++          ++          ~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr
index 4c207bd3e68..22bf1fdba32 100644
--- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr
+++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr
@@ -43,7 +43,7 @@ LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y }
 help: consider introducing a named lifetime parameter
    |
 LL | fn foo2<'a>(_: &'a u8, y: &'a u8) -> &'a u8 { y }
-   |        ++++    ~~~~~~     ~~~~~~      ~~
+   |        ++++     ~~         ~~         ~~
 
 error: aborting due to 5 previous errors
 
diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js
index d1cf5fb803d..e697e1f86a9 100644
--- a/src/tools/rustdoc-gui/tester.js
+++ b/src/tools/rustdoc-gui/tester.js
@@ -17,6 +17,11 @@ function showHelp() {
     console.log("  --no-headless              : disable headless mode");
     console.log("  --help                     : show this message then quit");
     console.log("  --tests-folder [PATH]      : location of the .GOML tests folder");
+    console.log("  --jobs [NUMBER]            : number of threads to run tests on");
+}
+
+function isNumeric(s) {
+    return /^\d+$/.test(s);
 }
 
 function parseOptions(args) {
@@ -27,6 +32,7 @@ function parseOptions(args) {
         "debug": false,
         "show_text": false,
         "no_headless": false,
+        "jobs": -1,
     };
     var correspondances = {
         "--doc-folder": "doc_folder",
@@ -39,13 +45,21 @@ function parseOptions(args) {
     for (var i = 0; i < args.length; ++i) {
         if (args[i] === "--doc-folder"
             || args[i] === "--tests-folder"
-            || args[i] === "--file") {
+            || args[i] === "--file"
+            || args[i] === "--jobs") {
             i += 1;
             if (i >= args.length) {
                 console.log("Missing argument after `" + args[i - 1] + "` option.");
                 return null;
             }
-            if (args[i - 1] !== "--file") {
+            if (args[i - 1] === "--jobs") {
+                if (!isNumeric(args[i])) {
+                    console.log(
+                        "`--jobs` option expects a positive number, found `" + args[i] + "`");
+                    return null;
+                }
+                opts["jobs"] = parseInt(args[i]);
+            } else if (args[i - 1] !== "--file") {
                 opts[correspondances[args[i - 1]]] = args[i];
             } else {
                 opts["files"].push(args[i]);
@@ -158,7 +172,11 @@ async function main(argv) {
     files.sort();
 
     console.log(`Running ${files.length} rustdoc-gui tests...`);
-    process.setMaxListeners(files.length + 1);
+    if (opts["jobs"] < 1) {
+        process.setMaxListeners(files.length + 1);
+    } else {
+        process.setMaxListeners(opts["jobs"]);
+    }
     let tests = [];
     let results = {
         successful: [],