about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-06-23 20:45:23 +0000
committerbors <bors@rust-lang.org>2023-06-23 20:45:23 +0000
commit22e9fe644ea710eec50cb0aabcae7fa8dd9fd675 (patch)
treebcdf9898595f7ddd107a0e810a32b9b8175cc45a /src
parentc79d6be6a287dcda55236fa6438286d16ec990ae (diff)
parent9d7f297f3c7ad6c18cea1f7fe091c3674ec34806 (diff)
downloadrust-22e9fe644ea710eec50cb0aabcae7fa8dd9fd675.tar.gz
rust-22e9fe644ea710eec50cb0aabcae7fa8dd9fd675.zip
Auto merge of #112974 - matthiaskrgr:rollup-hnk7ans, r=matthiaskrgr
Rollup of 8 pull requests

Successful merges:

 - #112616 (Improve tests on targets without unwinding)
 - #112643 (Always register sized obligation for argument)
 - #112740 (Add link to rustdoc book search chapter in help popover)
 - #112810 (Don't ICE on unnormalized struct tail in layout computation)
 - #112870 (Migrate `item_bounds` to `ty::Clause`)
 - #112925 (Stop hiding const eval limit in external macros)
 - #112960 ([tests/rustdoc] Add `@files` command)
 - #112962 (Fix rustdoc gui tester)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/download.rs22
-rw-r--r--src/bootstrap/lib.rs14
-rw-r--r--src/bootstrap/run.rs11
-rw-r--r--src/bootstrap/test.rs38
-rw-r--r--src/bootstrap/tool.rs2
-rw-r--r--src/bootstrap/util.rs2
-rwxr-xr-xsrc/etc/htmldocck.py54
-rw-r--r--src/librustdoc/clean/mod.rs21
-rw-r--r--src/librustdoc/clean/utils.rs3
-rw-r--r--src/librustdoc/html/layout.rs2
-rw-r--r--src/librustdoc/html/static/js/main.js8
-rw-r--r--src/librustdoc/html/templates/page.html1
-rw-r--r--src/tools/build_helper/src/util.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs14
-rw-r--r--src/tools/rustdoc-gui-test/src/main.rs9
16 files changed, 146 insertions, 77 deletions
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index 06f479808b9..cb40521dda7 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -54,9 +54,9 @@ impl Config {
     /// Runs a command, printing out nice contextual information if it fails.
     /// Exits if the command failed to execute at all, otherwise returns its
     /// `status.success()`.
-    pub(crate) fn try_run(&self, cmd: &mut Command) -> bool {
+    pub(crate) fn try_run(&self, cmd: &mut Command) -> Result<(), ()> {
         if self.dry_run() {
-            return true;
+            return Ok(());
         }
         self.verbose(&format!("running: {:?}", cmd));
         try_run(cmd, self.is_verbose())
@@ -156,12 +156,14 @@ impl Config {
                 ];
             }
             ";
-            nix_build_succeeded = self.try_run(Command::new("nix-build").args(&[
-                Path::new("-E"),
-                Path::new(NIX_EXPR),
-                Path::new("-o"),
-                &nix_deps_dir,
-            ]));
+            nix_build_succeeded = self
+                .try_run(Command::new("nix-build").args(&[
+                    Path::new("-E"),
+                    Path::new(NIX_EXPR),
+                    Path::new("-o"),
+                    &nix_deps_dir,
+                ]))
+                .is_ok();
             nix_deps_dir
         });
         if !nix_build_succeeded {
@@ -186,7 +188,7 @@ impl Config {
             patchelf.args(&["--set-interpreter", dynamic_linker.trim_end()]);
         }
 
-        self.try_run(patchelf.arg(fname));
+        self.try_run(patchelf.arg(fname)).unwrap();
     }
 
     fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) {
@@ -237,7 +239,7 @@ impl Config {
                             "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
                             url, tempfile.to_str().expect("invalid UTF-8 not supported with powershell downloads"),
                         ),
-                    ])) {
+                    ])).is_err() {
                         return;
                     }
                     eprintln!("\nspurious failure, trying again");
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index d7e77aeb338..d389b568f56 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -333,7 +333,7 @@ forward! {
     create(path: &Path, s: &str),
     remove(f: &Path),
     tempdir() -> PathBuf,
-    try_run(cmd: &mut Command) -> bool,
+    try_run(cmd: &mut Command) -> Result<(), ()>,
     llvm_link_shared() -> bool,
     download_rustc() -> bool,
     initial_rustfmt() -> Option<PathBuf>,
@@ -614,11 +614,13 @@ impl Build {
         }
 
         // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error).
-        let has_local_modifications = !self.try_run(
-            Command::new("git")
-                .args(&["diff-index", "--quiet", "HEAD"])
-                .current_dir(&absolute_path),
-        );
+        let has_local_modifications = self
+            .try_run(
+                Command::new("git")
+                    .args(&["diff-index", "--quiet", "HEAD"])
+                    .current_dir(&absolute_path),
+            )
+            .is_err();
         if has_local_modifications {
             self.run(Command::new("git").args(&["stash", "push"]).current_dir(&absolute_path));
         }
diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs
index ec01f744b82..c97b7592737 100644
--- a/src/bootstrap/run.rs
+++ b/src/bootstrap/run.rs
@@ -27,7 +27,8 @@ impl Step for ExpandYamlAnchors {
         try_run(
             builder,
             &mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("generate").arg(&builder.src),
-        );
+        )
+        .unwrap();
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -39,17 +40,17 @@ impl Step for ExpandYamlAnchors {
     }
 }
 
-fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool {
+fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> Result<(), ()> {
     if !builder.fail_fast {
-        if !builder.try_run(cmd) {
+        if let Err(e) = builder.try_run(cmd) {
             let mut failures = builder.delayed_failures.borrow_mut();
             failures.push(format!("{:?}", cmd));
-            return false;
+            return Err(e);
         }
     } else {
         builder.run(cmd);
     }
-    true
+    Ok(())
 }
 
 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 9212362f6c9..873ed61daf3 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -48,17 +48,17 @@ const MIR_OPT_BLESS_TARGET_MAPPING: &[(&str, &str)] = &[
     // build for, so there is no entry for "aarch64-apple-darwin" here.
 ];
 
-fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool {
+fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> Result<(), ()> {
     if !builder.fail_fast {
-        if !builder.try_run(cmd) {
+        if let Err(e) = builder.try_run(cmd) {
             let mut failures = builder.delayed_failures.borrow_mut();
             failures.push(format!("{:?}", cmd));
-            return false;
+            return Err(e);
         }
     } else {
         builder.run(cmd);
     }
-    true
+    Ok(())
 }
 
 fn try_run_quiet(builder: &Builder<'_>, cmd: &mut Command) -> bool {
@@ -187,7 +187,8 @@ You can skip linkcheck with --exclude src/tools/linkchecker"
         try_run(
             builder,
             builder.tool_cmd(Tool::Linkchecker).arg(builder.out.join(host.triple).join("doc")),
-        );
+        )
+        .unwrap();
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -240,7 +241,8 @@ impl Step for HtmlCheck {
         builder.default_doc(&[]);
         builder.ensure(crate::doc::Rustc::new(builder.top_stage, self.target, builder));
 
-        try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)));
+        try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)))
+            .unwrap();
     }
 }
 
@@ -286,7 +288,8 @@ impl Step for Cargotest {
                 .args(builder.config.test_args())
                 .env("RUSTC", builder.rustc(compiler))
                 .env("RUSTDOC", builder.rustdoc(compiler)),
-        );
+        )
+        .unwrap();
     }
 }
 
@@ -785,7 +788,7 @@ impl Step for Clippy {
         cargo.add_rustc_lib_path(builder, compiler);
         let mut cargo = prepare_cargo_test(cargo, &[], &[], "clippy", compiler, host, builder);
 
-        if builder.try_run(&mut cargo) {
+        if builder.try_run(&mut cargo).is_ok() {
             // The tests succeeded; nothing to do.
             return;
         }
@@ -858,7 +861,7 @@ impl Step for RustdocTheme {
                 util::lld_flag_no_threads(self.compiler.host.contains("windows")),
             );
         }
-        try_run(builder, &mut cmd);
+        try_run(builder, &mut cmd).unwrap();
     }
 }
 
@@ -1109,7 +1112,7 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy`
         }
 
         builder.info("tidy check");
-        try_run(builder, &mut cmd);
+        try_run(builder, &mut cmd).unwrap();
 
         builder.ensure(ExpandYamlAnchors);
 
@@ -1157,7 +1160,8 @@ impl Step for ExpandYamlAnchors {
         try_run(
             builder,
             &mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("check").arg(&builder.src),
-        );
+        )
+        .unwrap();
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -1936,7 +1940,7 @@ impl BookTest {
             compiler.host,
         );
         let _time = util::timeit(&builder);
-        let toolstate = if try_run(builder, &mut rustbook_cmd) {
+        let toolstate = if try_run(builder, &mut rustbook_cmd).is_ok() {
             ToolState::TestPass
         } else {
             ToolState::TestFail
@@ -2094,7 +2098,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
     cmd.arg("--test-args").arg(test_args);
 
     if builder.config.verbose_tests {
-        try_run(builder, &mut cmd)
+        try_run(builder, &mut cmd).is_ok()
     } else {
         try_run_quiet(builder, &mut cmd)
     }
@@ -2122,7 +2126,7 @@ impl Step for RustcGuide {
 
         let src = builder.src.join(relative_path);
         let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
-        let toolstate = if try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)) {
+        let toolstate = if try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)).is_ok() {
             ToolState::TestPass
         } else {
             ToolState::TestFail
@@ -2661,7 +2665,7 @@ impl Step for Bootstrap {
     fn run(self, builder: &Builder<'_>) {
         let mut check_bootstrap = Command::new(&builder.python());
         check_bootstrap.arg("bootstrap_test.py").current_dir(builder.src.join("src/bootstrap/"));
-        try_run(builder, &mut check_bootstrap);
+        try_run(builder, &mut check_bootstrap).unwrap();
 
         let host = builder.config.build;
         let compiler = builder.compiler(0, host);
@@ -2733,7 +2737,7 @@ impl Step for TierCheck {
         }
 
         builder.info("platform support check");
-        try_run(builder, &mut cargo.into());
+        try_run(builder, &mut cargo.into()).unwrap();
     }
 }
 
@@ -2813,7 +2817,7 @@ impl Step for RustInstaller {
         cmd.env("CARGO", &builder.initial_cargo);
         cmd.env("RUSTC", &builder.initial_rustc);
         cmd.env("TMP_DIR", &tmpdir);
-        try_run(builder, &mut cmd);
+        try_run(builder, &mut cmd).unwrap();
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 96341b69df0..126f0b1eb31 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -107,7 +107,7 @@ impl Step for ToolBuild {
         );
 
         let mut cargo = Command::from(cargo);
-        let is_expected = builder.try_run(&mut cargo);
+        let is_expected = builder.try_run(&mut cargo).is_ok();
 
         builder.save_toolstate(
             tool,
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 1ec49f80d63..b291584b300 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -228,7 +228,7 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef<Path>>(
 }
 
 pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) {
-    if !try_run(cmd, print_cmd_on_fail) {
+    if try_run(cmd, print_cmd_on_fail).is_err() {
         crate::detail_exit_macro!(1);
     }
 }
diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py
index eade9e04559..5ab1874e9ed 100755
--- a/src/etc/htmldocck.py
+++ b/src/etc/htmldocck.py
@@ -110,6 +110,9 @@ There are a number of supported commands:
 
 * `@has-dir PATH` checks for the existence of the given directory.
 
+* `@files FOLDER_PATH [ENTRIES]`, checks that `FOLDER_PATH` contains exactly
+  `[ENTRIES]`.
+
 All conditions can be negated with `!`. `@!has foo/type.NoSuch.html`
 checks if the given file does not exist, for example.
 
@@ -321,12 +324,15 @@ class CachedFiles(object):
         else:
             return self.last_path
 
+    def get_absolute_path(self, path):
+        return os.path.join(self.root, path)
+
     def get_file(self, path):
         path = self.resolve_path(path)
         if path in self.files:
             return self.files[path]
 
-        abspath = os.path.join(self.root, path)
+        abspath = self.get_absolute_path(path)
         if not(os.path.exists(abspath) and os.path.isfile(abspath)):
             raise FailedCheck('File does not exist {!r}'.format(path))
 
@@ -340,7 +346,7 @@ class CachedFiles(object):
         if path in self.trees:
             return self.trees[path]
 
-        abspath = os.path.join(self.root, path)
+        abspath = self.get_absolute_path(path)
         if not(os.path.exists(abspath) and os.path.isfile(abspath)):
             raise FailedCheck('File does not exist {!r}'.format(path))
 
@@ -356,7 +362,7 @@ class CachedFiles(object):
 
     def get_dir(self, path):
         path = self.resolve_path(path)
-        abspath = os.path.join(self.root, path)
+        abspath = self.get_absolute_path(path)
         if not(os.path.exists(abspath) and os.path.isdir(abspath)):
             raise FailedCheck('Directory does not exist {!r}'.format(path))
 
@@ -538,6 +544,41 @@ def get_nb_matching_elements(cache, c, regexp, stop_at_first):
         return check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first)
 
 
+def check_files_in_folder(c, cache, folder, files):
+    files = files.strip()
+    if not files.startswith('[') or not files.endswith(']'):
+        raise InvalidCheck("Expected list as second argument of @{} (ie '[]')".format(c.cmd))
+
+    folder = cache.get_absolute_path(folder)
+
+    # First we create a set of files to check if there are duplicates.
+    files = shlex.split(files[1:-1].replace(",", ""))
+    files_set = set()
+    for file in files:
+        if file in files_set:
+            raise InvalidCheck("Duplicated file `{}` in @{}".format(file, c.cmd))
+        files_set.add(file)
+    folder_set = set([f for f in os.listdir(folder) if f != "." and f != ".."])
+
+    # Then we remove entries from both sets (we clone `folder_set` so we can iterate it while
+    # removing its elements).
+    for entry in set(folder_set):
+        if entry in files_set:
+            files_set.remove(entry)
+            folder_set.remove(entry)
+
+    error = 0
+    if len(files_set) != 0:
+        print_err(c.lineno, c.context, "Entries not found in folder `{}`: `{}`".format(
+            folder, files_set))
+        error += 1
+    if len(folder_set) != 0:
+        print_err(c.lineno, c.context, "Extra entries in folder `{}`: `{}`".format(
+            folder, folder_set))
+        error += 1
+    return error == 0
+
+
 ERR_COUNT = 0
 
 
@@ -566,6 +607,13 @@ def check_command(c, cache):
             else:
                 raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd))
 
+        elif c.cmd == 'files': # check files in given folder
+            if len(c.args) != 2: # @files <folder path> <file list>
+                raise InvalidCheck("Invalid number of @{} arguments".format(c.cmd))
+            elif c.negated:
+                raise InvalidCheck("@{} doesn't support negative check".format(c.cmd))
+            ret = check_files_in_folder(c, cache, c.args[0], c.args[1])
+
         elif c.cmd == 'count':  # count test
             if len(c.args) == 3:  # @count <path> <pat> <count> = count test
                 expected = int(c.args[2])
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 9a815694e1b..f86c32158e0 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1361,8 +1361,10 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
             }
 
             if let ty::TraitContainer = assoc_item.container {
-                let bounds =
-                    tcx.explicit_item_bounds(assoc_item.def_id).subst_identity_iter_copied();
+                let bounds = tcx
+                    .explicit_item_bounds(assoc_item.def_id)
+                    .subst_identity_iter_copied()
+                    .map(|(c, s)| (c.as_predicate(), s));
                 let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates;
                 let predicates =
                     tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied()));
@@ -2117,7 +2119,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
 
 fn clean_middle_opaque_bounds<'tcx>(
     cx: &mut DocContext<'tcx>,
-    bounds: Vec<ty::Predicate<'tcx>>,
+    bounds: Vec<ty::Clause<'tcx>>,
 ) -> Type {
     let mut regions = vec![];
     let mut has_sized = false;
@@ -2126,13 +2128,8 @@ fn clean_middle_opaque_bounds<'tcx>(
         .filter_map(|bound| {
             let bound_predicate = bound.kind();
             let trait_ref = match bound_predicate.skip_binder() {
-                ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => {
-                    bound_predicate.rebind(tr.trait_ref)
-                }
-                ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
-                    _ty,
-                    reg,
-                ))) => {
+                ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
+                ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
                     if let Some(r) = clean_middle_region(reg) {
                         regions.push(GenericBound::Outlives(r));
                     }
@@ -2149,9 +2146,7 @@ fn clean_middle_opaque_bounds<'tcx>(
             let bindings: ThinVec<_> = bounds
                 .iter()
                 .filter_map(|bound| {
-                    if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) =
-                        bound.kind().skip_binder()
-                    {
+                    if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() {
                         if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
                             Some(TypeBinding {
                                 assoc: projection_to_path_segment(
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 294de12cea8..f375f0efbd1 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -21,6 +21,7 @@ use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::symbol::{kw, sym, Symbol};
 use std::fmt::Write as _;
 use std::mem;
+use std::sync::LazyLock as Lazy;
 use thin_vec::{thin_vec, ThinVec};
 
 #[cfg(test)]
@@ -582,6 +583,8 @@ pub(crate) fn has_doc_flag(tcx: TyCtxt<'_>, did: DefId, flag: Symbol) -> bool {
 ///
 /// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable.
 pub(crate) const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL");
+pub(crate) static DOC_CHANNEL: Lazy<&'static str> =
+    Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit("/").filter(|c| !c.is_empty()).next().unwrap());
 
 /// Render a sequence of macro arms in a format suitable for displaying to the user
 /// as part of an item declaration.
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 6ab849c92a0..8c5871d9126 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -55,6 +55,7 @@ struct PageLayout<'a> {
     sidebar: String,
     content: String,
     krate_with_trailing_slash: String,
+    rust_channel: &'static str,
     pub(crate) rustdoc_version: &'a str,
 }
 
@@ -82,6 +83,7 @@ pub(crate) fn render<T: Print, S: Print>(
         sidebar,
         content,
         krate_with_trailing_slash,
+        rust_channel: *crate::clean::utils::DOC_CHANNEL,
         rustdoc_version,
     }
     .render()
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index f5296abaee6..254b0d8bf5a 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -1050,9 +1050,10 @@ function preLoadCss(cssUrl) {
 
     function buildHelpMenu() {
         const book_info = document.createElement("span");
+        const channel = getVar("channel");
         book_info.className = "top";
-        book_info.innerHTML = "You can find more information in \
-            <a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
+        book_info.innerHTML = `You can find more information in \
+<a href="https://doc.rust-lang.org/${channel}/rustdoc/">the rustdoc book</a>.`;
 
         const shortcuts = [
             ["?", "Show this help dialog"],
@@ -1072,6 +1073,9 @@ function preLoadCss(cssUrl) {
         div_shortcuts.innerHTML = "<h2>Keyboard Shortcuts</h2><dl>" + shortcuts + "</dl></div>";
 
         const infos = [
+            `For a full list of all search features, take a look <a \
+href="https://doc.rust-lang.org/${channel}/rustdoc/how-to-read-rustdoc.html\
+#the-search-interface">here</a>.`,
             "Prefix searches with a type followed by a colon (e.g., <code>fn:</code>) to \
              restrict the search to a given item kind.",
             "Accepted kinds are: <code>fn</code>, <code>mod</code>, <code>struct</code>, \
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index 9133f899af6..759c4fd6012 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -31,6 +31,7 @@
          data-themes="{{themes|join(",") }}" {#+ #}
          data-resource-suffix="{{page.resource_suffix}}" {#+ #}
          data-rustdoc-version="{{rustdoc_version}}" {#+ #}
+         data-channel="{{rust_channel}}" {#+ #}
          data-search-js="{{files.search_js}}" {#+ #}
          data-settings-js="{{files.settings_js}}" {#+ #}
          data-settings-css="{{files.settings_css}}" {#+ #}
diff --git a/src/tools/build_helper/src/util.rs b/src/tools/build_helper/src/util.rs
index 731095023a9..11b8a228b8a 100644
--- a/src/tools/build_helper/src/util.rs
+++ b/src/tools/build_helper/src/util.rs
@@ -25,17 +25,21 @@ pub fn fail(s: &str) -> ! {
     detail_exit(1, cfg!(test));
 }
 
-pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
+pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> Result<(), ()> {
     let status = match cmd.status() {
         Ok(status) => status,
         Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
     };
-    if !status.success() && print_cmd_on_fail {
-        println!(
-            "\n\ncommand did not execute successfully: {:?}\n\
-             expected success, got: {}\n\n",
-            cmd, status
-        );
+    if !status.success() {
+        if print_cmd_on_fail {
+            println!(
+                "\n\ncommand did not execute successfully: {:?}\n\
+                 expected success, got: {}\n\n",
+                cmd, status
+            );
+        }
+        Err(())
+    } else {
+        Ok(())
     }
-    status.success()
 }
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index a391b76910a..818ebd1134d 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -67,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
             let preds = cx.tcx.explicit_item_bounds(def_id);
             let mut is_future = false;
             for (p, _span) in preds.subst_iter_copied(cx.tcx, substs) {
-                if let Some(trait_pred) = p.to_opt_poly_trait_pred() {
+                if let Some(trait_pred) = p.as_trait_clause() {
                     if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() {
                         is_future = true;
                         break;
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 12f18614d71..2b185943c59 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -94,7 +94,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
                         match predicate.kind().skip_binder() {
                             // For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
                             // and check substitutions to find `U`.
-                            ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
+                            ty::ClauseKind::Trait(trait_predicate) => {
                                 if trait_predicate
                                     .trait_ref
                                     .substs
@@ -107,7 +107,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
                             },
                             // For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
                             // so we check the term for `U`.
-                            ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection_predicate)) => {
+                            ty::ClauseKind::Projection(projection_predicate) => {
                                 if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() {
                                     if contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen) {
                                         return true;
@@ -268,7 +268,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
         ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)),
         ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
             for (predicate, _) in cx.tcx.explicit_item_bounds(def_id).skip_binder() {
-                if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() {
+                if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() {
                     if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) {
                         return true;
                     }
@@ -665,7 +665,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
         ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => sig_from_bounds(
             cx,
             ty,
-            cx.tcx.item_bounds(def_id).subst(cx.tcx, substs),
+            cx.tcx.item_bounds(def_id).subst_iter(cx.tcx, substs).map(|c| c.as_predicate()),
             cx.tcx.opt_parent(def_id),
         ),
         ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)),
@@ -698,7 +698,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
 fn sig_from_bounds<'tcx>(
     cx: &LateContext<'tcx>,
     ty: Ty<'tcx>,
-    predicates: &'tcx [Predicate<'tcx>],
+    predicates: impl IntoIterator<Item = Predicate<'tcx>>,
     predicates_id: Option<DefId>,
 ) -> Option<ExprFnSig<'tcx>> {
     let mut inputs = None;
@@ -747,7 +747,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option
         .subst_iter_copied(cx.tcx, ty.substs)
     {
         match pred.kind().skip_binder() {
-            PredicateKind::Clause(ty::ClauseKind::Trait(p))
+            ty::ClauseKind::Trait(p)
                 if (lang_items.fn_trait() == Some(p.def_id())
                     || lang_items.fn_mut_trait() == Some(p.def_id())
                     || lang_items.fn_once_trait() == Some(p.def_id())) =>
@@ -760,7 +760,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option
                 }
                 inputs = Some(i);
             },
-            PredicateKind::Clause(ty::ClauseKind::Projection(p))
+            ty::ClauseKind::Projection(p)
                 if Some(p.projection_ty.def_id) == lang_items.fn_once_output() =>
             {
                 if output.is_some() {
diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs
index dc902f8cb02..0ddd2c66cf9 100644
--- a/src/tools/rustdoc-gui-test/src/main.rs
+++ b/src/tools/rustdoc-gui-test/src/main.rs
@@ -67,7 +67,7 @@ fn find_librs<P: AsRef<Path>>(path: P) -> Option<PathBuf> {
     None
 }
 
-fn main() {
+fn main() -> Result<(), ()> {
     let config = Arc::new(Config::from_args(env::args().collect()));
 
     // The goal here is to check if the necessary packages are installed, and if not, we
@@ -128,7 +128,10 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse
                 }
             }
 
-            try_run(&mut cargo, config.verbose);
+            if try_run(&mut cargo, config.verbose).is_err() {
+                eprintln!("failed to document `{}`", entry.path().display());
+                panic!("Cannot run rustdoc-gui tests");
+            }
         }
     }
 
@@ -158,5 +161,5 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse
 
     command.args(&config.test_args);
 
-    try_run(&mut command, config.verbose);
+    try_run(&mut command, config.verbose)
 }