about summary refs log tree commit diff
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/build_helper/Cargo.toml10
-rw-r--r--src/tools/build_helper/README.md1
-rw-r--r--src/tools/build_helper/src/ci.rs95
-rw-r--r--src/tools/build_helper/src/drop_bomb/mod.rs54
-rw-r--r--src/tools/build_helper/src/drop_bomb/tests.rs15
-rw-r--r--src/tools/build_helper/src/git.rs208
-rw-r--r--src/tools/build_helper/src/lib.rs31
-rw-r--r--src/tools/build_helper/src/metrics.rs92
-rw-r--r--src/tools/build_helper/src/stage0_parser.rs76
-rw-r--r--src/tools/build_helper/src/util.rs75
-rw-r--r--src/tools/bump-stage0/Cargo.toml2
-rw-r--r--src/tools/clippy/CHANGELOG.md1
-rw-r--r--src/tools/clippy/clippy_dev/src/setup/vscode.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/utils.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/box_default.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/comparison_chain.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/copies.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/missing_headers.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/drop_forget_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/infinite_iter.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/item_name_repetitions.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_const_arrays.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/large_include_file.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_find.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/same_item_push.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/utils.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_clamp.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_strip.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/single_match.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/try_err.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_next.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_clone.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/str_splitn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs131
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/useless_asref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_continue.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/identity_op.rs190
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs172
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_slicing.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/swap.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/types/borrowed_box.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/vec_init_then_push.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/write.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/check_proc_macro.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs31
-rw-r--r--src/tools/clippy/clippy_utils/src/numeric_literal.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs12
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs10
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed1
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs1
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr30
-rw-r--r--src/tools/clippy/tests/ui-toml/large_include_file/empty.txt0
-rw-r--r--src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.rs6
-rw-r--r--src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed1
-rw-r--r--src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs1
-rw-r--r--src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr12
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr20
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr18
-rw-r--r--src/tools/clippy/tests/ui/four_forward_slashes.stderr10
-rw-r--r--src/tools/clippy/tests/ui/four_forward_slashes_first_line.stderr2
-rw-r--r--src/tools/clippy/tests/ui/identity_op.fixed46
-rw-r--r--src/tools/clippy/tests/ui/identity_op.rs44
-rw-r--r--src/tools/clippy/tests/ui/identity_op.stderr70
-rw-r--r--src/tools/clippy/tests/ui/question_mark.fixed56
-rw-r--r--src/tools/clippy/tests/ui/question_mark.rs71
-rw-r--r--src/tools/clippy/tests/ui/question_mark.stderr63
-rw-r--r--src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.stderr2
-rw-r--r--src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_map_or.fixed64
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_map_or.rs67
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_map_or.stderr99
-rw-r--r--src/tools/compiletest/Cargo.toml2
-rw-r--r--src/tools/compiletest/src/directive-list.rs3
-rw-r--r--src/tools/compiletest/src/header.rs27
-rw-r--r--src/tools/compiletest/src/header/tests.rs24
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/diagnostics.rs2
-rw-r--r--src/tools/opt-dist/Cargo.toml2
-rw-r--r--src/tools/run-make-support/Cargo.toml2
-rw-r--r--src/tools/run-make-support/src/external_deps/rustc.rs23
-rw-r--r--src/tools/run-make-support/src/lib.rs2
-rw-r--r--src/tools/run-make-support/src/targets.rs6
-rw-r--r--src/tools/rust-analyzer/.github/workflows/autopublish.yaml1
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs97
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs144
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs37
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs34
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/file_structure.rs59
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/render.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs4
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs6
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs18
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs1
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs30
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/minicore.rs10
-rw-r--r--src/tools/rust-analyzer/docs/dev/README.md2
-rw-r--r--src/tools/rust-analyzer/docs/dev/lsp-extensions.md2
-rw-r--r--src/tools/rust-analyzer/editors/code/package-lock.json44
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json16
-rw-r--r--src/tools/rust-analyzer/editors/code/src/client.ts2
-rw-r--r--src/tools/rust-analyzer/triagebot.toml2
-rw-r--r--src/tools/rustbook/.gitignore1
-rw-r--r--src/tools/rustbook/Cargo.lock291
-rw-r--r--src/tools/rustdoc-gui-test/Cargo.toml2
-rw-r--r--src/tools/rustdoc-js/tester.js55
-rw-r--r--src/tools/suggest-tests/Cargo.toml2
-rw-r--r--src/tools/tidy/Cargo.toml2
-rw-r--r--src/tools/tidy/src/deps.rs3
-rw-r--r--src/tools/tidy/src/known_bug.rs18
-rw-r--r--src/tools/unicode-table-generator/src/range_search.rs1
-rw-r--r--src/tools/unicode-table-generator/src/raw_emitter.rs4
157 files changed, 1742 insertions, 1433 deletions
diff --git a/src/tools/build_helper/Cargo.toml b/src/tools/build_helper/Cargo.toml
deleted file mode 100644
index 66894e1abc4..00000000000
--- a/src/tools/build_helper/Cargo.toml
+++ /dev/null
@@ -1,10 +0,0 @@
-[package]
-name = "build_helper"
-version = "0.1.0"
-edition = "2021"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-serde = "1"
-serde_derive = "1"
diff --git a/src/tools/build_helper/README.md b/src/tools/build_helper/README.md
deleted file mode 100644
index f81b631c3fd..00000000000
--- a/src/tools/build_helper/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Types and functions shared across tools in this workspace.
diff --git a/src/tools/build_helper/src/ci.rs b/src/tools/build_helper/src/ci.rs
deleted file mode 100644
index 60f319129a0..00000000000
--- a/src/tools/build_helper/src/ci.rs
+++ /dev/null
@@ -1,95 +0,0 @@
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum CiEnv {
-    /// Not a CI environment.
-    None,
-    /// The GitHub Actions environment, for Linux (including Docker), Windows and macOS builds.
-    GitHubActions,
-}
-
-impl CiEnv {
-    /// Obtains the current CI environment.
-    pub fn current() -> CiEnv {
-        if std::env::var("GITHUB_ACTIONS").map_or(false, |e| e == "true") {
-            CiEnv::GitHubActions
-        } else {
-            CiEnv::None
-        }
-    }
-
-    pub fn is_ci() -> bool {
-        Self::current() != CiEnv::None
-    }
-
-    /// Checks if running in rust-lang/rust managed CI job.
-    pub fn is_rust_lang_managed_ci_job() -> bool {
-        Self::is_ci()
-            // If both are present, we can assume it's an upstream CI job
-            // as they are always set unconditionally.
-            && std::env::var_os("CI_JOB_NAME").is_some()
-            && std::env::var_os("TOOLSTATE_REPO").is_some()
-    }
-}
-
-pub mod gha {
-    use std::sync::Mutex;
-
-    static ACTIVE_GROUPS: Mutex<Vec<String>> = Mutex::new(Vec::new());
-
-    /// All github actions log messages from this call to the Drop of the return value
-    /// will be grouped and hidden by default in logs. Note that since github actions doesn't
-    /// support group nesting, any active group will be first finished when a subgroup is started,
-    /// and then re-started when the subgroup finishes.
-    #[track_caller]
-    pub fn group(name: impl std::fmt::Display) -> Group {
-        let mut groups = ACTIVE_GROUPS.lock().unwrap();
-
-        // A group is currently active. End it first to avoid nesting.
-        if !groups.is_empty() {
-            end_group();
-        }
-
-        let name = name.to_string();
-        start_group(&name);
-        groups.push(name);
-        Group(())
-    }
-
-    /// A guard that closes the current github actions log group on drop.
-    #[must_use]
-    pub struct Group(());
-
-    impl Drop for Group {
-        fn drop(&mut self) {
-            end_group();
-
-            let mut groups = ACTIVE_GROUPS.lock().unwrap();
-            // Remove the current group
-            groups.pop();
-
-            // If there was some previous group, restart it
-            if is_in_gha() {
-                if let Some(name) = groups.last() {
-                    start_group(format!("{name} (continued)"));
-                }
-            }
-        }
-    }
-
-    fn start_group(name: impl std::fmt::Display) {
-        if is_in_gha() {
-            println!("::group::{name}");
-        } else {
-            println!("{name}")
-        }
-    }
-
-    fn end_group() {
-        if is_in_gha() {
-            println!("::endgroup::");
-        }
-    }
-
-    fn is_in_gha() -> bool {
-        std::env::var_os("GITHUB_ACTIONS").is_some()
-    }
-}
diff --git a/src/tools/build_helper/src/drop_bomb/mod.rs b/src/tools/build_helper/src/drop_bomb/mod.rs
deleted file mode 100644
index 0a5bb04b55b..00000000000
--- a/src/tools/build_helper/src/drop_bomb/mod.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-//! This module implements "drop bombs" intended for use by command wrappers to ensure that the
-//! constructed commands are *eventually* executed. This is exactly like `rustc_errors::Diag` where
-//! we force every `Diag` to be consumed or we emit a bug, but we panic instead.
-//!
-//! This is adapted from <https://docs.rs/drop_bomb/latest/drop_bomb/> and simplified for our
-//! purposes.
-
-use std::ffi::{OsStr, OsString};
-use std::panic;
-
-#[cfg(test)]
-mod tests;
-
-#[derive(Debug)]
-pub struct DropBomb {
-    command: OsString,
-    defused: bool,
-    armed_location: panic::Location<'static>,
-}
-
-impl DropBomb {
-    /// Arm a [`DropBomb`]. If the value is dropped without being [`defused`][Self::defused], then
-    /// it will panic. It is expected that the command wrapper uses `#[track_caller]` to help
-    /// propagate the caller location.
-    #[track_caller]
-    pub fn arm<S: AsRef<OsStr>>(command: S) -> DropBomb {
-        DropBomb {
-            command: command.as_ref().into(),
-            defused: false,
-            armed_location: *panic::Location::caller(),
-        }
-    }
-
-    pub fn get_created_location(&self) -> panic::Location<'static> {
-        self.armed_location
-    }
-
-    /// Defuse the [`DropBomb`]. This will prevent the drop bomb from panicking when dropped.
-    pub fn defuse(&mut self) {
-        self.defused = true;
-    }
-}
-
-impl Drop for DropBomb {
-    fn drop(&mut self) {
-        if !self.defused && !std::thread::panicking() {
-            panic!(
-                "command constructed at `{}` was dropped without being executed: `{}`",
-                self.armed_location,
-                self.command.to_string_lossy()
-            )
-        }
-    }
-}
diff --git a/src/tools/build_helper/src/drop_bomb/tests.rs b/src/tools/build_helper/src/drop_bomb/tests.rs
deleted file mode 100644
index 4a488c0f670..00000000000
--- a/src/tools/build_helper/src/drop_bomb/tests.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use super::DropBomb;
-
-#[test]
-#[should_panic]
-fn test_arm() {
-    let bomb = DropBomb::arm("hi :3");
-    drop(bomb); // <- armed bomb should explode when not defused
-}
-
-#[test]
-fn test_defuse() {
-    let mut bomb = DropBomb::arm("hi :3");
-    bomb.defuse();
-    drop(bomb); // <- defused bomb should not explode
-}
diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs
deleted file mode 100644
index 2aad5650fa8..00000000000
--- a/src/tools/build_helper/src/git.rs
+++ /dev/null
@@ -1,208 +0,0 @@
-use std::path::{Path, PathBuf};
-use std::process::{Command, Stdio};
-
-use crate::ci::CiEnv;
-
-pub struct GitConfig<'a> {
-    pub git_repository: &'a str,
-    pub nightly_branch: &'a str,
-    pub git_merge_commit_email: &'a str,
-}
-
-/// Runs a command and returns the output
-pub fn output_result(cmd: &mut Command) -> Result<String, String> {
-    let output = match cmd.stderr(Stdio::inherit()).output() {
-        Ok(status) => status,
-        Err(e) => return Err(format!("failed to run command: {:?}: {}", cmd, e)),
-    };
-    if !output.status.success() {
-        return Err(format!(
-            "command did not execute successfully: {:?}\n\
-             expected success, got: {}\n{}",
-            cmd,
-            output.status,
-            String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))?
-        ));
-    }
-    String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))
-}
-
-/// Finds the remote for rust-lang/rust.
-/// For example for these remotes it will return `upstream`.
-/// ```text
-/// origin  https://github.com/Nilstrieb/rust.git (fetch)
-/// origin  https://github.com/Nilstrieb/rust.git (push)
-/// upstream        https://github.com/rust-lang/rust (fetch)
-/// upstream        https://github.com/rust-lang/rust (push)
-/// ```
-pub fn get_rust_lang_rust_remote(
-    config: &GitConfig<'_>,
-    git_dir: Option<&Path>,
-) -> Result<String, String> {
-    let mut git = Command::new("git");
-    if let Some(git_dir) = git_dir {
-        git.current_dir(git_dir);
-    }
-    git.args(["config", "--local", "--get-regex", "remote\\..*\\.url"]);
-    let stdout = output_result(&mut git)?;
-
-    let rust_lang_remote = stdout
-        .lines()
-        .find(|remote| remote.contains(config.git_repository))
-        .ok_or_else(|| format!("{} remote not found", config.git_repository))?;
-
-    let remote_name =
-        rust_lang_remote.split('.').nth(1).ok_or_else(|| "remote name not found".to_owned())?;
-    Ok(remote_name.into())
-}
-
-pub fn rev_exists(rev: &str, git_dir: Option<&Path>) -> Result<bool, String> {
-    let mut git = Command::new("git");
-    if let Some(git_dir) = git_dir {
-        git.current_dir(git_dir);
-    }
-    git.args(["rev-parse", rev]);
-    let output = git.output().map_err(|err| format!("{err:?}"))?;
-
-    match output.status.code() {
-        Some(0) => Ok(true),
-        Some(128) => Ok(false),
-        None => Err(format!(
-            "git didn't exit properly: {}",
-            String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))?
-        )),
-        Some(code) => Err(format!(
-            "git command exited with status code: {code}: {}",
-            String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))?
-        )),
-    }
-}
-
-/// Returns the master branch from which we can take diffs to see changes.
-/// This will usually be rust-lang/rust master, but sometimes this might not exist.
-/// This could be because the user is updating their forked master branch using the GitHub UI
-/// and therefore doesn't need an upstream master branch checked out.
-/// We will then fall back to origin/master in the hope that at least this exists.
-pub fn updated_master_branch(
-    config: &GitConfig<'_>,
-    git_dir: Option<&Path>,
-) -> Result<String, String> {
-    let upstream_remote = get_rust_lang_rust_remote(config, git_dir)?;
-    let branch = config.nightly_branch;
-    for upstream_master in [format!("{upstream_remote}/{branch}"), format!("origin/{branch}")] {
-        if rev_exists(&upstream_master, git_dir)? {
-            return Ok(upstream_master);
-        }
-    }
-
-    Err("Cannot find any suitable upstream master branch".to_owned())
-}
-
-/// Finds the nearest merge commit by comparing the local `HEAD` with the upstream branch's state.
-/// To work correctly, the upstream remote must be properly configured using `git remote add <name> <url>`.
-/// In most cases `get_closest_merge_commit` is the function you are looking for as it doesn't require remote
-/// to be configured.
-fn git_upstream_merge_base(
-    config: &GitConfig<'_>,
-    git_dir: Option<&Path>,
-) -> Result<String, String> {
-    let updated_master = updated_master_branch(config, git_dir)?;
-    let mut git = Command::new("git");
-    if let Some(git_dir) = git_dir {
-        git.current_dir(git_dir);
-    }
-    Ok(output_result(git.arg("merge-base").arg(&updated_master).arg("HEAD"))?.trim().to_owned())
-}
-
-/// Searches for the nearest merge commit in the repository that also exists upstream.
-///
-/// It looks for the most recent commit made by the merge bot by matching the author's email
-/// address with the merge bot's email.
-pub fn get_closest_merge_commit(
-    git_dir: Option<&Path>,
-    config: &GitConfig<'_>,
-    target_paths: &[PathBuf],
-) -> Result<String, String> {
-    let mut git = Command::new("git");
-
-    if let Some(git_dir) = git_dir {
-        git.current_dir(git_dir);
-    }
-
-    let merge_base = {
-        if CiEnv::is_ci() {
-            git_upstream_merge_base(config, git_dir).unwrap()
-        } else {
-            // For non-CI environments, ignore rust-lang/rust upstream as it usually gets
-            // outdated very quickly.
-            "HEAD".to_string()
-        }
-    };
-
-    git.args([
-        "rev-list",
-        &format!("--author={}", config.git_merge_commit_email),
-        "-n1",
-        "--first-parent",
-        &merge_base,
-    ]);
-
-    if !target_paths.is_empty() {
-        git.arg("--").args(target_paths);
-    }
-
-    Ok(output_result(&mut git)?.trim().to_owned())
-}
-
-/// Returns the files that have been modified in the current branch compared to the master branch.
-/// The `extensions` parameter can be used to filter the files by their extension.
-/// Does not include removed files.
-/// If `extensions` is empty, all files will be returned.
-pub fn get_git_modified_files(
-    config: &GitConfig<'_>,
-    git_dir: Option<&Path>,
-    extensions: &[&str],
-) -> Result<Option<Vec<String>>, String> {
-    let merge_base = get_closest_merge_commit(git_dir, config, &[])?;
-
-    let mut git = Command::new("git");
-    if let Some(git_dir) = git_dir {
-        git.current_dir(git_dir);
-    }
-    let files = output_result(git.args(["diff-index", "--name-status", merge_base.trim()]))?
-        .lines()
-        .filter_map(|f| {
-            let (status, name) = f.trim().split_once(char::is_whitespace).unwrap();
-            if status == "D" {
-                None
-            } else if Path::new(name).extension().map_or(false, |ext| {
-                extensions.is_empty() || extensions.contains(&ext.to_str().unwrap())
-            }) {
-                Some(name.to_owned())
-            } else {
-                None
-            }
-        })
-        .collect();
-    Ok(Some(files))
-}
-
-/// Returns the files that haven't been added to git yet.
-pub fn get_git_untracked_files(
-    config: &GitConfig<'_>,
-    git_dir: Option<&Path>,
-) -> Result<Option<Vec<String>>, String> {
-    let Ok(_updated_master) = updated_master_branch(config, git_dir) else {
-        return Ok(None);
-    };
-    let mut git = Command::new("git");
-    if let Some(git_dir) = git_dir {
-        git.current_dir(git_dir);
-    }
-
-    let files = output_result(git.arg("ls-files").arg("--others").arg("--exclude-standard"))?
-        .lines()
-        .map(|s| s.trim().to_owned())
-        .collect();
-    Ok(Some(files))
-}
diff --git a/src/tools/build_helper/src/lib.rs b/src/tools/build_helper/src/lib.rs
deleted file mode 100644
index 4a4f0ca2a9d..00000000000
--- a/src/tools/build_helper/src/lib.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-//! Types and functions shared across tools in this workspace.
-
-pub mod ci;
-pub mod drop_bomb;
-pub mod git;
-pub mod metrics;
-pub mod stage0_parser;
-pub mod util;
-
-/// The default set of crates for opt-dist to collect LLVM profiles.
-pub const LLVM_PGO_CRATES: &[&str] = &[
-    "syn-1.0.89",
-    "cargo-0.60.0",
-    "serde-1.0.136",
-    "ripgrep-13.0.0",
-    "regex-1.5.5",
-    "clap-3.1.6",
-    "hyper-0.14.18",
-];
-
-/// The default set of crates for opt-dist to collect rustc profiles.
-pub const RUSTC_PGO_CRATES: &[&str] = &[
-    "externs",
-    "ctfe-stress-5",
-    "cargo-0.60.0",
-    "token-stream-stress",
-    "match-stress",
-    "tuple-stress",
-    "diesel-1.4.8",
-    "bitmaps-3.1.0",
-];
diff --git a/src/tools/build_helper/src/metrics.rs b/src/tools/build_helper/src/metrics.rs
deleted file mode 100644
index 2d0c66a8f33..00000000000
--- a/src/tools/build_helper/src/metrics.rs
+++ /dev/null
@@ -1,92 +0,0 @@
-use serde_derive::{Deserialize, Serialize};
-
-#[derive(Serialize, Deserialize)]
-#[serde(rename_all = "snake_case")]
-pub struct JsonRoot {
-    #[serde(default)] // For version 0 the field was not present.
-    pub format_version: usize,
-    pub system_stats: JsonInvocationSystemStats,
-    pub invocations: Vec<JsonInvocation>,
-}
-
-#[derive(Serialize, Deserialize)]
-#[serde(rename_all = "snake_case")]
-pub struct JsonInvocation {
-    // Unix timestamp in seconds
-    //
-    // This is necessary to easily correlate this invocation with logs or other data.
-    pub start_time: u64,
-    pub duration_including_children_sec: f64,
-    pub children: Vec<JsonNode>,
-}
-
-#[derive(Serialize, Deserialize)]
-#[serde(tag = "kind", rename_all = "snake_case")]
-pub enum JsonNode {
-    RustbuildStep {
-        #[serde(rename = "type")]
-        type_: String,
-        debug_repr: String,
-
-        duration_excluding_children_sec: f64,
-        system_stats: JsonStepSystemStats,
-
-        children: Vec<JsonNode>,
-    },
-    TestSuite(TestSuite),
-}
-
-#[derive(Serialize, Deserialize)]
-pub struct TestSuite {
-    pub metadata: TestSuiteMetadata,
-    pub tests: Vec<Test>,
-}
-
-#[derive(Serialize, Deserialize)]
-#[serde(tag = "kind", rename_all = "snake_case")]
-pub enum TestSuiteMetadata {
-    CargoPackage {
-        crates: Vec<String>,
-        target: String,
-        host: String,
-        stage: u32,
-    },
-    Compiletest {
-        suite: String,
-        mode: String,
-        compare_mode: Option<String>,
-        target: String,
-        host: String,
-        stage: u32,
-    },
-}
-
-#[derive(Serialize, Deserialize)]
-pub struct Test {
-    pub name: String,
-    #[serde(flatten)]
-    pub outcome: TestOutcome,
-}
-
-#[derive(Serialize, Deserialize)]
-#[serde(tag = "outcome", rename_all = "snake_case")]
-pub enum TestOutcome {
-    Passed,
-    Failed,
-    Ignored { ignore_reason: Option<String> },
-}
-
-#[derive(Serialize, Deserialize)]
-#[serde(rename_all = "snake_case")]
-pub struct JsonInvocationSystemStats {
-    pub cpu_threads_count: usize,
-    pub cpu_model: String,
-
-    pub memory_total_bytes: u64,
-}
-
-#[derive(Serialize, Deserialize)]
-#[serde(rename_all = "snake_case")]
-pub struct JsonStepSystemStats {
-    pub cpu_utilization_percent: f64,
-}
diff --git a/src/tools/build_helper/src/stage0_parser.rs b/src/tools/build_helper/src/stage0_parser.rs
deleted file mode 100644
index ff05b116989..00000000000
--- a/src/tools/build_helper/src/stage0_parser.rs
+++ /dev/null
@@ -1,76 +0,0 @@
-use std::collections::BTreeMap;
-
-#[derive(Default, Clone)]
-pub struct Stage0 {
-    pub compiler: VersionMetadata,
-    pub rustfmt: Option<VersionMetadata>,
-    pub config: Stage0Config,
-    pub checksums_sha256: BTreeMap<String, String>,
-}
-
-#[derive(Default, Clone)]
-pub struct VersionMetadata {
-    pub date: String,
-    pub version: String,
-}
-
-#[derive(Default, Clone)]
-pub struct Stage0Config {
-    pub dist_server: String,
-    pub artifacts_server: String,
-    pub artifacts_with_llvm_assertions_server: String,
-    pub git_merge_commit_email: String,
-    pub git_repository: String,
-    pub nightly_branch: String,
-}
-
-pub fn parse_stage0_file() -> Stage0 {
-    let stage0_content = include_str!("../../../stage0");
-
-    let mut stage0 = Stage0::default();
-    for line in stage0_content.lines() {
-        let line = line.trim();
-
-        if line.is_empty() {
-            continue;
-        }
-
-        // Ignore comments
-        if line.starts_with('#') {
-            continue;
-        }
-
-        let (key, value) = line.split_once('=').unwrap();
-
-        match key {
-            "dist_server" => stage0.config.dist_server = value.to_owned(),
-            "artifacts_server" => stage0.config.artifacts_server = value.to_owned(),
-            "artifacts_with_llvm_assertions_server" => {
-                stage0.config.artifacts_with_llvm_assertions_server = value.to_owned()
-            }
-            "git_merge_commit_email" => stage0.config.git_merge_commit_email = value.to_owned(),
-            "git_repository" => stage0.config.git_repository = value.to_owned(),
-            "nightly_branch" => stage0.config.nightly_branch = value.to_owned(),
-
-            "compiler_date" => stage0.compiler.date = value.to_owned(),
-            "compiler_version" => stage0.compiler.version = value.to_owned(),
-
-            "rustfmt_date" => {
-                stage0.rustfmt.get_or_insert(VersionMetadata::default()).date = value.to_owned();
-            }
-            "rustfmt_version" => {
-                stage0.rustfmt.get_or_insert(VersionMetadata::default()).version = value.to_owned();
-            }
-
-            dist if dist.starts_with("dist") => {
-                stage0.checksums_sha256.insert(key.to_owned(), value.to_owned());
-            }
-
-            unsupported => {
-                println!("'{unsupported}' field is not supported.");
-            }
-        }
-    }
-
-    stage0
-}
diff --git a/src/tools/build_helper/src/util.rs b/src/tools/build_helper/src/util.rs
deleted file mode 100644
index 72c05c4c48a..00000000000
--- a/src/tools/build_helper/src/util.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-use std::fs::File;
-use std::io::{BufRead, BufReader};
-use std::path::Path;
-use std::process::Command;
-use std::sync::OnceLock;
-
-/// Invokes `build_helper::util::detail_exit` with `cfg!(test)`
-///
-/// This is a macro instead of a function so that it uses `cfg(test)` in the *calling* crate, not in build helper.
-#[macro_export]
-macro_rules! exit {
-    ($code:expr) => {
-        $crate::util::detail_exit($code, cfg!(test));
-    };
-}
-
-/// If code is not 0 (successful exit status), exit status is 101 (rust's default error code.)
-/// If `is_test` true and code is an error code, it will cause a panic.
-pub fn detail_exit(code: i32, is_test: bool) -> ! {
-    // if in test and code is an error code, panic with status code provided
-    if is_test {
-        panic!("status code: {}", code);
-    } else {
-        // otherwise,exit with provided status code
-        std::process::exit(code);
-    }
-}
-
-pub fn fail(s: &str) -> ! {
-    eprintln!("\n\n{}\n\n", s);
-    detail_exit(1, cfg!(test));
-}
-
-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() {
-        if print_cmd_on_fail {
-            println!(
-                "\n\ncommand did not execute successfully: {:?}\n\
-                 expected success, got: {}\n\n",
-                cmd, status
-            );
-        }
-        Err(())
-    } else {
-        Ok(())
-    }
-}
-
-/// Returns the submodule paths from the `.gitmodules` file in the given directory.
-pub fn parse_gitmodules(target_dir: &Path) -> &[String] {
-    static SUBMODULES_PATHS: OnceLock<Vec<String>> = OnceLock::new();
-    let gitmodules = target_dir.join(".gitmodules");
-    assert!(gitmodules.exists(), "'{}' file is missing.", gitmodules.display());
-
-    let init_submodules_paths = || {
-        let file = File::open(gitmodules).unwrap();
-
-        let mut submodules_paths = vec![];
-        for line in BufReader::new(file).lines().map_while(Result::ok) {
-            let line = line.trim();
-            if line.starts_with("path") {
-                let actual_path = line.split(' ').last().expect("Couldn't get value of path");
-                submodules_paths.push(actual_path.to_owned());
-            }
-        }
-
-        submodules_paths
-    };
-
-    SUBMODULES_PATHS.get_or_init(|| init_submodules_paths())
-}
diff --git a/src/tools/bump-stage0/Cargo.toml b/src/tools/bump-stage0/Cargo.toml
index de5d821133d..6ee7a831839 100644
--- a/src/tools/bump-stage0/Cargo.toml
+++ b/src/tools/bump-stage0/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2021"
 
 [dependencies]
 anyhow = "1.0.34"
-build_helper = { path = "../build_helper" }
+build_helper = { path = "../../build_helper" }
 curl = "0.4.38"
 indexmap = { version = "2.0.0", features = ["serde"] }
 serde = { version = "1.0.125", features = ["derive"] }
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 161fa630ed4..dd3124ee9a3 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6071,6 +6071,7 @@ Released 2018-09-13
 [`unnecessary_literal_bound`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_literal_bound
 [`unnecessary_literal_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_literal_unwrap
 [`unnecessary_map_on_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_map_on_constructor
+[`unnecessary_map_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_map_or
 [`unnecessary_min_or_max`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_min_or_max
 [`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed
 [`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation
diff --git a/src/tools/clippy/clippy_dev/src/setup/vscode.rs b/src/tools/clippy/clippy_dev/src/setup/vscode.rs
index 204f4af2cf1..a37c873eed4 100644
--- a/src/tools/clippy/clippy_dev/src/setup/vscode.rs
+++ b/src/tools/clippy/clippy_dev/src/setup/vscode.rs
@@ -84,7 +84,7 @@ fn delete_vs_task_file(path: &Path) -> bool {
 /// It may fail silently.
 fn try_delete_vs_directory_if_empty() {
     let path = Path::new(VSCODE_DIR);
-    if path.read_dir().map_or(false, |mut iter| iter.next().is_none()) {
+    if path.read_dir().is_ok_and(|mut iter| iter.next().is_none()) {
         // The directory is empty. We just try to delete it but allow a silence
         // fail as an empty `.vscode` directory is still valid
         let _silence_result = fs::remove_dir(path);
diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
index dc5a6857089..e21853598c3 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
@@ -16,7 +16,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
             return;
         }
         if let Some(lint_list) = &attr.meta_item_list() {
-            if attr.ident().map_or(false, |ident| is_lint_level(ident.name, attr.id)) {
+            if attr.ident().is_some_and(|ident| is_lint_level(ident.name, attr.id)) {
                 for lint in lint_list {
                     match item.kind {
                         ItemKind::Use(..) => {
diff --git a/src/tools/clippy/clippy_lints/src/attrs/utils.rs b/src/tools/clippy/clippy_lints/src/attrs/utils.rs
index 9b10ae83651..3bb02688bf2 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/utils.rs
@@ -50,7 +50,7 @@ fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_
         block
             .expr
             .as_ref()
-            .map_or(false, |e| is_relevant_expr(cx, typeck_results, e)),
+            .is_some_and(|e| is_relevant_expr(cx, typeck_results, e)),
         |stmt| match &stmt.kind {
             StmtKind::Let(_) => true,
             StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, typeck_results, expr),
@@ -60,7 +60,7 @@ fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_
 }
 
 fn is_relevant_expr(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_>, expr: &Expr<'_>) -> bool {
-    if macro_backtrace(expr.span).last().map_or(false, |macro_call| {
+    if macro_backtrace(expr.span).last().is_some_and(|macro_call| {
         is_panic(cx, macro_call.def_id) || cx.tcx.item_name(macro_call.def_id) == sym::unreachable
     }) {
         return false;
diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
index db5792188dd..7d89195eeca 100644
--- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
+++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
@@ -60,8 +60,8 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -
                 trait_id,
             )
         })
-        .map_or(false, |assoc_item| {
-            let proj = Ty::new_projection_from_args(cx.tcx, assoc_item.def_id, cx.tcx.mk_args_trait(ty, []));
+        .is_some_and(|assoc_item| {
+            let proj = Ty::new_projection(cx.tcx, assoc_item.def_id, cx.tcx.mk_args_trait(ty, []));
             let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj);
 
             nty.is_bool()
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index 26a20bc99a0..896bd5fd03d 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -667,5 +667,5 @@ fn implements_ord(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let ty = cx.typeck_results().expr_ty(expr);
     cx.tcx
         .get_diagnostic_item(sym::Ord)
-        .map_or(false, |id| implements_trait(cx, ty, id, &[]))
+        .is_some_and(|id| implements_trait(cx, ty, id, &[]))
 }
diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs
index bf1d077fec2..a1ca23e65ff 100644
--- a/src/tools/clippy/clippy_lints/src/box_default.rs
+++ b/src/tools/clippy/clippy_lints/src/box_default.rs
@@ -45,7 +45,7 @@ impl LateLintPass<'_> for BoxDefault {
             // And that method is `new`
             && seg.ident.name == sym::new
             // And the call is that of a `Box` method
-            && path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box())
+            && path_def_id(cx, ty).is_some_and(|id| Some(id) == cx.tcx.lang_items().owned_box())
             // And the single argument to the call is another function call
             // This is the `T::default()` (or default equivalent) of `Box::new(T::default())`
             && let ExprKind::Call(arg_path, _) = arg.kind
@@ -83,9 +83,9 @@ fn is_plain_default(cx: &LateContext<'_>, arg_path: &Expr<'_>) -> bool {
 }
 
 fn is_local_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>, ref_expr: &Expr<'_>) -> bool {
-    macro_backtrace(expr.span).next().map_or(false, |call| {
-        cx.tcx.is_diagnostic_item(sym::vec_macro, call.def_id) && call.span.eq_ctxt(ref_expr.span)
-    })
+    macro_backtrace(expr.span)
+        .next()
+        .is_some_and(|call| cx.tcx.is_diagnostic_item(sym::vec_macro, call.def_id) && call.span.eq_ctxt(ref_expr.span))
 }
 
 #[derive(Default)]
diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
index abd80abffe6..332e897def7 100644
--- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
@@ -159,8 +159,7 @@ pub(super) fn check<'tcx>(
         // The same is true if the expression encompassing the cast expression is a unary
         // expression or an addressof expression.
         let needs_block = matches!(cast_expr.kind, ExprKind::Unary(..) | ExprKind::AddrOf(..))
-            || get_parent_expr(cx, expr)
-                .map_or(false, |e| matches!(e.kind, ExprKind::Unary(..) | ExprKind::AddrOf(..)));
+            || get_parent_expr(cx, expr).is_some_and(|e| matches!(e.kind, ExprKind::Unary(..) | ExprKind::AddrOf(..)));
 
         span_lint_and_sugg(
             cx,
diff --git a/src/tools/clippy/clippy_lints/src/comparison_chain.rs b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
index b9baf9af248..c85e3500ebd 100644
--- a/src/tools/clippy/clippy_lints/src/comparison_chain.rs
+++ b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
@@ -110,7 +110,7 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain {
                 let is_ord = cx
                     .tcx
                     .get_diagnostic_item(sym::Ord)
-                    .map_or(false, |id| implements_trait(cx, ty, id, &[]));
+                    .is_some_and(|id| implements_trait(cx, ty, id, &[]));
 
                 if !is_ord {
                     return;
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index c4afdc757d8..3ecd36d3711 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -345,7 +345,7 @@ fn eq_binding_names(s: &Stmt<'_>, names: &[(HirId, Symbol)]) -> bool {
         let mut i = 0usize;
         let mut res = true;
         l.pat.each_binding_or_first(&mut |_, _, _, name| {
-            if names.get(i).map_or(false, |&(_, n)| n == name.name) {
+            if names.get(i).is_some_and(|&(_, n)| n == name.name) {
                 i += 1;
             } else {
                 res = false;
@@ -389,12 +389,10 @@ fn eq_stmts(
         let new_bindings = &moved_bindings[old_count..];
         blocks
             .iter()
-            .all(|b| get_stmt(b).map_or(false, |s| eq_binding_names(s, new_bindings)))
+            .all(|b| get_stmt(b).is_some_and(|s| eq_binding_names(s, new_bindings)))
     } else {
         true
-    }) && blocks
-        .iter()
-        .all(|b| get_stmt(b).map_or(false, |s| eq.eq_stmt(s, stmt)))
+    }) && blocks.iter().all(|b| get_stmt(b).is_some_and(|s| eq.eq_stmt(s, stmt)))
 }
 
 #[expect(clippy::too_many_lines)]
@@ -451,9 +449,7 @@ fn scan_block_for_eq<'tcx>(
     //     x + 50
     let expr_hash_eq = if let Some(e) = block.expr {
         let hash = hash_expr(cx, e);
-        blocks
-            .iter()
-            .all(|b| b.expr.map_or(false, |e| hash_expr(cx, e) == hash))
+        blocks.iter().all(|b| b.expr.is_some_and(|e| hash_expr(cx, e) == hash))
     } else {
         blocks.iter().all(|b| b.expr.is_none())
     };
@@ -514,7 +510,7 @@ fn scan_block_for_eq<'tcx>(
         });
     if let Some(e) = block.expr {
         for block in blocks {
-            if block.expr.map_or(false, |expr| !eq.eq_expr(expr, e)) {
+            if block.expr.is_some_and(|expr| !eq.eq_expr(expr, e)) {
                 moved_locals.truncate(moved_locals_at_start);
                 return BlockEq {
                     start_end_eq,
@@ -533,7 +529,7 @@ fn scan_block_for_eq<'tcx>(
 }
 
 fn check_for_warn_of_moved_symbol(cx: &LateContext<'_>, symbols: &[(HirId, Symbol)], if_expr: &Expr<'_>) -> bool {
-    get_enclosing_block(cx, if_expr.hir_id).map_or(false, |block| {
+    get_enclosing_block(cx, if_expr.hir_id).is_some_and(|block| {
         let ignore_span = block.span.shrink_to_lo().to(if_expr.span);
 
         symbols
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index edb52851e0c..dff60f76b74 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -481,6 +481,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::methods::UNNECESSARY_JOIN_INFO,
     crate::methods::UNNECESSARY_LAZY_EVALUATIONS_INFO,
     crate::methods::UNNECESSARY_LITERAL_UNWRAP_INFO,
+    crate::methods::UNNECESSARY_MAP_OR_INFO,
     crate::methods::UNNECESSARY_MIN_OR_MAX_INFO,
     crate::methods::UNNECESSARY_RESULT_MAP_OR_ELSE_INFO,
     crate::methods::UNNECESSARY_SORT_BY_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
index 4808c372754..ef6b141920d 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -253,6 +253,6 @@ impl<'tcx> From<Ty<'tcx>> for ExplicitTyBound {
 
 impl<'tcx> From<Option<Ty<'tcx>>> for ExplicitTyBound {
     fn from(v: Option<Ty<'tcx>>) -> Self {
-        Self(v.map_or(false, Ty::is_numeric))
+        Self(v.is_some_and(Ty::is_numeric))
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index 2b6bfafe695..767dda552bc 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -81,7 +81,7 @@ fn is_path_self(e: &Expr<'_>) -> bool {
 fn contains_trait_object(ty: Ty<'_>) -> bool {
     match ty.kind() {
         ty::Ref(_, ty, _) => contains_trait_object(*ty),
-        ty::Adt(def, args) => def.is_box() && args[0].as_type().map_or(false, contains_trait_object),
+        ty::Adt(def, args) => def.is_box() && args[0].as_type().is_some_and(contains_trait_object),
         ty::Dynamic(..) => true,
         _ => false,
     }
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index e569c4dc786..0db6a822ec0 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -327,7 +327,7 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h
     // there's a Copy impl for any instance of the adt.
     if !is_copy(cx, ty) {
         if ty_subs.non_erasable_generics().next().is_some() {
-            let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(&copy_id).map_or(false, |impls| {
+            let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(&copy_id).is_some_and(|impls| {
                 impls.iter().any(|&id| {
                     matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _)
                                         if ty_adt.did() == adt.did())
diff --git a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
index c9173030a55..40377dd841e 100644
--- a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
@@ -47,7 +47,7 @@ pub fn check(
         ),
         _ => (),
     }
-    if !headers.panics && panic_info.map_or(false, |el| !el.1) {
+    if !headers.panics && panic_info.is_some_and(|el| !el.1) {
         span_lint_and_note(
             cx,
             MISSING_PANICS_DOC,
diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
index c7dd7292a14..55afdbf22e1 100644
--- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
@@ -112,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
                             MEM_FORGET,
                             Cow::Owned(format!(
                                 "usage of `mem::forget` on {}",
-                                if arg_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) {
+                                if arg_ty.ty_adt_def().is_some_and(|def| def.has_dtor(cx.tcx)) {
                                     "`Drop` type"
                                 } else {
                                     "type with `Drop` fields"
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index de10b7bf533..6c87a05ace3 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -196,7 +196,7 @@ fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tc
             {
                 span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
                     if let Some(mut snippet) = snippet_opt(cx, callee.span) {
-                        if path_to_local(callee).map_or(false, |l| {
+                        if path_to_local(callee).is_some_and(|l| {
                             // FIXME: Do we really need this `local_used_in` check?
                             // Isn't it checking something like... `callee(callee)`?
                             // If somehow this check is needed, add some test for it,
diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
index c2b40ae01d4..4986a311eba 100644
--- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
@@ -87,7 +87,7 @@ fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option<HirId> {
 }
 
 fn check_arg(cx: &LateContext<'_>, raw_ptrs: &HirIdSet, arg: &hir::Expr<'_>) {
-    if path_to_local(arg).map_or(false, |id| raw_ptrs.contains(&id)) {
+    if path_to_local(arg).is_some_and(|id| raw_ptrs.contains(&id)) {
         span_lint(
             cx,
             NOT_UNSAFE_PTR_ARG_DEREF,
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index 48874d6064b..d3aade31f14 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -171,13 +171,13 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
             if let ExprKind::Path(ref qpath) = path.kind {
                 cx.qpath_res(qpath, path.hir_id)
                     .opt_def_id()
-                    .map_or(false, |id| cx.tcx.is_diagnostic_item(sym::iter_repeat, id))
+                    .is_some_and(|id| cx.tcx.is_diagnostic_item(sym::iter_repeat, id))
                     .into()
             } else {
                 Finite
             }
         },
-        ExprKind::Struct(..) => higher::Range::hir(expr).map_or(false, |r| r.end.is_none()).into(),
+        ExprKind::Struct(..) => higher::Range::hir(expr).is_some_and(|r| r.end.is_none()).into(),
         _ => Finite,
     }
 }
@@ -228,9 +228,7 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
                 let not_double_ended = cx
                     .tcx
                     .get_diagnostic_item(sym::DoubleEndedIterator)
-                    .map_or(false, |id| {
-                        !implements_trait(cx, cx.typeck_results().expr_ty(receiver), id, &[])
-                    });
+                    .is_some_and(|id| !implements_trait(cx, cx.typeck_results().expr_ty(receiver), id, &[]));
                 if not_double_ended {
                     return is_infinite(cx, receiver);
                 }
diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
index dd90e2a6e94..6363f717a5c 100644
--- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
+++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
@@ -309,8 +309,8 @@ fn check_enum_start(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_>
     let item_name_chars = item_name.chars().count();
 
     if count_match_start(item_name, name).char_count == item_name_chars
-        && name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase())
-        && name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric())
+        && name.chars().nth(item_name_chars).is_some_and(|c| !c.is_lowercase())
+        && name.chars().nth(item_name_chars + 1).is_some_and(|c| !c.is_numeric())
     {
         span_lint_hir(
             cx,
diff --git a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
index b19b348c743..25105817ad9 100644
--- a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
@@ -75,7 +75,7 @@ fn check_sig(cx: &LateContext<'_>, name: Symbol, sig: &FnSig<'_>, fn_id: LocalDe
         if cx
             .tcx
             .get_diagnostic_item(sym::Iterator)
-            .map_or(false, |iter_id| !implements_trait(cx, ret_ty, iter_id, &[]))
+            .is_some_and(|iter_id| !implements_trait(cx, ret_ty, iter_id, &[]))
         {
             span_lint(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
index aa8b4d88d2f..c5a2760234f 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -56,7 +56,8 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
             && !item.span.from_expansion()
             && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
             && let ty::Array(element_type, cst) = ty.kind()
-            && let Ok((_, ty::ValTree::Leaf(element_count))) = cst.eval_valtree(cx.tcx, ParamEnv::empty(), item.span)
+            && let Some((ty::ValTree::Leaf(element_count), _)) = cx.tcx
+                .try_normalize_erasing_regions(ParamEnv::empty(), *cst).unwrap_or(*cst).try_to_valtree()
             && let element_count = element_count.to_target_usize(cx.tcx)
             && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
             && u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size)
diff --git a/src/tools/clippy/clippy_lints/src/large_include_file.rs b/src/tools/clippy/clippy_lints/src/large_include_file.rs
index ab3d19f89c3..4f22931a4de 100644
--- a/src/tools/clippy/clippy_lints/src/large_include_file.rs
+++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs
@@ -94,6 +94,8 @@ impl LateLintPass<'_> for LargeIncludeFile {
             // Currently, rustc limits the usage of macro at the top-level of attributes,
             // so we don't need to recurse into each level.
             && let AttrKind::Normal(ref normal) = attr.kind
+            && let Some(doc) = attr.doc_str()
+            && doc.as_str().len() as u64 > self.max_file_size
             && let AttrArgs::Eq(_, AttrArgsEq::Hir(ref meta)) = normal.item.args
             && !attr.span.contains(meta.span)
             // Since the `include_str` is already expanded at this point, we can only take the
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index b7887ef76a5..3ea758e176f 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -622,7 +622,7 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 
     let ty = &cx.typeck_results().expr_ty(expr).peel_refs();
     match ty.kind() {
-        ty::Dynamic(tt, ..) => tt.principal().map_or(false, |principal| {
+        ty::Dynamic(tt, ..) => tt.principal().is_some_and(|principal| {
             let is_empty = sym!(is_empty);
             cx.tcx
                 .associated_items(principal.def_id())
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index d55be2b036a..ce0e1a24a7b 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -737,7 +737,7 @@ fn elision_suggestions(
     suggestions.extend(
         usages
             .iter()
-            .filter(|usage| named_lifetime(usage).map_or(false, |id| elidable_lts.contains(&id)))
+            .filter(|usage| named_lifetime(usage).is_some_and(|id| elidable_lts.contains(&id)))
             .map(|usage| {
                 match cx.tcx.parent_hir_node(usage.hir_id) {
                     Node::Ty(Ty {
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
index bfe2e68b5d1..1721f569541 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
@@ -58,7 +58,7 @@ pub(super) fn check<'tcx>(
             .tcx
             .lang_items()
             .copy_trait()
-            .map_or(false, |id| implements_trait(cx, ty, id, &[]))
+            .is_some_and(|id| implements_trait(cx, ty, id, &[]))
         {
             snippet.push_str(
                 &format!(
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
index af089451759..701567a7d84 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
@@ -416,7 +416,7 @@ fn get_assignments<'a, 'tcx>(
         .chain(*expr)
         .filter(move |e| {
             if let ExprKind::AssignOp(_, place, _) = e.kind {
-                path_to_local(place).map_or(false, |id| {
+                path_to_local(place).is_some_and(|id| {
                     !loop_counters
                         .iter()
                         // skip the first item which should be `StartKind::Range`
diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
index 094b1947324..39e5e140b7a 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
@@ -126,7 +126,7 @@ impl BreakAfterExprVisitor {
             break_after_expr: false,
         };
 
-        get_enclosing_block(cx, hir_id).map_or(false, |block| {
+        get_enclosing_block(cx, hir_id).is_some_and(|block| {
             visitor.visit_block(block);
             visitor.break_after_expr
         })
diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
index d255fea3af2..951ebc9caef 100644
--- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
@@ -50,7 +50,7 @@ pub(super) fn check<'tcx>(
             .tcx
             .lang_items()
             .clone_trait()
-            .map_or(false, |id| implements_trait(cx, ty, id, &[]))
+            .is_some_and(|id| implements_trait(cx, ty, id, &[]))
     {
         // Make sure that the push does not involve possibly mutating values
         match pushed_item.kind {
diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs
index c4c504e1ae4..51fde5288ab 100644
--- a/src/tools/clippy/clippy_lints/src/loops/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs
@@ -256,9 +256,10 @@ fn is_conditional(expr: &Expr<'_>) -> bool {
 /// If `arg` was the argument to a `for` loop, return the "cleanest" way of writing the
 /// actual `Iterator` that the loop uses.
 pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic_ref: &mut Applicability) -> String {
-    let impls_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| {
-        implements_trait(cx, cx.typeck_results().expr_ty(arg), id, &[])
-    });
+    let impls_iterator = cx
+        .tcx
+        .get_diagnostic_item(sym::Iterator)
+        .is_some_and(|id| implements_trait(cx, cx.typeck_results().expr_ty(arg), id, &[]));
     if impls_iterator {
         format!(
             "{}",
diff --git a/src/tools/clippy/clippy_lints/src/manual_clamp.rs b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
index fd66cacdfe9..016ec7320a6 100644
--- a/src/tools/clippy/clippy_lints/src/manual_clamp.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
@@ -226,7 +226,7 @@ impl TypeClampability {
         } else if cx
             .tcx
             .get_diagnostic_item(sym::Ord)
-            .map_or(false, |id| implements_trait(cx, ty, id, &[]))
+            .is_some_and(|id| implements_trait(cx, ty, id, &[]))
         {
             Some(TypeClampability::Ord)
         } else {
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 828c5a3f6ff..3f401eff6bd 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -162,9 +162,9 @@ fn eq_pattern_length<'tcx>(cx: &LateContext<'tcx>, pattern: &Expr<'_>, expr: &'t
         ..
     }) = expr.kind
     {
-        constant_length(cx, pattern).map_or(false, |length| *n == length)
+        constant_length(cx, pattern).is_some_and(|length| *n == length)
     } else {
-        len_arg(cx, expr).map_or(false, |arg| eq_expr_value(cx, pattern, arg))
+        len_arg(cx, expr).is_some_and(|arg| eq_expr_value(cx, pattern, arg))
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
index 6d62b530ae7..47472ab831f 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
@@ -74,7 +74,7 @@ where
         && b0 != b1
         && (first_guard.is_none() || iter.len() == 0)
         && first_attrs.is_empty()
-        && iter.all(|arm| find_bool_lit(&arm.2.kind).map_or(false, |b| b == b0) && arm.3.is_none() && arm.0.is_empty())
+        && iter.all(|arm| find_bool_lit(&arm.2.kind).is_some_and(|b| b == b0) && arm.3.is_none() && arm.0.is_empty())
     {
         if let Some(last_pat) = last_pat_opt {
             if !is_wild(last_pat) {
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
index ca45ed6ea59..264458a86ef 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -447,7 +447,7 @@ fn is_pat_variant(cx: &LateContext<'_>, pat: &Pat<'_>, path: &QPath<'_>, expecte
             .tcx
             .lang_items()
             .get(expected_lang_item)
-            .map_or(false, |expected_id| cx.tcx.parent(id) == expected_id),
+            .is_some_and(|expected_id| cx.tcx.parent(id) == expected_id),
         Item::Diag(expected_ty, expected_variant) => {
             let ty = cx.typeck_results().pat_ty(pat);
 
diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
index 2aea25b5f12..95a4bf6f60d 100644
--- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
@@ -175,7 +175,7 @@ impl<'tcx> Visitor<'tcx> for PatVisitor<'tcx> {
         if matches!(pat.kind, PatKind::Binding(..)) {
             ControlFlow::Break(())
         } else {
-            self.has_enum |= self.typeck.pat_ty(pat).ty_adt_def().map_or(false, AdtDef::is_enum);
+            self.has_enum |= self.typeck.pat_ty(pat).ty_adt_def().is_some_and(AdtDef::is_enum);
             walk_pat(self, pat)
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/matches/try_err.rs b/src/tools/clippy/clippy_lints/src/matches/try_err.rs
index c7e1b70d19e..6c02207af49 100644
--- a/src/tools/clippy/clippy_lints/src/matches/try_err.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/try_err.rs
@@ -58,7 +58,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine
                 let span = hygiene::walk_chain(err_arg.span, try_arg.span.ctxt());
                 let mut applicability = Applicability::MachineApplicable;
                 let origin_snippet = snippet_with_applicability(cx, span, "_", &mut applicability);
-                let ret_prefix = if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::Ret(_))) {
+                let ret_prefix = if get_parent_expr(cx, expr).is_some_and(|e| matches!(e.kind, ExprKind::Ret(_))) {
                     "" // already returns
                 } else {
                     "return "
diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
index c288dbdabe9..6dc48c26ba9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
@@ -83,7 +83,7 @@ pub(super) fn check<'tcx>(
             hir::ExprKind::MethodCall(..) => {
                 cx.typeck_results()
                     .type_dependent_def_id(arg.hir_id)
-                    .map_or(false, |method_id| {
+                    .is_some_and(|method_id| {
                         matches!(
                             cx.tcx.fn_sig(method_id).instantiate_identity().output().skip_binder().kind(),
                             ty::Ref(re, ..) if re.is_static()
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
index e697ba656f5..6c1a14fc882 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
@@ -32,9 +32,10 @@ pub(super) fn check<'tcx>(
     filter_arg: &'tcx hir::Expr<'_>,
 ) {
     // lint if caller of `.filter().next()` is an Iterator
-    let recv_impls_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| {
-        implements_trait(cx, cx.typeck_results().expr_ty(recv), id, &[])
-    });
+    let recv_impls_iterator = cx
+        .tcx
+        .get_diagnostic_item(sym::Iterator)
+        .is_some_and(|id| implements_trait(cx, cx.typeck_results().expr_ty(recv), id, &[]));
     if recv_impls_iterator {
         let msg = "called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling \
                    `.find(..)` instead";
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs b/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs
index 5f3fec53827..9a03559b223 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs
@@ -19,9 +19,7 @@ pub(super) fn check<'tcx>(
     if cx
         .tcx
         .get_diagnostic_item(sym::DoubleEndedIterator)
-        .map_or(false, |double_ended_iterator| {
-            implements_trait(cx, rev_recv_ty, double_ended_iterator, &[])
-        })
+        .is_some_and(|double_ended_iterator| implements_trait(cx, rev_recv_ty, double_ended_iterator, &[]))
         && is_trait_method(cx, rev_call, sym::Iterator)
         && is_trait_method(cx, expr, sym::Iterator)
     {
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
index 61e74369cb0..098721dc046 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
@@ -36,8 +36,8 @@ fn parse_repeat_arg(cx: &LateContext<'_>, e: &Expr<'_>) -> Option<RepeatKind> {
     } else {
         let ty = cx.typeck_results().expr_ty(e);
         if is_type_lang_item(cx, ty, LangItem::String)
-            || (is_type_lang_item(cx, ty, LangItem::OwnedBox) && get_ty_param(ty).map_or(false, Ty::is_str))
-            || (is_type_diagnostic_item(cx, ty, sym::Cow) && get_ty_param(ty).map_or(false, Ty::is_str))
+            || (is_type_lang_item(cx, ty, LangItem::OwnedBox) && get_ty_param(ty).is_some_and(Ty::is_str))
+            || (is_type_diagnostic_item(cx, ty, sym::Cow) && get_ty_param(ty).is_some_and(Ty::is_str))
         {
             Some(RepeatKind::String)
         } else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
index 515d4a11ed5..d5594b21db5 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
@@ -70,7 +70,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_
                                 if ident_eq(name, obj) && method.ident.name == sym::clone
                                 && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id)
                                 && let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
-                                && cx.tcx.lang_items().clone_trait().map_or(false, |id| id == trait_id)
+                                && cx.tcx.lang_items().clone_trait() == Some(trait_id)
                                 // no autoderefs
                                 && !cx.typeck_results().expr_adjustments(obj).iter()
                                     .any(|a| matches!(a.kind, Adjust::Deref(Some(..))))
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index b1809796355..795e041ffd9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -121,6 +121,7 @@ mod unnecessary_iter_cloned;
 mod unnecessary_join;
 mod unnecessary_lazy_eval;
 mod unnecessary_literal_unwrap;
+mod unnecessary_map_or;
 mod unnecessary_min_or_max;
 mod unnecessary_result_map_or_else;
 mod unnecessary_sort_by;
@@ -4101,6 +4102,33 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
+    /// Converts some constructs mapping an Enum value for equality comparison.
+    ///
+    /// ### Why is this bad?
+    /// Calls such as `opt.map_or(false, |val| val == 5)` are needlessly long and cumbersome,
+    /// and can be reduced to, for example, `opt == Some(5)` assuming `opt` implements `PartialEq`.
+    /// This lint offers readability and conciseness improvements.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// pub fn a(x: Option<i32>) -> bool {
+    ///     x.map_or(false, |n| n == 5)
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// pub fn a(x: Option<i32>) -> bool {
+    ///     x == Some(5)
+    /// }
+    /// ```
+    #[clippy::version = "1.75.0"]
+    pub UNNECESSARY_MAP_OR,
+    style,
+    "reduce unnecessary pattern matching for constructs that implement `PartialEq`"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
     /// Checks if an iterator is used to check if a string is ascii.
     ///
     /// ### Why is this bad?
@@ -4417,6 +4445,7 @@ impl_lint_pass!(Methods => [
     NEEDLESS_AS_BYTES,
     MAP_ALL_ANY_IDENTITY,
     MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES,
+    UNNECESSARY_MAP_OR,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -4950,6 +4979,7 @@ impl Methods {
                     option_map_or_none::check(cx, expr, recv, def, map);
                     manual_ok_or::check(cx, expr, recv, def, map);
                     option_map_or_err_ok::check(cx, expr, recv, def, map);
+                    unnecessary_map_or::check(cx, expr, recv, def, map, &self.msrv);
                 },
                 ("map_or_else", [def, map]) => {
                     result_map_or_else_none::check(cx, expr, recv, def, map);
@@ -5343,7 +5373,7 @@ impl SelfKind {
                 boxed_ty == parent_ty
             } else if is_type_diagnostic_item(cx, ty, sym::Rc) || is_type_diagnostic_item(cx, ty, sym::Arc) {
                 if let ty::Adt(_, args) = ty.kind() {
-                    args.types().next().map_or(false, |t| t == parent_ty)
+                    args.types().next() == Some(parent_ty)
                 } else {
                     false
                 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index 055107068ae..9c41528e647 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -193,7 +193,7 @@ fn check_collect_into_intoiterator<'tcx>(
 
 /// Checks if the given method call matches the expected signature of `([&[mut]] self) -> bool`
 fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool {
-    cx.typeck_results().type_dependent_def_id(call_id).map_or(false, |id| {
+    cx.typeck_results().type_dependent_def_id(call_id).is_some_and(|id| {
         let sig = cx.tcx.fn_sig(id).instantiate_identity().skip_binder();
         sig.inputs().len() == 1 && sig.output().is_bool()
     })
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
index 389e02056b2..998bdee0157 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -45,7 +45,7 @@ pub(super) fn check(
         hir::ExprKind::Path(ref expr_qpath) => {
             cx.qpath_res(expr_qpath, map_arg.hir_id)
                 .opt_def_id()
-                .map_or(false, |fun_def_id| {
+                .is_some_and(|fun_def_id| {
                     cx.tcx.is_diagnostic_item(sym::deref_method, fun_def_id)
                         || cx.tcx.is_diagnostic_item(sym::deref_mut_method, fun_def_id)
                         || deref_aliases
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
index b685a466b72..6b39b753885 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
@@ -59,9 +59,7 @@ pub(super) fn check<'tcx>(
                 let output_ty = cx.tcx.fn_sig(def_id).instantiate(cx.tcx, args).skip_binder().output();
                 cx.tcx
                     .get_diagnostic_item(sym::Default)
-                    .map_or(false, |default_trait_id| {
-                        implements_trait(cx, output_ty, default_trait_id, &[])
-                    })
+                    .is_some_and(|default_trait_id| implements_trait(cx, output_ty, default_trait_id, &[]))
             } else {
                 false
             }
diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
index a2a7de905ca..1cee28e1986 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -348,7 +348,7 @@ fn parse_iter_usage<'tcx>(
                     && cx
                         .typeck_results()
                         .type_dependent_def_id(e.hir_id)
-                        .map_or(false, |id| is_diag_item_method(cx, id, sym::Option)) =>
+                        .is_some_and(|id| is_diag_item_method(cx, id, sym::Option)) =>
             {
                 (Some(UnwrapKind::Unwrap), e.span)
             },
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs
new file mode 100644
index 00000000000..adc27cd437f
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs
@@ -0,0 +1,131 @@
+use std::borrow::Cow;
+
+use clippy_config::msrvs::{self, Msrv};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::eager_or_lazy::switch_to_eager_eval;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::sugg::{Sugg, make_binop};
+use clippy_utils::ty::{get_type_diagnostic_name, implements_trait};
+use clippy_utils::visitors::is_local_used;
+use clippy_utils::{is_from_proc_macro, path_to_local_id};
+use rustc_ast::LitKind::Bool;
+use rustc_errors::Applicability;
+use rustc_hir::{BinOpKind, Expr, ExprKind, PatKind};
+use rustc_lint::LateContext;
+use rustc_span::sym;
+
+use super::UNNECESSARY_MAP_OR;
+
+pub(super) enum Variant {
+    Ok,
+    Some,
+}
+impl Variant {
+    pub fn variant_name(&self) -> &'static str {
+        match self {
+            Variant::Ok => "Ok",
+            Variant::Some => "Some",
+        }
+    }
+
+    pub fn method_name(&self) -> &'static str {
+        match self {
+            Variant::Ok => "is_ok_and",
+            Variant::Some => "is_some_and",
+        }
+    }
+}
+
+pub(super) fn check<'a>(
+    cx: &LateContext<'a>,
+    expr: &Expr<'a>,
+    recv: &Expr<'_>,
+    def: &Expr<'_>,
+    map: &Expr<'_>,
+    msrv: &Msrv,
+) {
+    let ExprKind::Lit(def_kind) = def.kind else {
+        return;
+    };
+
+    let recv_ty = cx.typeck_results().expr_ty(recv);
+
+    let Bool(def_bool) = def_kind.node else {
+        return;
+    };
+
+    let variant = match get_type_diagnostic_name(cx, recv_ty) {
+        Some(sym::Option) => Variant::Some,
+        Some(sym::Result) => Variant::Ok,
+        Some(_) | None => return,
+    };
+
+    let (sugg, method) = if let ExprKind::Closure(map_closure) = map.kind
+            && let closure_body = cx.tcx.hir().body(map_closure.body)
+            && let closure_body_value = closure_body.value.peel_blocks()
+            && let ExprKind::Binary(op, l, r) = closure_body_value.kind
+            && let Some(param) = closure_body.params.first()
+            && let PatKind::Binding(_, hir_id, _, _) = param.pat.kind
+            // checking that map_or is one of the following:
+            // .map_or(false, |x| x == y)
+            // .map_or(false, |x| y == x) - swapped comparison
+            // .map_or(true, |x| x != y)
+            // .map_or(true, |x| y != x) - swapped comparison
+            && ((BinOpKind::Eq == op.node && !def_bool) || (BinOpKind::Ne == op.node && def_bool))
+            && let non_binding_location = if path_to_local_id(l, hir_id) { r } else { l }
+            && switch_to_eager_eval(cx, non_binding_location)
+            // xor, because if its both then thats a strange edge case and
+            // we can just ignore it, since by default clippy will error on this
+            && (path_to_local_id(l, hir_id) ^ path_to_local_id(r, hir_id))
+            && !is_local_used(cx, non_binding_location, hir_id)
+            && let typeck_results = cx.typeck_results()
+            && typeck_results.expr_ty(l) == typeck_results.expr_ty(r)
+            && let Some(partial_eq) = cx.tcx.get_diagnostic_item(sym::PartialEq)
+            && implements_trait(cx, recv_ty, partial_eq, &[recv_ty.into()])
+    {
+        let wrap = variant.variant_name();
+
+        // we may need to add parens around the suggestion
+        // in case the parent expression has additional method calls,
+        // since for example `Some(5).map_or(false, |x| x == 5).then(|| 1)`
+        // being converted to `Some(5) == Some(5).then(|| 1)` isnt
+        // the same thing
+
+        let inner_non_binding = Sugg::NonParen(Cow::Owned(format!(
+            "{wrap}({})",
+            Sugg::hir(cx, non_binding_location, "")
+        )));
+
+        let binop = make_binop(op.node, &Sugg::hir(cx, recv, ".."), &inner_non_binding)
+            .maybe_par()
+            .into_string();
+
+        (binop, "a standard comparison")
+    } else if !def_bool
+        && msrv.meets(msrvs::OPTION_RESULT_IS_VARIANT_AND)
+        && let Some(recv_callsite) = snippet_opt(cx, recv.span.source_callsite())
+        && let Some(span_callsite) = snippet_opt(cx, map.span.source_callsite())
+    {
+        let suggested_name = variant.method_name();
+        (
+            format!("{recv_callsite}.{suggested_name}({span_callsite})",),
+            suggested_name,
+        )
+    } else {
+        return;
+    };
+
+    if is_from_proc_macro(cx, expr) {
+        return;
+    }
+
+    span_lint_and_sugg(
+        cx,
+        UNNECESSARY_MAP_OR,
+        expr.span,
+        "this `map_or` is redundant",
+        format!("use {method} instead"),
+        sugg,
+        Applicability::MaybeIncorrect,
+    );
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
index 6911da69b94..603916e06c9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
@@ -166,9 +166,10 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Exp
             },
         )) = &left_expr.kind
             && left_name == left_ident
-            && cx.tcx.get_diagnostic_item(sym::Ord).map_or(false, |id| {
-                implements_trait(cx, cx.typeck_results().expr_ty(left_expr), id, &[])
-            })
+            && cx
+                .tcx
+                .get_diagnostic_item(sym::Ord)
+                .is_some_and(|id| implements_trait(cx, cx.typeck_results().expr_ty(left_expr), id, &[]))
         {
             return Some(LintTrigger::Sort(SortDetection { vec_name }));
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
index c309e778116..82313257e5c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
@@ -124,7 +124,7 @@ fn is_calling_clone(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool {
                         && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id)
                         && let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
                         // We check it's the `Clone` trait.
-                        && cx.tcx.lang_items().clone_trait().map_or(false, |id| id == trait_id)
+                        && cx.tcx.lang_items().clone_trait().is_some_and(|id| id == trait_id)
                         // no autoderefs
                         && !cx.typeck_results().expr_adjustments(obj).iter()
                             .any(|a| matches!(a.kind, Adjust::Deref(Some(..))))
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
index 4cba13a05c2..37d7427f9a5 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
@@ -427,7 +427,7 @@ impl MiscEarlyLints {
         // See <https://github.com/rust-lang/rust-clippy/issues/4507> for a regression.
         // FIXME: Find a better way to detect those cases.
         let lit_snip = match snippet_opt(cx, span) {
-            Some(snip) if snip.chars().next().map_or(false, |c| c.is_ascii_digit()) => snip,
+            Some(snip) if snip.chars().next().is_some_and(|c| c.is_ascii_digit()) => snip,
             _ => return,
         };
 
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
index f7fa31d83aa..c1424b9f1dc 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
@@ -134,9 +134,11 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowsForGenericArgs<'tcx> {
     }
 
     fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &Body<'_>) {
-        if self.possible_borrowers.last().map_or(false, |&(local_def_id, _)| {
-            local_def_id == cx.tcx.hir().body_owner_def_id(body.id())
-        }) {
+        if self
+            .possible_borrowers
+            .last()
+            .is_some_and(|&(local_def_id, _)| local_def_id == cx.tcx.hir().body_owner_def_id(body.id()))
+        {
             self.possible_borrowers.pop();
         }
     }
@@ -232,7 +234,7 @@ fn needless_borrow_count<'tcx>(
     let mut check_reference_and_referent = |reference: &Expr<'tcx>, referent: &Expr<'tcx>| {
         if let ExprKind::Field(base, _) = &referent.kind {
             let base_ty = cx.typeck_results().expr_ty(base);
-            if drop_trait_def_id.map_or(false, |id| implements_trait(cx, base_ty, id, &[])) {
+            if drop_trait_def_id.is_some_and(|id| implements_trait(cx, base_ty, id, &[])) {
                 return false;
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs
index c4836772933..c48232f9905 100644
--- a/src/tools/clippy/clippy_lints/src/needless_continue.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs
@@ -153,7 +153,7 @@ fn needless_continue_in_else(else_expr: &ast::Expr, label: Option<&ast::Label>)
 }
 
 fn is_first_block_stmt_continue(block: &ast::Block, label: Option<&ast::Label>) -> bool {
-    block.stmts.first().map_or(false, |stmt| match stmt.kind {
+    block.stmts.first().is_some_and(|stmt| match stmt.kind {
         ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => {
             if let ast::ExprKind::Continue(ref l) = e.kind {
                 compare_labels(label, l.as_ref())
@@ -390,7 +390,7 @@ fn check_and_warn(cx: &EarlyContext<'_>, expr: &ast::Expr) {
 #[must_use]
 fn erode_from_back(s: &str) -> String {
     let mut ret = s.to_string();
-    while ret.pop().map_or(false, |c| c != '}') {}
+    while ret.pop().is_some_and(|c| c != '}') {}
     while let Some(c) = ret.pop() {
         if !c.is_whitespace() {
             ret.push(c);
diff --git a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
index a13391a5945..83f7d931969 100644
--- a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
+++ b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
@@ -88,7 +88,7 @@ fn is_offending_macro(cx: &EarlyContext<'_>, span: Span, mac_braces: &MacroBrace
             || span
                 .macro_backtrace()
                 .last()
-                .map_or(false, |e| e.macro_def_id.map_or(false, DefId::is_local))
+                .is_some_and(|e| e.macro_def_id.is_some_and(DefId::is_local))
     };
     let span_call_site = span.ctxt().outer_expn_data().call_site;
     if let ExpnKind::Macro(MacroKind::Bang, mac_name) = span.ctxt().outer_expn_data().kind
diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
index 372128ac16f..13b3d240700 100644
--- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
@@ -290,7 +290,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
                     Some((Node::Expr(parent), child_id)) => match parent.kind {
                         // Recursive call. Track which index the parameter is used in.
                         ExprKind::Call(callee, args)
-                            if path_def_id(cx, callee).map_or(false, |id| {
+                            if path_def_id(cx, callee).is_some_and(|id| {
                                 id == param.fn_id && has_matching_args(param.fn_kind, typeck.node_args(callee.hir_id))
                             }) =>
                         {
@@ -300,7 +300,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
                             return;
                         },
                         ExprKind::MethodCall(_, receiver, args, _)
-                            if typeck.type_dependent_def_id(parent.hir_id).map_or(false, |id| {
+                            if typeck.type_dependent_def_id(parent.hir_id).is_some_and(|id| {
                                 id == param.fn_id && has_matching_args(param.fn_kind, typeck.node_args(parent.hir_id))
                             }) =>
                         {
diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
index 8b9f899d82d..65ef56fd211 100644
--- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
@@ -325,7 +325,7 @@ impl ArithmeticSideEffects {
     fn should_skip_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) -> bool {
         is_lint_allowed(cx, ARITHMETIC_SIDE_EFFECTS, expr.hir_id)
             || self.expr_span.is_some()
-            || self.const_span.map_or(false, |sp| sp.contains(expr.span))
+            || self.const_span.is_some_and(|sp| sp.contains(expr.span))
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
index 208b20a7a06..b0d872e98fd 100644
--- a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
@@ -42,14 +42,12 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
             if typeck
                 .type_dependent_def_id(expr.hir_id)
                 .and_then(|id| cx.tcx.trait_of_item(id))
-                .map_or(false, |id| {
-                    matches!(cx.tcx.get_diagnostic_name(id), Some(sym::ToString | sym::ToOwned))
-                }) =>
+                .is_some_and(|id| matches!(cx.tcx.get_diagnostic_name(id), Some(sym::ToString | sym::ToOwned))) =>
         {
             (arg, arg.span)
         },
         ExprKind::Call(path, [arg])
-            if path_def_id(cx, path).map_or(false, |did| {
+            if path_def_id(cx, path).is_some_and(|did| {
                 if cx.tcx.is_diagnostic_item(sym::from_str_method, did) {
                     true
                 } else if cx.tcx.is_diagnostic_item(sym::from_fn, did) {
diff --git a/src/tools/clippy/clippy_lints/src/operators/identity_op.rs b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
index 830be50c8ba..1c2d6e90fc9 100644
--- a/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
@@ -42,83 +42,43 @@ pub(crate) fn check<'tcx>(
 
     match op {
         BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => {
-            let _ = check_op(
-                cx,
-                left,
-                0,
-                expr.span,
-                peeled_right_span,
-                needs_parenthesis(cx, expr, right),
-                right_is_coerced_to_value,
-            ) || check_op(
-                cx,
-                right,
-                0,
-                expr.span,
-                peeled_left_span,
-                Parens::Unneeded,
-                left_is_coerced_to_value,
-            );
+            if is_redundant_op(cx, left, 0) {
+                let paren = needs_parenthesis(cx, expr, right);
+                span_ineffective_operation(cx, expr.span, peeled_right_span, paren, right_is_coerced_to_value);
+            } else if is_redundant_op(cx, right, 0) {
+                let paren = needs_parenthesis(cx, expr, left);
+                span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value);
+            }
         },
         BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => {
-            let _ = check_op(
-                cx,
-                right,
-                0,
-                expr.span,
-                peeled_left_span,
-                Parens::Unneeded,
-                left_is_coerced_to_value,
-            );
+            if is_redundant_op(cx, right, 0) {
+                let paren = needs_parenthesis(cx, expr, left);
+                span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value);
+            }
         },
         BinOpKind::Mul => {
-            let _ = check_op(
-                cx,
-                left,
-                1,
-                expr.span,
-                peeled_right_span,
-                needs_parenthesis(cx, expr, right),
-                right_is_coerced_to_value,
-            ) || check_op(
-                cx,
-                right,
-                1,
-                expr.span,
-                peeled_left_span,
-                Parens::Unneeded,
-                left_is_coerced_to_value,
-            );
+            if is_redundant_op(cx, left, 1) {
+                let paren = needs_parenthesis(cx, expr, right);
+                span_ineffective_operation(cx, expr.span, peeled_right_span, paren, right_is_coerced_to_value);
+            } else if is_redundant_op(cx, right, 1) {
+                let paren = needs_parenthesis(cx, expr, left);
+                span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value);
+            }
         },
         BinOpKind::Div => {
-            let _ = check_op(
-                cx,
-                right,
-                1,
-                expr.span,
-                peeled_left_span,
-                Parens::Unneeded,
-                left_is_coerced_to_value,
-            );
+            if is_redundant_op(cx, right, 1) {
+                let paren = needs_parenthesis(cx, expr, left);
+                span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value);
+            }
         },
         BinOpKind::BitAnd => {
-            let _ = check_op(
-                cx,
-                left,
-                -1,
-                expr.span,
-                peeled_right_span,
-                needs_parenthesis(cx, expr, right),
-                right_is_coerced_to_value,
-            ) || check_op(
-                cx,
-                right,
-                -1,
-                expr.span,
-                peeled_left_span,
-                Parens::Unneeded,
-                left_is_coerced_to_value,
-            );
+            if is_redundant_op(cx, left, -1) {
+                let paren = needs_parenthesis(cx, expr, right);
+                span_ineffective_operation(cx, expr.span, peeled_right_span, paren, right_is_coerced_to_value);
+            } else if is_redundant_op(cx, right, -1) {
+                let paren = needs_parenthesis(cx, expr, left);
+                span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value);
+            }
         },
         BinOpKind::Rem => check_remainder(cx, left, right, expr.span, left.span),
         _ => (),
@@ -138,43 +98,70 @@ enum Parens {
     Unneeded,
 }
 
-/// Checks if `left op right` needs parenthesis when reduced to `right`
+/// Checks if a binary expression needs parenthesis when reduced to just its
+/// right or left child.
+///
+/// e.g. `-(x + y + 0)` cannot be reduced to `-x + y`, as the behavior changes silently.
+/// e.g. `1u64 + ((x + y + 0i32) as u64)` cannot be reduced to `1u64 + x + y as u64`, since
+/// the the cast expression will not apply to the same expression.
 /// e.g. `0 + if b { 1 } else { 2 } + if b { 3 } else { 4 }` cannot be reduced
 /// to `if b { 1 } else { 2 } + if b { 3 } else { 4 }` where the `if` could be
-/// interpreted as a statement
+/// interpreted as a statement. The same behavior happens for `match`, `loop`,
+/// and blocks.
+/// e.g.  `2 * (0 + { a })` can be reduced to `2 * { a }` without the need for parenthesis,
+/// but `1 * ({ a } + 4)` cannot be reduced to `{ a } + 4`, as a block at the start of a line
+/// will be interpreted as a statement instead of an expression.
 ///
-/// See #8724
-fn needs_parenthesis(cx: &LateContext<'_>, binary: &Expr<'_>, right: &Expr<'_>) -> Parens {
-    match right.kind {
+/// See #8724, #13470
+fn needs_parenthesis(cx: &LateContext<'_>, binary: &Expr<'_>, child: &Expr<'_>) -> Parens {
+    match child.kind {
         ExprKind::Binary(_, lhs, _) | ExprKind::Cast(lhs, _) => {
-            // ensure we're checking against the leftmost expression of `right`
-            //
-            //     ~~~ `lhs`
-            // 0 + {4} * 2
-            //     ~~~~~~~ `right`
-            return needs_parenthesis(cx, binary, lhs);
+            // For casts and binary expressions, we want to add parenthesis if
+            // the parent HIR node is an expression, or if the parent HIR node
+            // is a Block or Stmt, and the new left hand side would need
+            // parenthesis be treated as a statement rather than an expression.
+            if let Some((_, parent)) = cx.tcx.hir().parent_iter(binary.hir_id).next() {
+                match parent {
+                    Node::Expr(_) => return Parens::Needed,
+                    Node::Block(_) | Node::Stmt(_) => {
+                        // ensure we're checking against the leftmost expression of `child`
+                        //
+                        // ~~~~~~~~~~~ `binary`
+                        //     ~~~ `lhs`
+                        // 0 + {4} * 2
+                        //     ~~~~~~~ `child`
+                        return needs_parenthesis(cx, binary, lhs);
+                    },
+                    _ => return Parens::Unneeded,
+                }
+            }
+        },
+        ExprKind::If(..) | ExprKind::Match(..) | ExprKind::Block(..) | ExprKind::Loop(..) => {
+            // For if, match, block, and loop expressions, we want to add parenthesis if
+            // the closest ancestor node that is not an expression is a block or statement.
+            // This would mean that the rustfix suggestion will appear at the start of a line, which causes
+            // these expressions to be interpreted as statements if they do not have parenthesis.
+            let mut prev_id = binary.hir_id;
+            for (_, parent) in cx.tcx.hir().parent_iter(binary.hir_id) {
+                if let Node::Expr(expr) = parent
+                    && let ExprKind::Binary(_, lhs, _) | ExprKind::Cast(lhs, _) | ExprKind::Unary(_, lhs) = expr.kind
+                    && lhs.hir_id == prev_id
+                {
+                    // keep going until we find a node that encompasses left of `binary`
+                    prev_id = expr.hir_id;
+                    continue;
+                }
+
+                match parent {
+                    Node::Block(_) | Node::Stmt(_) => return Parens::Needed,
+                    _ => return Parens::Unneeded,
+                };
+            }
+        },
+        _ => {
+            return Parens::Unneeded;
         },
-        ExprKind::If(..) | ExprKind::Match(..) | ExprKind::Block(..) | ExprKind::Loop(..) => {},
-        _ => return Parens::Unneeded,
-    }
-
-    let mut prev_id = binary.hir_id;
-    for (_, node) in cx.tcx.hir().parent_iter(binary.hir_id) {
-        if let Node::Expr(expr) = node
-            && let ExprKind::Binary(_, lhs, _) | ExprKind::Cast(lhs, _) = expr.kind
-            && lhs.hir_id == prev_id
-        {
-            // keep going until we find a node that encompasses left of `binary`
-            prev_id = expr.hir_id;
-            continue;
-        }
-
-        match node {
-            Node::Block(_) | Node::Stmt(_) => break,
-            _ => return Parens::Unneeded,
-        };
     }
-
     Parens::Needed
 }
 
@@ -199,7 +186,7 @@ fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span
     }
 }
 
-fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, parens: Parens, is_erased: bool) -> bool {
+fn is_redundant_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8) -> bool {
     if let Some(Constant::Int(v)) = ConstEvalCtxt::new(cx).eval_simple(e).map(Constant::peel_refs) {
         let check = match *cx.typeck_results().expr_ty(e).peel_refs().kind() {
             ty::Int(ity) => unsext(cx.tcx, -1_i128, ity),
@@ -212,7 +199,6 @@ fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, pa
             1 => v == 1,
             _ => unreachable!(),
         } {
-            span_ineffective_operation(cx, span, arg, parens, is_erased);
             return true;
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
index 565294bb40a..d369978b8be 100644
--- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
@@ -14,7 +14,7 @@ pub struct Context {
 }
 impl Context {
     fn skip_expr(&mut self, e: &hir::Expr<'_>) -> bool {
-        self.expr_id.is_some() || self.const_span.map_or(false, |span| span.contains(e.span))
+        self.expr_id.is_some() || self.const_span.is_some_and(|span| span.contains(e.span))
     }
 
     pub fn check_binary<'tcx>(
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index 1bddfab39c6..b2089487a9f 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -192,7 +192,7 @@ impl PassByRefOrValue {
                                 continue;
                             }
                         }
-                        let value_type = if fn_body.and_then(|body| body.params.get(index)).map_or(false, is_self) {
+                        let value_type = if fn_body.and_then(|body| body.params.get(index)).is_some_and(is_self) {
                             "self".into()
                         } else {
                             snippet(cx, decl_ty.span, "_").into()
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index a548c6ef3b1..ecc095f3859 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -727,9 +727,8 @@ fn get_ref_lm<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutabili
 
 fn is_null_path(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     if let ExprKind::Call(pathexp, []) = expr.kind {
-        path_def_id(cx, pathexp).map_or(false, |id| {
-            matches!(cx.tcx.get_diagnostic_name(id), Some(sym::ptr_null | sym::ptr_null_mut))
-        })
+        path_def_id(cx, pathexp)
+            .is_some_and(|id| matches!(cx.tcx.get_diagnostic_name(id), Some(sym::ptr_null | sym::ptr_null_mut)))
     } else {
         false
     }
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index cb374fcf20e..a00fd01a62e 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -8,18 +8,18 @@ use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use clippy_utils::{
     eq_expr_value, higher, is_else_clause, is_in_const_context, is_lint_allowed, is_path_lang_item, is_res_lang_ctor,
-    pat_and_expr_can_be_question_mark, path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt,
-    span_contains_comment,
+    pat_and_expr_can_be_question_mark, path_res, path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt,
+    span_contains_cfg, span_contains_comment,
 };
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk};
 use rustc_hir::def::Res;
 use rustc_hir::{
-    BindingMode, Block, Body, ByRef, Expr, ExprKind, LetStmt, Mutability, Node, PatKind, PathSegment, QPath, Stmt,
-    StmtKind,
+    Arm, BindingMode, Block, Body, ByRef, Expr, ExprKind, FnRetTy, HirId, LetStmt, MatchSource, Mutability, Node, Pat,
+    PatKind, PathSegment, QPath, Stmt, StmtKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::Ty;
+use rustc_middle::ty::{self, Ty};
 use rustc_session::impl_lint_pass;
 use rustc_span::sym;
 use rustc_span::symbol::Symbol;
@@ -58,6 +58,9 @@ pub struct QuestionMark {
     /// if it is greater than zero.
     /// As for why we need this in the first place: <https://github.com/rust-lang/rust-clippy/issues/8628>
     try_block_depth_stack: Vec<u32>,
+    /// Keeps track of the number of inferred return type closures we are inside, to avoid problems
+    /// with the `Err(x.into())` expansion being ambiguious.
+    inferred_ret_closure_stack: u16,
 }
 
 impl_lint_pass!(QuestionMark => [QUESTION_MARK, MANUAL_LET_ELSE]);
@@ -68,6 +71,7 @@ impl QuestionMark {
             msrv: conf.msrv.clone(),
             matches_behaviour: conf.matches_for_let_else,
             try_block_depth_stack: Vec::new(),
+            inferred_ret_closure_stack: 0,
         }
     }
 }
@@ -125,7 +129,7 @@ fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
         cx.tcx
             .lang_items()
             .try_trait()
-            .map_or(false, |did| implements_trait(cx, init_ty, did, &[]))
+            .is_some_and(|did| implements_trait(cx, init_ty, did, &[]))
     }
 
     if let StmtKind::Let(LetStmt {
@@ -271,6 +275,135 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex
     }
 }
 
+#[derive(Clone, Copy, Debug)]
+enum TryMode {
+    Result,
+    Option,
+}
+
+fn find_try_mode<'tcx>(cx: &LateContext<'tcx>, scrutinee: &Expr<'tcx>) -> Option<TryMode> {
+    let scrutinee_ty = cx.typeck_results().expr_ty_adjusted(scrutinee);
+    let ty::Adt(scrutinee_adt_def, _) = scrutinee_ty.kind() else {
+        return None;
+    };
+
+    match cx.tcx.get_diagnostic_name(scrutinee_adt_def.did())? {
+        sym::Result => Some(TryMode::Result),
+        sym::Option => Some(TryMode::Option),
+        _ => None,
+    }
+}
+
+// Check that `pat` is `{ctor_lang_item}(val)`, returning `val`.
+fn extract_ctor_call<'a, 'tcx>(
+    cx: &LateContext<'tcx>,
+    expected_ctor: LangItem,
+    pat: &'a Pat<'tcx>,
+) -> Option<&'a Pat<'tcx>> {
+    if let PatKind::TupleStruct(variant_path, [val_binding], _) = &pat.kind
+        && is_res_lang_ctor(cx, cx.qpath_res(variant_path, pat.hir_id), expected_ctor)
+    {
+        Some(val_binding)
+    } else {
+        None
+    }
+}
+
+// Extracts the local ID of a plain `val` pattern.
+fn extract_binding_pat(pat: &Pat<'_>) -> Option<HirId> {
+    if let PatKind::Binding(BindingMode::NONE, binding, _, None) = pat.kind {
+        Some(binding)
+    } else {
+        None
+    }
+}
+
+fn check_arm_is_some_or_ok<'tcx>(cx: &LateContext<'tcx>, mode: TryMode, arm: &Arm<'tcx>) -> bool {
+    let happy_ctor = match mode {
+        TryMode::Result => ResultOk,
+        TryMode::Option => OptionSome,
+    };
+
+    // Check for `Ok(val)` or `Some(val)`
+    if arm.guard.is_none()
+        && let Some(val_binding) = extract_ctor_call(cx, happy_ctor, arm.pat)
+        // Extract out `val`
+        && let Some(binding) = extract_binding_pat(val_binding)
+        // Check body is just `=> val`
+        && path_to_local_id(peel_blocks(arm.body), binding)
+    {
+        true
+    } else {
+        false
+    }
+}
+
+fn check_arm_is_none_or_err<'tcx>(cx: &LateContext<'tcx>, mode: TryMode, arm: &Arm<'tcx>) -> bool {
+    if arm.guard.is_some() {
+        return false;
+    }
+
+    let arm_body = peel_blocks(arm.body);
+    match mode {
+        TryMode::Result => {
+            // Check that pat is Err(val)
+            if let Some(ok_pat) = extract_ctor_call(cx, ResultErr, arm.pat)
+                && let Some(ok_val) = extract_binding_pat(ok_pat)
+                // check `=> return Err(...)`
+                && let ExprKind::Ret(Some(wrapped_ret_expr)) = arm_body.kind
+                && let ExprKind::Call(ok_ctor, [ret_expr]) = wrapped_ret_expr.kind
+                && is_res_lang_ctor(cx, path_res(cx, ok_ctor), ResultErr)
+                // check `...` is `val` from binding
+                && path_to_local_id(ret_expr, ok_val)
+            {
+                true
+            } else {
+                false
+            }
+        },
+        TryMode::Option => {
+            // Check the pat is `None`
+            if is_res_lang_ctor(cx, path_res(cx, arm.pat), OptionNone)
+                // Check `=> return None`
+                && let ExprKind::Ret(Some(ret_expr)) = arm_body.kind
+                && is_res_lang_ctor(cx, path_res(cx, ret_expr), OptionNone)
+                && !ret_expr.span.from_expansion()
+            {
+                true
+            } else {
+                false
+            }
+        },
+    }
+}
+
+fn check_arms_are_try<'tcx>(cx: &LateContext<'tcx>, mode: TryMode, arm1: &Arm<'tcx>, arm2: &Arm<'tcx>) -> bool {
+    (check_arm_is_some_or_ok(cx, mode, arm1) && check_arm_is_none_or_err(cx, mode, arm2))
+        || (check_arm_is_some_or_ok(cx, mode, arm2) && check_arm_is_none_or_err(cx, mode, arm1))
+}
+
+fn check_if_try_match<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+    if let ExprKind::Match(scrutinee, [arm1, arm2], MatchSource::Normal | MatchSource::Postfix) = expr.kind
+        && !expr.span.from_expansion()
+        && let Some(mode) = find_try_mode(cx, scrutinee)
+        && !span_contains_cfg(cx, expr.span)
+        && check_arms_are_try(cx, mode, arm1, arm2)
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        let snippet = snippet_with_applicability(cx, scrutinee.span.source_callsite(), "..", &mut applicability);
+
+        span_lint_and_sugg(
+            cx,
+            QUESTION_MARK,
+            expr.span,
+            "this `match` expression can be replaced with `?`",
+            "try instead",
+            snippet.into_owned() + "?",
+            applicability,
+        );
+    }
+}
+
 fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
     if let Some(higher::IfLet {
         let_pat,
@@ -339,6 +472,17 @@ fn is_try_block(cx: &LateContext<'_>, bl: &Block<'_>) -> bool {
     }
 }
 
+fn is_inferred_ret_closure(expr: &Expr<'_>) -> bool {
+    let ExprKind::Closure(closure) = expr.kind else {
+        return false;
+    };
+
+    match closure.fn_decl.output {
+        FnRetTy::Return(ret_ty) => ret_ty.is_suggestable_infer_ty(),
+        FnRetTy::DefaultReturn(_) => true,
+    }
+}
+
 impl<'tcx> LateLintPass<'tcx> for QuestionMark {
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
         if !is_lint_allowed(cx, QUESTION_MARK_USED, stmt.hir_id) {
@@ -350,11 +494,27 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark {
         }
         self.check_manual_let_else(cx, stmt);
     }
+
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        if is_inferred_ret_closure(expr) {
+            self.inferred_ret_closure_stack += 1;
+            return;
+        }
+
         if !self.inside_try_block() && !is_in_const_context(cx) && is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id)
         {
             check_is_none_or_err_and_early_return(cx, expr);
             check_if_let_some_or_err_and_early_return(cx, expr);
+
+            if self.inferred_ret_closure_stack == 0 {
+                check_if_try_match(cx, expr);
+            }
+        }
+    }
+
+    fn check_expr_post(&mut self, _: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if is_inferred_ret_closure(expr) {
+            self.inferred_ret_closure_stack -= 1;
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
index 030df535c35..dc66fb28fa8 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
@@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
             let (expr_ty, expr_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(expr));
             let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed));
             let parent_expr = get_parent_expr(cx, expr);
-            let needs_parens_for_prefix = parent_expr.map_or(false, |parent| parent.precedence().order() > PREC_PREFIX);
+            let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence().order() > PREC_PREFIX);
 
             if expr_ty == indexed_ty {
                 if expr_ref_count > indexed_ref_count {
@@ -107,7 +107,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
                         kind: ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _),
                         ..
                     })
-                ) || cx.typeck_results().expr_adjustments(expr).first().map_or(false, |a| {
+                ) || cx.typeck_results().expr_adjustments(expr).first().is_some_and(|a| {
                     matches!(
                         a.kind,
                         Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::Mut { .. }))
diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs
index 23362506cca..78f0b7d121c 100644
--- a/src/tools/clippy/clippy_lints/src/swap.rs
+++ b/src/tools/clippy/clippy_lints/src/swap.rs
@@ -412,9 +412,7 @@ impl<'tcx> IndexBinding<'_, 'tcx> {
                 }
                 Self::is_used_slice_indexed(lhs, idx_ident) || Self::is_used_slice_indexed(rhs, idx_ident)
             },
-            ExprKind::Path(QPath::Resolved(_, path)) => {
-                path.segments.first().map_or(false, |idx| idx.ident == idx_ident)
-            },
+            ExprKind::Path(QPath::Resolved(_, path)) => path.segments.first().is_some_and(|idx| idx.ident == idx_ident),
             _ => false,
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
index eb7ffbbe360..bde88ab61ad 100644
--- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
@@ -51,8 +51,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
                         format!("&{ltopt}({inner_snippet})")
                     },
                     TyKind::Path(qpath)
-                        if get_bounds_if_impl_trait(cx, qpath, inner.hir_id)
-                            .map_or(false, |bounds| bounds.len() > 1) =>
+                        if get_bounds_if_impl_trait(cx, qpath, inner.hir_id).is_some_and(|bounds| bounds.len() > 1) =>
                     {
                         format!("&{ltopt}({inner_snippet})")
                     },
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
index 1a1284ce9c4..6eef582b4b2 100644
--- a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
@@ -38,7 +38,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) {
             return;
         }
 
-        if (local.ty.map_or(false, |ty| !matches!(ty.kind, TyKind::Infer))
+        if (local.ty.is_some_and(|ty| !matches!(ty.kind, TyKind::Infer))
             || matches!(local.pat.kind, PatKind::Tuple([], ddpos) if ddpos.as_opt_usize().is_none()))
             && expr_needs_inferred_result(cx, init)
         {
diff --git a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs
index 91dff5a9523..cbc6885ae5d 100644
--- a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs
+++ b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs
@@ -98,7 +98,7 @@ impl VecPushSearcher {
                     needs_mut |= cx.typeck_results().expr_ty_adjusted(last_place).ref_mutability()
                         == Some(Mutability::Mut)
                         || get_parent_expr(cx, last_place)
-                            .map_or(false, |e| matches!(e.kind, ExprKind::AddrOf(_, Mutability::Mut, _)));
+                            .is_some_and(|e| matches!(e.kind, ExprKind::AddrOf(_, Mutability::Mut, _)));
                 },
                 ExprKind::MethodCall(_, recv, ..)
                     if recv.hir_id == e.hir_id
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index 1dd46ed5a89..a42ddcdae35 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -295,7 +295,7 @@ impl<'tcx> LateLintPass<'tcx> for Write {
             .opts
             .crate_name
             .as_ref()
-            .map_or(false, |crate_name| crate_name == "build_script_build");
+            .is_some_and(|crate_name| crate_name == "build_script_build");
 
         let allowed_in_tests = self.allow_print_in_tests && is_in_test(cx.tcx, expr.hir_id);
         match diag_name {
diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
index 75169e05734..3269bf758ac 100644
--- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
+++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
@@ -51,7 +51,7 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) ->
         return false;
     };
     let end = span.hi() - pos.sf.start_pos;
-    src.get(pos.pos.0 as usize..end.0 as usize).map_or(false, |s| {
+    src.get(pos.pos.0 as usize..end.0 as usize).is_some_and(|s| {
         // Spans can be wrapped in a mixture or parenthesis, whitespace, and trailing commas.
         let start_str = s.trim_start_matches(|c: char| c.is_whitespace() || c == '(');
         let end_str = s.trim_end_matches(|c: char| c.is_whitespace() || c == ')' || c == ',');
@@ -60,13 +60,13 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) ->
             Pat::MultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)),
             Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)),
             Pat::Sym(sym) => start_str.starts_with(sym.as_str()),
-            Pat::Num => start_str.as_bytes().first().map_or(false, u8::is_ascii_digit),
+            Pat::Num => start_str.as_bytes().first().is_some_and(u8::is_ascii_digit),
         } && match end_pat {
             Pat::Str(text) => end_str.ends_with(text),
             Pat::MultiStr(texts) => texts.iter().any(|s| end_str.ends_with(s)),
             Pat::OwnedMultiStr(texts) => texts.iter().any(|s| end_str.ends_with(s)),
             Pat::Sym(sym) => end_str.ends_with(sym.as_str()),
-            Pat::Num => end_str.as_bytes().last().map_or(false, u8::is_ascii_hexdigit),
+            Pat::Num => end_str.as_bytes().last().is_some_and(u8::is_ascii_hexdigit),
         })
     })
 }
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index cb69f8e5a0e..c73ab4bfa68 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -258,7 +258,7 @@ impl HirEqInterExpr<'_, '_, '_> {
     }
 
     fn should_ignore(&mut self, expr: &Expr<'_>) -> bool {
-        macro_backtrace(expr.span).last().map_or(false, |macro_call| {
+        macro_backtrace(expr.span).last().is_some_and(|macro_call| {
             matches!(
                 &self.inner.cx.tcx.get_diagnostic_name(macro_call.def_id),
                 Some(sym::todo_macro | sym::unimplemented_macro)
@@ -322,7 +322,7 @@ impl HirEqInterExpr<'_, '_, '_> {
             (&ExprKind::Block(l, _), &ExprKind::Block(r, _)) => self.eq_block(l, r),
             (&ExprKind::Binary(l_op, ll, lr), &ExprKind::Binary(r_op, rl, rr)) => {
                 l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
-                    || swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| {
+                    || swap_binop(l_op.node, ll, lr).is_some_and(|(l_op, ll, lr)| {
                         l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
                     })
             },
@@ -444,7 +444,7 @@ impl HirEqInterExpr<'_, '_, '_> {
             ) => false,
         };
         (is_eq && (!self.should_ignore(left) || !self.should_ignore(right)))
-            || self.inner.expr_fallback.as_mut().map_or(false, |f| f(left, right))
+            || self.inner.expr_fallback.as_mut().is_some_and(|f| f(left, right))
     }
 
     fn eq_exprs(&mut self, left: &[Expr<'_>], right: &[Expr<'_>]) -> bool {
@@ -724,7 +724,7 @@ fn swap_binop<'a>(
 /// `eq_fn`.
 pub fn both<X>(l: Option<&X>, r: Option<&X>, mut eq_fn: impl FnMut(&X, &X) -> bool) -> bool {
     l.as_ref()
-        .map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y)))
+        .map_or_else(|| r.is_none(), |x| r.as_ref().is_some_and(|y| eq_fn(x, y)))
 }
 
 /// Checks if two slices are equal as per `eq_fn`.
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 50d334acf18..19316a90683 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -342,10 +342,9 @@ pub fn is_ty_alias(qpath: &QPath<'_>) -> bool {
 /// Checks if the method call given in `expr` belongs to the given trait.
 /// This is a deprecated function, consider using [`is_trait_method`].
 pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {
-    cx.typeck_results()
-        .type_dependent_def_id(expr.hir_id)
-        .and_then(|defid| cx.tcx.trait_of_item(defid))
-        .map_or(false, |trt_id| match_def_path(cx, trt_id, path))
+    let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
+    let trt_id = cx.tcx.trait_of_item(def_id);
+    trt_id.is_some_and(|trt_id| match_def_path(cx, trt_id, path))
 }
 
 /// Checks if the given method call expression calls an inherent method.
@@ -379,7 +378,7 @@ pub fn is_diag_trait_item(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol
 pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
     cx.typeck_results()
         .type_dependent_def_id(expr.hir_id)
-        .map_or(false, |did| is_diag_trait_item(cx, did, diag_item))
+        .is_some_and(|did| is_diag_trait_item(cx, did, diag_item))
 }
 
 /// Checks if the `def_id` belongs to a function that is part of a trait impl.
@@ -406,7 +405,7 @@ pub fn is_trait_item(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -
     if let ExprKind::Path(ref qpath) = expr.kind {
         cx.qpath_res(qpath, expr.hir_id)
             .opt_def_id()
-            .map_or(false, |def_id| is_diag_trait_item(cx, def_id, diag_item))
+            .is_some_and(|def_id| is_diag_trait_item(cx, def_id, diag_item))
     } else {
         false
     }
@@ -466,13 +465,13 @@ pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool {
 ///
 /// Please use `is_path_diagnostic_item` if the target is a diagnostic item.
 pub fn is_expr_path_def_path(cx: &LateContext<'_>, expr: &Expr<'_>, segments: &[&str]) -> bool {
-    path_def_id(cx, expr).map_or(false, |id| match_def_path(cx, id, segments))
+    path_def_id(cx, expr).is_some_and(|id| match_def_path(cx, id, segments))
 }
 
 /// If `maybe_path` is a path node which resolves to an item, resolves it to a `DefId` and checks if
 /// it matches the given lang item.
 pub fn is_path_lang_item<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>, lang_item: LangItem) -> bool {
-    path_def_id(cx, maybe_path).map_or(false, |id| cx.tcx.lang_items().get(lang_item) == Some(id))
+    path_def_id(cx, maybe_path).is_some_and(|id| cx.tcx.lang_items().get(lang_item) == Some(id))
 }
 
 /// If `maybe_path` is a path node which resolves to an item, resolves it to a `DefId` and checks if
@@ -482,7 +481,7 @@ pub fn is_path_diagnostic_item<'tcx>(
     maybe_path: &impl MaybePath<'tcx>,
     diag_item: Symbol,
 ) -> bool {
-    path_def_id(cx, maybe_path).map_or(false, |id| cx.tcx.is_diagnostic_item(diag_item, id))
+    path_def_id(cx, maybe_path).is_some_and(|id| cx.tcx.is_diagnostic_item(diag_item, id))
 }
 
 /// THIS METHOD IS DEPRECATED. Matches a `Path` against a slice of segment string literals.
@@ -1315,7 +1314,7 @@ pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec
 pub fn is_entrypoint_fn(cx: &LateContext<'_>, def_id: DefId) -> bool {
     cx.tcx
         .entry_fn(())
-        .map_or(false, |(entry_fn_def_id, _)| def_id == entry_fn_def_id)
+        .is_some_and(|(entry_fn_def_id, _)| def_id == entry_fn_def_id)
 }
 
 /// Returns `true` if the expression is in the program's `#[panic_handler]`.
@@ -1753,8 +1752,8 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
 
     match pat.kind {
         PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable.
-        PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)),
-        PatKind::Box(pat) | PatKind::Deref(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),
+        PatKind::Binding(_, _, _, pat) => pat.is_some_and(|pat| is_refutable(cx, pat)),
+        PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),
         PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
         PatKind::Or(pats) => {
             // TODO: should be the honest check, that pats is exhaustive set
@@ -1778,7 +1777,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
                 },
             }
         },
-        PatKind::Lit(..) | PatKind::Range(..) | PatKind::Err(_) => true,
+        PatKind::Lit(..) | PatKind::Range(..) | PatKind::Err(_) | PatKind::Deref(_) => true,
     }
 }
 
@@ -2021,7 +2020,7 @@ pub fn match_libc_symbol(cx: &LateContext<'_>, did: DefId, name: &str) -> bool {
     let path = cx.get_def_path(did);
     // libc is meant to be used as a flat list of names, but they're all actually defined in different
     // modules based on the target platform. Ignore everything but crate name and the item name.
-    path.first().map_or(false, |s| s.as_str() == "libc") && path.last().map_or(false, |s| s.as_str() == name)
+    path.first().is_some_and(|s| s.as_str() == "libc") && path.last().is_some_and(|s| s.as_str() == name)
 }
 
 /// Returns the list of condition expressions and the list of blocks in a
@@ -2104,7 +2103,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
         _ => None,
     };
 
-    did.map_or(false, |did| cx.tcx.has_attr(did, sym::must_use))
+    did.is_some_and(|did| cx.tcx.has_attr(did, sym::must_use))
 }
 
 /// Checks if a function's body represents the identity function. Looks for bodies of the form:
@@ -2211,7 +2210,7 @@ pub fn is_expr_untyped_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>)
 pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     match expr.kind {
         ExprKind::Closure(&Closure { body, .. }) => is_body_identity_function(cx, cx.tcx.hir().body(body)),
-        _ => path_def_id(cx, expr).map_or(false, |id| cx.tcx.is_diagnostic_item(sym::convert_identity, id)),
+        _ => path_def_id(cx, expr).is_some_and(|id| cx.tcx.is_diagnostic_item(sym::convert_identity, id)),
     }
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/numeric_literal.rs b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
index c5a34160e3d..2c49df9d807 100644
--- a/src/tools/clippy/clippy_utils/src/numeric_literal.rs
+++ b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
@@ -53,7 +53,7 @@ impl<'a> NumericLiteral<'a> {
                 .trim_start()
                 .chars()
                 .next()
-                .map_or(false, |c| c.is_ascii_digit())
+                .is_some_and(|c| c.is_ascii_digit())
         {
             let (unsuffixed, suffix) = split_suffix(src, lit_kind);
             let float = matches!(lit_kind, LitKind::Float(..));
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 666ec8df930..971f8eeb1b3 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -393,12 +393,8 @@ fn is_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool {
 
                 msrv.meets(const_stab_rust_version)
             } else {
-                // Unstable const fn, check if the feature is enabled. We need both the regular stability
-                // feature and (if set) the const stability feature to const-call this function.
-                let stab = tcx.lookup_stability(def_id);
-                let is_enabled = stab.is_some_and(|s| s.is_stable() || tcx.features().enabled(s.feature))
-                    && const_stab.feature.is_none_or(|f| tcx.features().enabled(f));
-                is_enabled && msrv.current().is_none()
+                // Unstable const fn, check if the feature is enabled.
+                tcx.features().enabled(const_stab.feature) && msrv.current().is_none()
             }
         })
 }
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 3255c51d009..25ebe879192 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -905,7 +905,7 @@ impl<'tcx> DerefDelegate<'_, 'tcx> {
             _ => return false,
         };
 
-        ty.map_or(false, |ty| matches!(ty.kind(), ty::Ref(_, inner, _) if inner.is_ref()))
+        ty.is_some_and(|ty| matches!(ty.kind(), ty::Ref(_, inner, _) if inner.is_ref()))
     }
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index ce1a20e0066..770cd9c3786 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -45,7 +45,7 @@ pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
 pub fn has_debug_impl<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
     cx.tcx
         .get_diagnostic_item(sym::Debug)
-        .map_or(false, |debug| implements_trait(cx, ty, debug, &[]))
+        .is_some_and(|debug| implements_trait(cx, ty, debug, &[]))
 }
 
 /// Checks whether a type can be partially moved.
@@ -487,7 +487,7 @@ pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
             .tcx
             .lang_items()
             .drop_trait()
-            .map_or(false, |id| implements_trait(cx, ty, id, &[]))
+            .is_some_and(|id| implements_trait(cx, ty, id, &[]))
         {
             // This type doesn't implement drop, so no side effects here.
             // Check if any component type has any.
@@ -718,7 +718,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
                 {
                     let output = bounds
                         .projection_bounds()
-                        .find(|p| lang_items.fn_once_output().map_or(false, |id| id == p.item_def_id()))
+                        .find(|p| lang_items.fn_once_output().is_some_and(|id| id == p.item_def_id()))
                         .map(|p| p.map_bound(|p| p.term.expect_type()));
                     Some(ExprFnSig::Trait(bound.map_bound(|b| b.args.type_at(0)), output, None))
                 },
@@ -753,7 +753,7 @@ fn sig_from_bounds<'tcx>(
                     && p.self_ty() == ty =>
             {
                 let i = pred.kind().rebind(p.trait_ref.args.type_at(1));
-                if inputs.map_or(false, |inputs| i != inputs) {
+                if inputs.is_some_and(|inputs| i != inputs) {
                     // Multiple different fn trait impls. Is this even allowed?
                     return None;
                 }
@@ -794,7 +794,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option
             {
                 let i = pred.kind().rebind(p.trait_ref.args.type_at(1));
 
-                if inputs.map_or(false, |inputs| inputs != i) {
+                if inputs.is_some_and(|inputs| inputs != i) {
                     // Multiple different fn trait impls. Is this even allowed?
                     return None;
                 }
@@ -1291,7 +1291,7 @@ pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>
 
 /// Checks if the type is `core::mem::ManuallyDrop<_>`
 pub fn is_manually_drop(ty: Ty<'_>) -> bool {
-    ty.ty_adt_def().map_or(false, AdtDef::is_manually_drop)
+    ty.ty_adt_def().is_some_and(AdtDef::is_manually_drop)
 }
 
 /// Returns the deref chain of a type, starting with the type itself.
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 8f5ec185bf1..a79be5ca7d4 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -344,13 +344,13 @@ pub fn is_const_evaluatable<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) ->
                     .cx
                     .qpath_res(p, hir_id)
                     .opt_def_id()
-                    .map_or(false, |id| self.cx.tcx.is_const_fn(id)) => {},
+                    .is_some_and(|id| self.cx.tcx.is_const_fn(id)) => {},
                 ExprKind::MethodCall(..)
                     if self
                         .cx
                         .typeck_results()
                         .type_dependent_def_id(e.hir_id)
-                        .map_or(false, |id| self.cx.tcx.is_const_fn(id)) => {},
+                        .is_some_and(|id| self.cx.tcx.is_const_fn(id)) => {},
                 ExprKind::Binary(_, lhs, rhs)
                     if self.cx.typeck_results().expr_ty(lhs).peel_refs().is_primitive_ty()
                         && self.cx.typeck_results().expr_ty(rhs).peel_refs().is_primitive_ty() => {},
@@ -426,9 +426,7 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool {
                         .cx
                         .typeck_results()
                         .type_dependent_def_id(e.hir_id)
-                        .map_or(false, |id| {
-                            self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe
-                        }) =>
+                        .is_some_and(|id| self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe) =>
                 {
                     ControlFlow::Break(())
                 },
@@ -444,7 +442,7 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool {
                         .cx
                         .qpath_res(p, e.hir_id)
                         .opt_def_id()
-                        .map_or(false, |id| self.cx.tcx.is_mutable_static(id)) =>
+                        .is_some_and(|id| self.cx.tcx.is_mutable_static(id)) =>
                 {
                     ControlFlow::Break(())
                 },
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 37d9cce2465..e32e0cb3604 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,4 +1,4 @@
 [toolchain]
-channel = "nightly-2024-11-07"
+channel = "nightly-2024-11-14"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
 profile = "minimal"
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
index 0a994842834..d3fab60f9e3 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
@@ -1,6 +1,7 @@
 //@aux-build:paths.rs
 #![deny(clippy::internal)]
 #![feature(rustc_private)]
+#![allow(clippy::unnecessary_map_or)]
 
 extern crate clippy_utils;
 extern crate paths;
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
index ba68de6c6d0..1b36f6b09e9 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
@@ -1,6 +1,7 @@
 //@aux-build:paths.rs
 #![deny(clippy::internal)]
 #![feature(rustc_private)]
+#![allow(clippy::unnecessary_map_or)]
 
 extern crate clippy_utils;
 extern crate paths;
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr
index 79da1731613..79521c5037a 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr
@@ -1,5 +1,5 @@
 error: use of a def path to a diagnostic item
-  --> tests/ui-internal/unnecessary_def_path.rs:36:13
+  --> tests/ui-internal/unnecessary_def_path.rs:37:13
    |
 LL |     let _ = match_type(cx, ty, &OPTION);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Option)`
@@ -12,61 +12,61 @@ LL | #![deny(clippy::internal)]
    = note: `#[deny(clippy::unnecessary_def_path)]` implied by `#[deny(clippy::internal)]`
 
 error: use of a def path to a diagnostic item
-  --> tests/ui-internal/unnecessary_def_path.rs:37:13
+  --> tests/ui-internal/unnecessary_def_path.rs:38:13
    |
 LL |     let _ = match_type(cx, ty, RESULT);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)`
 
 error: use of a def path to a diagnostic item
-  --> tests/ui-internal/unnecessary_def_path.rs:38:13
+  --> tests/ui-internal/unnecessary_def_path.rs:39:13
    |
 LL |     let _ = match_type(cx, ty, &["core", "result", "Result"]);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)`
 
 error: use of a def path to a diagnostic item
-  --> tests/ui-internal/unnecessary_def_path.rs:42:13
+  --> tests/ui-internal/unnecessary_def_path.rs:43:13
    |
 LL |     let _ = clippy_utils::ty::match_type(cx, ty, rc_path);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Rc)`
 
 error: use of a def path to a diagnostic item
-  --> tests/ui-internal/unnecessary_def_path.rs:44:13
+  --> tests/ui-internal/unnecessary_def_path.rs:45:13
    |
 LL |     let _ = match_type(cx, ty, &paths::OPTION);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Option)`
 
 error: use of a def path to a diagnostic item
-  --> tests/ui-internal/unnecessary_def_path.rs:45:13
+  --> tests/ui-internal/unnecessary_def_path.rs:46:13
    |
 LL |     let _ = match_type(cx, ty, paths::RESULT);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)`
 
 error: use of a def path to a `LangItem`
-  --> tests/ui-internal/unnecessary_def_path.rs:47:13
+  --> tests/ui-internal/unnecessary_def_path.rs:48:13
    |
 LL |     let _ = match_type(cx, ty, &["alloc", "boxed", "Box"]);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_lang_item(cx, ty, LangItem::OwnedBox)`
 
 error: use of a def path to a diagnostic item
-  --> tests/ui-internal/unnecessary_def_path.rs:48:13
+  --> tests/ui-internal/unnecessary_def_path.rs:49:13
    |
 LL |     let _ = match_type(cx, ty, &["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::maybe_uninit_uninit)`
 
 error: use of a def path to a `LangItem`
-  --> tests/ui-internal/unnecessary_def_path.rs:50:13
+  --> tests/ui-internal/unnecessary_def_path.rs:51:13
    |
 LL |     let _ = match_def_path(cx, did, &["alloc", "boxed", "Box"]);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OwnedBox) == Some(did)`
 
 error: use of a def path to a diagnostic item
-  --> tests/ui-internal/unnecessary_def_path.rs:51:13
+  --> tests/ui-internal/unnecessary_def_path.rs:52:13
    |
 LL |     let _ = match_def_path(cx, did, &["core", "option", "Option"]);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.is_diagnostic_item(sym::Option, did)`
 
 error: use of a def path to a `LangItem`
-  --> tests/ui-internal/unnecessary_def_path.rs:52:13
+  --> tests/ui-internal/unnecessary_def_path.rs:53:13
    |
 LL |     let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OptionSome) == Some(did)`
@@ -74,25 +74,25 @@ LL |     let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]);
    = help: if this `DefId` came from a constructor expression or pattern then the parent `DefId` should be used instead
 
 error: use of a def path to a diagnostic item
-  --> tests/ui-internal/unnecessary_def_path.rs:54:13
+  --> tests/ui-internal/unnecessary_def_path.rs:55:13
    |
 LL |     let _ = match_trait_method(cx, expr, &["core", "convert", "AsRef"]);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_trait_method(cx, expr, sym::AsRef)`
 
 error: use of a def path to a diagnostic item
-  --> tests/ui-internal/unnecessary_def_path.rs:56:13
+  --> tests/ui-internal/unnecessary_def_path.rs:57:13
    |
 LL |     let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option"]);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_path_diagnostic_item(cx, expr, sym::Option)`
 
 error: use of a def path to a `LangItem`
-  --> tests/ui-internal/unnecessary_def_path.rs:57:13
+  --> tests/ui-internal/unnecessary_def_path.rs:58:13
    |
 LL |     let _ = is_expr_path_def_path(cx, expr, &["core", "iter", "traits", "Iterator", "next"]);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().get(LangItem::IteratorNext) == Some(id))`
 
 error: use of a def path to a `LangItem`
-  --> tests/ui-internal/unnecessary_def_path.rs:58:13
+  --> tests/ui-internal/unnecessary_def_path.rs:59:13
    |
 LL |     let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option", "Some"]);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_res_lang_ctor(cx, path_res(cx, expr), LangItem::OptionSome)`
diff --git a/src/tools/clippy/tests/ui-toml/large_include_file/empty.txt b/src/tools/clippy/tests/ui-toml/large_include_file/empty.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/large_include_file/empty.txt
diff --git a/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.rs b/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.rs
index dc9349f75a0..8a6dd36501c 100644
--- a/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.rs
+++ b/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.rs
@@ -15,5 +15,9 @@ const TOO_BIG_INCLUDE_BYTES: &[u8; 654] = include_bytes!("too_big.txt");
 const TOO_BIG_INCLUDE_STR: &str = include_str!("too_big.txt");
 //~^ large_include_file
 
-#[doc = include_str!("too_big.txt")] //~ large_include_file
+#[doc = include_str!("too_big.txt")]
+//~^ large_include_file
+// Should not lint!
+// Regression test for <https://github.com/rust-lang/rust-clippy/issues/13670>.
+#[doc = include_str!("empty.txt")]
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
index 8b4a165a97c..c4d77f24f12 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
@@ -1,4 +1,5 @@
 #![warn(clippy::case_sensitive_file_extension_comparisons)]
+#![allow(clippy::unnecessary_map_or)]
 
 use std::string::String;
 
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
index e4b8178110b..690e93c2639 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::case_sensitive_file_extension_comparisons)]
+#![allow(clippy::unnecessary_map_or)]
 
 use std::string::String;
 
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
index d203f91b832..e21815f251b 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
@@ -1,5 +1,5 @@
 error: case-sensitive file extension comparison
-  --> tests/ui/case_sensitive_file_extension_comparisons.rs:13:5
+  --> tests/ui/case_sensitive_file_extension_comparisons.rs:14:5
    |
 LL |     filename.ends_with(".rs")
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -15,7 +15,7 @@ LL +         .map_or(false, |ext| ext.eq_ignore_ascii_case("rs"))
    |
 
 error: case-sensitive file extension comparison
-  --> tests/ui/case_sensitive_file_extension_comparisons.rs:18:13
+  --> tests/ui/case_sensitive_file_extension_comparisons.rs:19:13
    |
 LL |     let _ = String::new().ends_with(".ext12");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -29,7 +29,7 @@ LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
    |
 
 error: case-sensitive file extension comparison
-  --> tests/ui/case_sensitive_file_extension_comparisons.rs:19:13
+  --> tests/ui/case_sensitive_file_extension_comparisons.rs:20:13
    |
 LL |     let _ = "str".ends_with(".ext12");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -43,7 +43,7 @@ LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
    |
 
 error: case-sensitive file extension comparison
-  --> tests/ui/case_sensitive_file_extension_comparisons.rs:23:17
+  --> tests/ui/case_sensitive_file_extension_comparisons.rs:24:17
    |
 LL |         let _ = "str".ends_with(".ext12");
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -57,7 +57,7 @@ LL ~             .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
    |
 
 error: case-sensitive file extension comparison
-  --> tests/ui/case_sensitive_file_extension_comparisons.rs:30:13
+  --> tests/ui/case_sensitive_file_extension_comparisons.rs:31:13
    |
 LL |     let _ = String::new().ends_with(".EXT12");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,7 +71,7 @@ LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
    |
 
 error: case-sensitive file extension comparison
-  --> tests/ui/case_sensitive_file_extension_comparisons.rs:31:13
+  --> tests/ui/case_sensitive_file_extension_comparisons.rs:32:13
    |
 LL |     let _ = "str".ends_with(".EXT12");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr
index c238b4c9a17..2852e26680f 100644
--- a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr
+++ b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr
@@ -3,7 +3,7 @@ error: empty line after doc comment
    |
 LL | / /// for the crate
 LL | |
-   | |_
+   | |_^
 LL |   fn first_in_crate() {}
    |   ------------------- the comment documents this function
    |
@@ -22,7 +22,7 @@ error: empty line after doc comment
    |
 LL | /     /// for the module
 LL | |
-   | |_
+   | |_^
 LL |       fn first_in_module() {}
    |       -------------------- the comment documents this function
    |
@@ -39,7 +39,7 @@ error: empty line after doc comment
    |
 LL | /     /// # Indented
 LL | |
-   | |_
+   | |_^
 LL |       /// Blank line
 LL |       fn indented() {}
    |       ------------- the comment documents this function
@@ -55,7 +55,7 @@ error: empty line after doc comment
    |
 LL | / /// This should produce a warning
 LL | |
-   | |_
+   | |_^
 LL |   fn with_doc_and_newline() {}
    |   ------------------------- the comment documents this function
    |
@@ -69,7 +69,7 @@ LL | |
 LL | | /** This is also a doc comment and is part of the warning
 LL | |  */
 LL | |
-   | |_
+   | |_^
 ...
 LL |   fn three_attributes() {}
    |   --------------------- the comment documents this function
@@ -82,7 +82,7 @@ error: empty line after doc comment
 LL | /     /// docs for `old_code`
 LL | |     // fn old_code() {}
 LL | |
-   | |_
+   | |_^
 LL |       fn new_code() {}
    |       ------------- the comment documents this function
    |
@@ -102,7 +102,7 @@ LL | |     /// Docs
 LL | |     /// for OldB
 LL | |     // struct OldB;
 LL | |
-   | |_
+   | |_^
 ...
 LL |       struct Multiple;
    |       --------------- the comment documents this struct
@@ -125,7 +125,7 @@ LL | /     /**
 LL | |      * Meant to be inner doc comment
 LL | |      */
 LL | |
-   | |_
+   | |_^
 LL |       fn first_in_module() {}
    |       -------------------- the comment documents this function
    |
@@ -143,7 +143,7 @@ LL | |      * Docs for `old_code`
 LL | |      */
 LL | |     /* fn old_code() {} */
 LL | |
-   | |_
+   | |_^
 ...
 LL |       fn new_code() {}
    |       ------------- the comment documents this function
@@ -161,7 +161,7 @@ error: empty line after doc comment
 LL | /     /// Docs for `old_code2`
 LL | |     /* fn old_code2() {} */
 LL | |
-   | |_
+   | |_^
 LL |       /// Docs for `new_code2`
 LL |       fn new_code2() {}
    |       -------------- the comment documents this function
diff --git a/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr b/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr
index 958b40424a9..75fc23e9e7e 100644
--- a/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr
+++ b/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr
@@ -3,7 +3,7 @@ error: empty line after outer attribute
    |
 LL | / #[crate_type = "lib"]
 LL | |
-   | |_
+   | |_^
 LL |   fn first_in_crate() {}
    |   ------------------- the attribute applies to this function
    |
@@ -20,7 +20,7 @@ error: empty line after outer attribute
    |
 LL | / #[inline]
 LL | |
-   | |_
+   | |_^
 LL |   /// some comment
 LL |   fn with_one_newline_and_comment() {}
    |   --------------------------------- the attribute applies to this function
@@ -32,7 +32,7 @@ error: empty line after outer attribute
    |
 LL | / #[inline]
 LL | |
-   | |_
+   | |_^
 LL |   fn with_one_newline() {}
    |   --------------------- the attribute applies to this function
    |
@@ -44,7 +44,7 @@ error: empty lines after outer attribute
 LL | /     #[crate_type = "lib"]
 LL | |
 LL | |
-   | |_
+   | |_^
 LL |       fn with_two_newlines() {}
    |       ---------------------- the attribute applies to this function
    |
@@ -59,7 +59,7 @@ error: empty line after outer attribute
    |
 LL | / #[doc = "doc attributes should be considered attributes"]
 LL | |
-   | |_
+   | |_^
 LL |   enum Baz {
    |   -------- the attribute applies to this enum
    |
@@ -70,7 +70,7 @@ error: empty line after outer attribute
    |
 LL | / #[repr(C)]
 LL | |
-   | |_
+   | |_^
 LL |   struct Foo {
    |   ---------- the attribute applies to this struct
    |
@@ -81,7 +81,7 @@ error: empty line after outer attribute
    |
 LL | / #[allow(dead_code)]
 LL | |
-   | |_
+   | |_^
 LL |   mod foo {}
    |   ------- the attribute applies to this module
    |
@@ -93,7 +93,7 @@ error: empty line after outer attribute
 LL | / #[inline]
 LL | | // Still lint cases where the empty line does not immediately follow the attribute
 LL | |
-   | |_
+   | |_^
 LL |   fn comment_before_empty_line() {}
    |   ------------------------------ the attribute applies to this function
    |
@@ -106,7 +106,7 @@ LL | / #[allow(unused)]
 LL | |
 LL | | // This comment is isolated
 LL | |
-   | |_
+   | |_^
 LL |   pub fn isolated_comment() {}
    |   ------------------------- the attribute applies to this function
    |
diff --git a/src/tools/clippy/tests/ui/four_forward_slashes.stderr b/src/tools/clippy/tests/ui/four_forward_slashes.stderr
index a2218ea4d10..3606a2227a0 100644
--- a/src/tools/clippy/tests/ui/four_forward_slashes.stderr
+++ b/src/tools/clippy/tests/ui/four_forward_slashes.stderr
@@ -3,7 +3,7 @@ error: this item has comments with 4 forward slashes (`////`). These look like d
    |
 LL | / //// whoops
 LL | | fn a() {}
-   | |_
+   | |_^
    |
    = note: `-D clippy::four-forward-slashes` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::four_forward_slashes)]`
@@ -18,7 +18,7 @@ error: this item has comments with 4 forward slashes (`////`). These look like d
 LL | / //// whoops
 LL | | #[allow(dead_code)]
 LL | | fn b() {}
-   | |_
+   | |_^
    |
 help: make this a doc comment by removing one `/`
    |
@@ -32,7 +32,7 @@ LL | / //// whoops
 LL | | //// two borked comments!
 LL | | #[track_caller]
 LL | | fn c() {}
-   | |_
+   | |_^
    |
 help: turn these into doc comments by removing one `/`
    |
@@ -46,7 +46,7 @@ error: this item has comments with 4 forward slashes (`////`). These look like d
 LL | / //// between attributes
 LL | | #[allow(dead_code)]
 LL | | fn g() {}
-   | |_
+   | |_^
    |
 help: make this a doc comment by removing one `/`
    |
@@ -58,7 +58,7 @@ error: this item has comments with 4 forward slashes (`////`). These look like d
    |
 LL | /     //// not very start of contents
 LL | | fn h() {}
-   | |_
+   | |_^
    |
 help: make this a doc comment by removing one `/`
    |
diff --git a/src/tools/clippy/tests/ui/four_forward_slashes_first_line.stderr b/src/tools/clippy/tests/ui/four_forward_slashes_first_line.stderr
index 23937034b7e..81732346412 100644
--- a/src/tools/clippy/tests/ui/four_forward_slashes_first_line.stderr
+++ b/src/tools/clippy/tests/ui/four_forward_slashes_first_line.stderr
@@ -3,7 +3,7 @@ error: this item has comments with 4 forward slashes (`////`). These look like d
    |
 LL | / //// borked doc comment on the first line. doesn't combust!
 LL | | fn a() {}
-   | |_
+   | |_^
    |
    = note: `-D clippy::four-forward-slashes` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::four_forward_slashes)]`
diff --git a/src/tools/clippy/tests/ui/identity_op.fixed b/src/tools/clippy/tests/ui/identity_op.fixed
index b18d8560f6f..2e8e2366de6 100644
--- a/src/tools/clippy/tests/ui/identity_op.fixed
+++ b/src/tools/clippy/tests/ui/identity_op.fixed
@@ -116,7 +116,7 @@ fn main() {
     //~^ ERROR: this operation has no effect
     (match a { 0 => 10, _ => 20 }) + if b { 3 } else { 4 };
     //~^ ERROR: this operation has no effect
-    (if b { 1 } else { 2 });
+    ((if b { 1 } else { 2 }));
     //~^ ERROR: this operation has no effect
 
     ({ a }) + 3;
@@ -212,3 +212,47 @@ fn issue_12050() {
         //~^ ERROR: this operation has no effect
     }
 }
+
+fn issue_13470() {
+    let x = 1i32;
+    let y = 1i32;
+    // Removes the + 0i32 while keeping the parentheses around x + y so the cast operation works
+    let _: u64 = (x + y) as u64;
+    //~^ ERROR: this operation has no effect
+    // both of the next two lines should look the same after rustfix
+    let _: u64 = 1u64 & (x + y) as u64;
+    //~^ ERROR: this operation has no effect
+    // Same as above, but with extra redundant parenthesis
+    let _: u64 = 1u64 & ((x + y)) as u64;
+    //~^ ERROR: this operation has no effect
+    // Should maintain parenthesis even if the surrounding expr has the same precedence
+    let _: u64 = 5u64 + ((x + y)) as u64;
+    //~^ ERROR: this operation has no effect
+
+    // If we don't maintain the parens here, the behavior changes
+    let _ = -(x + y);
+    //~^ ERROR: this operation has no effect
+    // Similarly, we need to maintain parens here
+    let _ = -(x / y);
+    //~^ ERROR: this operation has no effect
+    // Maintain parenthesis if the parent expr is of higher precedence
+    let _ = 2i32 * (x + y);
+    //~^ ERROR: this operation has no effect
+    // Maintain parenthesis if the parent expr is the same precedence
+    // as not all operations are associative
+    let _ = 2i32 - (x - y);
+    //~^ ERROR: this operation has no effect
+    // But make sure that inner parens still exist
+    let z = 1i32;
+    let _ = 2 + (x + (y * z));
+    //~^ ERROR: this operation has no effect
+    // Maintain parenthesis if the parent expr is of lower precedence
+    // This is for clarity, and clippy will not warn on these being unnecessary
+    let _ = 2i32 + (x * y);
+    //~^ ERROR: this operation has no effect
+
+    let x = 1i16;
+    let y = 1i16;
+    let _: u64 = 1u64 + ((x as i32 + y as i32) as u64);
+    //~^ ERROR: this operation has no effect
+}
diff --git a/src/tools/clippy/tests/ui/identity_op.rs b/src/tools/clippy/tests/ui/identity_op.rs
index f1f01b42447..3e20fa6f2b8 100644
--- a/src/tools/clippy/tests/ui/identity_op.rs
+++ b/src/tools/clippy/tests/ui/identity_op.rs
@@ -212,3 +212,47 @@ fn issue_12050() {
         //~^ ERROR: this operation has no effect
     }
 }
+
+fn issue_13470() {
+    let x = 1i32;
+    let y = 1i32;
+    // Removes the + 0i32 while keeping the parentheses around x + y so the cast operation works
+    let _: u64 = (x + y + 0i32) as u64;
+    //~^ ERROR: this operation has no effect
+    // both of the next two lines should look the same after rustfix
+    let _: u64 = 1u64 & (x + y + 0i32) as u64;
+    //~^ ERROR: this operation has no effect
+    // Same as above, but with extra redundant parenthesis
+    let _: u64 = 1u64 & ((x + y) + 0i32) as u64;
+    //~^ ERROR: this operation has no effect
+    // Should maintain parenthesis even if the surrounding expr has the same precedence
+    let _: u64 = 5u64 + ((x + y) + 0i32) as u64;
+    //~^ ERROR: this operation has no effect
+
+    // If we don't maintain the parens here, the behavior changes
+    let _ = -(x + y + 0i32);
+    //~^ ERROR: this operation has no effect
+    // Similarly, we need to maintain parens here
+    let _ = -(x / y / 1i32);
+    //~^ ERROR: this operation has no effect
+    // Maintain parenthesis if the parent expr is of higher precedence
+    let _ = 2i32 * (x + y + 0i32);
+    //~^ ERROR: this operation has no effect
+    // Maintain parenthesis if the parent expr is the same precedence
+    // as not all operations are associative
+    let _ = 2i32 - (x - y - 0i32);
+    //~^ ERROR: this operation has no effect
+    // But make sure that inner parens still exist
+    let z = 1i32;
+    let _ = 2 + (x + (y * z) + 0);
+    //~^ ERROR: this operation has no effect
+    // Maintain parenthesis if the parent expr is of lower precedence
+    // This is for clarity, and clippy will not warn on these being unnecessary
+    let _ = 2i32 + (x * y * 1i32);
+    //~^ ERROR: this operation has no effect
+
+    let x = 1i16;
+    let y = 1i16;
+    let _: u64 = 1u64 + ((x as i32 + y as i32) as u64 + 0u64);
+    //~^ ERROR: this operation has no effect
+}
diff --git a/src/tools/clippy/tests/ui/identity_op.stderr b/src/tools/clippy/tests/ui/identity_op.stderr
index 9fff86b86f9..99a58ef2c1b 100644
--- a/src/tools/clippy/tests/ui/identity_op.stderr
+++ b/src/tools/clippy/tests/ui/identity_op.stderr
@@ -149,7 +149,7 @@ error: this operation has no effect
   --> tests/ui/identity_op.rs:119:5
    |
 LL |     (if b { 1 } else { 2 }) + 0;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `((if b { 1 } else { 2 }))`
 
 error: this operation has no effect
   --> tests/ui/identity_op.rs:122:5
@@ -313,5 +313,71 @@ error: this operation has no effect
 LL |         let _: i32 = **&&*&x + 0;
    |                      ^^^^^^^^^^^ help: consider reducing it to: `***&&*&x`
 
-error: aborting due to 52 previous errors
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:220:18
+   |
+LL |     let _: u64 = (x + y + 0i32) as u64;
+   |                  ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:223:25
+   |
+LL |     let _: u64 = 1u64 & (x + y + 0i32) as u64;
+   |                         ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:226:25
+   |
+LL |     let _: u64 = 1u64 & ((x + y) + 0i32) as u64;
+   |                         ^^^^^^^^^^^^^^^^ help: consider reducing it to: `((x + y))`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:229:25
+   |
+LL |     let _: u64 = 5u64 + ((x + y) + 0i32) as u64;
+   |                         ^^^^^^^^^^^^^^^^ help: consider reducing it to: `((x + y))`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:233:14
+   |
+LL |     let _ = -(x + y + 0i32);
+   |              ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:236:14
+   |
+LL |     let _ = -(x / y / 1i32);
+   |              ^^^^^^^^^^^^^^ help: consider reducing it to: `(x / y)`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:239:20
+   |
+LL |     let _ = 2i32 * (x + y + 0i32);
+   |                    ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:243:20
+   |
+LL |     let _ = 2i32 - (x - y - 0i32);
+   |                    ^^^^^^^^^^^^^^ help: consider reducing it to: `(x - y)`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:247:17
+   |
+LL |     let _ = 2 + (x + (y * z) + 0);
+   |                 ^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(x + (y * z))`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:251:20
+   |
+LL |     let _ = 2i32 + (x * y * 1i32);
+   |                    ^^^^^^^^^^^^^^ help: consider reducing it to: `(x * y)`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:256:25
+   |
+LL |     let _: u64 = 1u64 + ((x as i32 + y as i32) as u64 + 0u64);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `((x as i32 + y as i32) as u64)`
+
+error: aborting due to 63 previous errors
 
diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed
index 679388372e6..b6e148e9f77 100644
--- a/src/tools/clippy/tests/ui/question_mark.fixed
+++ b/src/tools/clippy/tests/ui/question_mark.fixed
@@ -96,12 +96,42 @@ impl MoveStruct {
 }
 
 fn func() -> Option<i32> {
+    macro_rules! opt_none {
+        () => {
+            None
+        };
+    }
+
     fn f() -> Option<String> {
         Some(String::new())
     }
 
     f()?;
 
+    let _val = f()?;
+
+    let s: &str = match &Some(String::new()) {
+        Some(v) => v,
+        None => return None,
+    };
+
+    f()?;
+
+    opt_none!()?;
+
+    match f() {
+        Some(x) => x,
+        None => return opt_none!(),
+    };
+
+    match f() {
+        Some(val) => {
+            println!("{val}");
+            val
+        },
+        None => return None,
+    };
+
     Some(0)
 }
 
@@ -114,6 +144,10 @@ fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
 
     x?;
 
+    let _val = func_returning_result()?;
+
+    func_returning_result()?;
+
     // No warning
     let y = if let Ok(x) = x {
         x
@@ -157,6 +191,28 @@ fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
     Ok(y)
 }
 
+fn infer_check() {
+    let closure = |x: Result<u8, ()>| {
+        // `?` would fail here, as it expands to `Err(val.into())` which is not constrained.
+        let _val = match x {
+            Ok(val) => val,
+            Err(val) => return Err(val),
+        };
+
+        Ok(())
+    };
+
+    let closure = |x: Result<u8, ()>| -> Result<(), _> {
+        // `?` would fail here, as it expands to `Err(val.into())` which is not constrained.
+        let _val = match x {
+            Ok(val) => val,
+            Err(val) => return Err(val),
+        };
+
+        Ok(())
+    };
+}
+
 // see issue #8019
 pub enum NotOption {
     None,
diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs
index 601ab78bf5a..48dc9eb0a62 100644
--- a/src/tools/clippy/tests/ui/question_mark.rs
+++ b/src/tools/clippy/tests/ui/question_mark.rs
@@ -124,6 +124,12 @@ impl MoveStruct {
 }
 
 fn func() -> Option<i32> {
+    macro_rules! opt_none {
+        () => {
+            None
+        };
+    }
+
     fn f() -> Option<String> {
         Some(String::new())
     }
@@ -132,6 +138,39 @@ fn func() -> Option<i32> {
         return None;
     }
 
+    let _val = match f() {
+        Some(val) => val,
+        None => return None,
+    };
+
+    let s: &str = match &Some(String::new()) {
+        Some(v) => v,
+        None => return None,
+    };
+
+    match f() {
+        Some(val) => val,
+        None => return None,
+    };
+
+    match opt_none!() {
+        Some(x) => x,
+        None => return None,
+    };
+
+    match f() {
+        Some(x) => x,
+        None => return opt_none!(),
+    };
+
+    match f() {
+        Some(val) => {
+            println!("{val}");
+            val
+        },
+        None => return None,
+    };
+
     Some(0)
 }
 
@@ -146,6 +185,16 @@ fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
         return x;
     }
 
+    let _val = match func_returning_result() {
+        Ok(val) => val,
+        Err(err) => return Err(err),
+    };
+
+    match func_returning_result() {
+        Ok(val) => val,
+        Err(err) => return Err(err),
+    };
+
     // No warning
     let y = if let Ok(x) = x {
         x
@@ -189,6 +238,28 @@ fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
     Ok(y)
 }
 
+fn infer_check() {
+    let closure = |x: Result<u8, ()>| {
+        // `?` would fail here, as it expands to `Err(val.into())` which is not constrained.
+        let _val = match x {
+            Ok(val) => val,
+            Err(val) => return Err(val),
+        };
+
+        Ok(())
+    };
+
+    let closure = |x: Result<u8, ()>| -> Result<(), _> {
+        // `?` would fail here, as it expands to `Err(val.into())` which is not constrained.
+        let _val = match x {
+            Ok(val) => val,
+            Err(val) => return Err(val),
+        };
+
+        Ok(())
+    };
+}
+
 // see issue #8019
 pub enum NotOption {
     None,
diff --git a/src/tools/clippy/tests/ui/question_mark.stderr b/src/tools/clippy/tests/ui/question_mark.stderr
index 5f26a7ea2c3..0a48c4e80cb 100644
--- a/src/tools/clippy/tests/ui/question_mark.stderr
+++ b/src/tools/clippy/tests/ui/question_mark.stderr
@@ -94,29 +94,76 @@ LL | |         };
    | |_________^ help: replace it with: `self.opt?`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:131:5
+  --> tests/ui/question_mark.rs:137:5
    |
 LL | /     if f().is_none() {
 LL | |         return None;
 LL | |     }
    | |_____^ help: replace it with: `f()?;`
 
+error: this `match` expression can be replaced with `?`
+  --> tests/ui/question_mark.rs:141:16
+   |
+LL |       let _val = match f() {
+   |  ________________^
+LL | |         Some(val) => val,
+LL | |         None => return None,
+LL | |     };
+   | |_____^ help: try instead: `f()?`
+
+error: this `match` expression can be replaced with `?`
+  --> tests/ui/question_mark.rs:151:5
+   |
+LL | /     match f() {
+LL | |         Some(val) => val,
+LL | |         None => return None,
+LL | |     };
+   | |_____^ help: try instead: `f()?`
+
+error: this `match` expression can be replaced with `?`
+  --> tests/ui/question_mark.rs:156:5
+   |
+LL | /     match opt_none!() {
+LL | |         Some(x) => x,
+LL | |         None => return None,
+LL | |     };
+   | |_____^ help: try instead: `opt_none!()?`
+
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:143:13
+  --> tests/ui/question_mark.rs:182:13
    |
 LL |     let _ = if let Ok(x) = x { x } else { return x };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x?`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:145:5
+  --> tests/ui/question_mark.rs:184:5
    |
 LL | /     if x.is_err() {
 LL | |         return x;
 LL | |     }
    | |_____^ help: replace it with: `x?;`
 
+error: this `match` expression can be replaced with `?`
+  --> tests/ui/question_mark.rs:188:16
+   |
+LL |       let _val = match func_returning_result() {
+   |  ________________^
+LL | |         Ok(val) => val,
+LL | |         Err(err) => return Err(err),
+LL | |     };
+   | |_____^ help: try instead: `func_returning_result()?`
+
+error: this `match` expression can be replaced with `?`
+  --> tests/ui/question_mark.rs:193:5
+   |
+LL | /     match func_returning_result() {
+LL | |         Ok(val) => val,
+LL | |         Err(err) => return Err(err),
+LL | |     };
+   | |_____^ help: try instead: `func_returning_result()?`
+
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:213:5
+  --> tests/ui/question_mark.rs:284:5
    |
 LL | /     if let Err(err) = func_returning_result() {
 LL | |         return Err(err);
@@ -124,7 +171,7 @@ LL | |     }
    | |_____^ help: replace it with: `func_returning_result()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:220:5
+  --> tests/ui/question_mark.rs:291:5
    |
 LL | /     if let Err(err) = func_returning_result() {
 LL | |         return Err(err);
@@ -132,7 +179,7 @@ LL | |     }
    | |_____^ help: replace it with: `func_returning_result()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:297:13
+  --> tests/ui/question_mark.rs:368:13
    |
 LL | /             if a.is_none() {
 LL | |                 return None;
@@ -142,12 +189,12 @@ LL | |             }
    | |_____________^ help: replace it with: `a?;`
 
 error: this `let...else` may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:357:5
+  --> tests/ui/question_mark.rs:428:5
    |
 LL | /     let Some(v) = bar.foo.owned.clone() else {
 LL | |         return None;
 LL | |     };
    | |______^ help: replace it with: `let v = bar.foo.owned.clone()?;`
 
-error: aborting due to 17 previous errors
+error: aborting due to 22 previous errors
 
diff --git a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.stderr b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.stderr
index 6403265a39c..6ef333f0cfd 100644
--- a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.stderr
+++ b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.stderr
@@ -6,7 +6,7 @@ LL | | /// A much longer explanation that goes into a lot more detail about
 LL | | /// how the thing works, possibly with doclinks and so one,
 LL | | /// and probably spanning a many rows. Blablabla, it needs to be over
 LL | | /// 200 characters so I needed to write something longeeeeeeer.
-   | |_
+   | |_^
    |
    = note: `-D clippy::too-long-first-doc-paragraph` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::too_long_first_doc_paragraph)]`
diff --git a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr
index 39926647f54..95f42349b9b 100644
--- a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr
+++ b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr
@@ -23,7 +23,7 @@ error: first doc comment paragraph is too long
 LL | / /// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia
 LL | | /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero,
 LL | | /// gravida non lacinia at, rhoncus eu lacus.
-   | |_
+   | |_^
 
 error: first doc comment paragraph is too long
   --> tests/ui/too_long_first_doc_paragraph.rs:36:1
@@ -32,7 +32,7 @@ LL | / /// Lorem
 LL | | /// ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia
 LL | | /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero,
 LL | | /// gravida non lacinia at, rhoncus eu lacus.
-   | |_
+   | |_^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.fixed b/src/tools/clippy/tests/ui/unnecessary_map_or.fixed
new file mode 100644
index 00000000000..2d932a70e9d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_map_or.fixed
@@ -0,0 +1,64 @@
+//@aux-build:proc_macros.rs
+#![warn(clippy::unnecessary_map_or)]
+#![allow(clippy::no_effect)]
+#![allow(clippy::eq_op)]
+#![allow(clippy::unnecessary_lazy_evaluations)]
+#[clippy::msrv = "1.70.0"]
+#[macro_use]
+extern crate proc_macros;
+
+fn main() {
+    // should trigger
+    let _ = (Some(5) == Some(5));
+    let _ = (Some(5) != Some(5));
+    let _ = (Some(5) == Some(5));
+    let _ = Some(5).is_some_and(|n| {
+        let _ = n;
+        6 >= 5
+    });
+    let _ = Some(vec![5]).is_some_and(|n| n == [5]);
+    let _ = Some(vec![1]).is_some_and(|n| vec![2] == n);
+    let _ = Some(5).is_some_and(|n| n == n);
+    let _ = Some(5).is_some_and(|n| n == if 2 > 1 { n } else { 0 });
+    let _ = Ok::<Vec<i32>, i32>(vec![5]).is_ok_and(|n| n == [5]);
+    let _ = (Ok::<i32, i32>(5) == Ok(5));
+    let _ = (Some(5) == Some(5)).then(|| 1);
+
+    // shouldnt trigger
+    let _ = Some(5).map_or(true, |n| n == 5);
+    let _ = Some(5).map_or(true, |n| 5 == n);
+    macro_rules! x {
+        () => {
+            Some(1)
+        };
+    }
+    // methods lints dont fire on macros
+    let _ = x!().map_or(false, |n| n == 1);
+    let _ = x!().map_or(false, |n| n == vec![1][0]);
+
+    msrv_1_69();
+
+    external! {
+        let _ = Some(5).map_or(false, |n| n == 5);
+    }
+
+    with_span! {
+        let _ = Some(5).map_or(false, |n| n == 5);
+    }
+
+    // check for presence of PartialEq, and alter suggestion to use `is_ok_and` if absent
+    struct S;
+    let r: Result<i32, S> = Ok(3);
+    let _ = r.is_ok_and(|x| x == 7);
+
+    #[derive(PartialEq)]
+    struct S2;
+    let r: Result<i32, S2> = Ok(4);
+    let _ = (r == Ok(8));
+}
+
+#[clippy::msrv = "1.69.0"]
+fn msrv_1_69() {
+    // is_some_and added in 1.70.0
+    let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 });
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.rs b/src/tools/clippy/tests/ui/unnecessary_map_or.rs
new file mode 100644
index 00000000000..4a9d69be1e9
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_map_or.rs
@@ -0,0 +1,67 @@
+//@aux-build:proc_macros.rs
+#![warn(clippy::unnecessary_map_or)]
+#![allow(clippy::no_effect)]
+#![allow(clippy::eq_op)]
+#![allow(clippy::unnecessary_lazy_evaluations)]
+#[clippy::msrv = "1.70.0"]
+#[macro_use]
+extern crate proc_macros;
+
+fn main() {
+    // should trigger
+    let _ = Some(5).map_or(false, |n| n == 5);
+    let _ = Some(5).map_or(true, |n| n != 5);
+    let _ = Some(5).map_or(false, |n| {
+        let _ = 1;
+        n == 5
+    });
+    let _ = Some(5).map_or(false, |n| {
+        let _ = n;
+        6 >= 5
+    });
+    let _ = Some(vec![5]).map_or(false, |n| n == [5]);
+    let _ = Some(vec![1]).map_or(false, |n| vec![2] == n);
+    let _ = Some(5).map_or(false, |n| n == n);
+    let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 });
+    let _ = Ok::<Vec<i32>, i32>(vec![5]).map_or(false, |n| n == [5]);
+    let _ = Ok::<i32, i32>(5).map_or(false, |n| n == 5);
+    let _ = Some(5).map_or(false, |n| n == 5).then(|| 1);
+
+    // shouldnt trigger
+    let _ = Some(5).map_or(true, |n| n == 5);
+    let _ = Some(5).map_or(true, |n| 5 == n);
+    macro_rules! x {
+        () => {
+            Some(1)
+        };
+    }
+    // methods lints dont fire on macros
+    let _ = x!().map_or(false, |n| n == 1);
+    let _ = x!().map_or(false, |n| n == vec![1][0]);
+
+    msrv_1_69();
+
+    external! {
+        let _ = Some(5).map_or(false, |n| n == 5);
+    }
+
+    with_span! {
+        let _ = Some(5).map_or(false, |n| n == 5);
+    }
+
+    // check for presence of PartialEq, and alter suggestion to use `is_ok_and` if absent
+    struct S;
+    let r: Result<i32, S> = Ok(3);
+    let _ = r.map_or(false, |x| x == 7);
+
+    #[derive(PartialEq)]
+    struct S2;
+    let r: Result<i32, S2> = Ok(4);
+    let _ = r.map_or(false, |x| x == 8);
+}
+
+#[clippy::msrv = "1.69.0"]
+fn msrv_1_69() {
+    // is_some_and added in 1.70.0
+    let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 });
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.stderr b/src/tools/clippy/tests/ui/unnecessary_map_or.stderr
new file mode 100644
index 00000000000..299a4e5da7a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_map_or.stderr
@@ -0,0 +1,99 @@
+error: this `map_or` is redundant
+  --> tests/ui/unnecessary_map_or.rs:12:13
+   |
+LL |     let _ = Some(5).map_or(false, |n| n == 5);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) == Some(5))`
+   |
+   = note: `-D clippy::unnecessary-map-or` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::unnecessary_map_or)]`
+
+error: this `map_or` is redundant
+  --> tests/ui/unnecessary_map_or.rs:13:13
+   |
+LL |     let _ = Some(5).map_or(true, |n| n != 5);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) != Some(5))`
+
+error: this `map_or` is redundant
+  --> tests/ui/unnecessary_map_or.rs:14:13
+   |
+LL |       let _ = Some(5).map_or(false, |n| {
+   |  _____________^
+LL | |         let _ = 1;
+LL | |         n == 5
+LL | |     });
+   | |______^ help: use a standard comparison instead: `(Some(5) == Some(5))`
+
+error: this `map_or` is redundant
+  --> tests/ui/unnecessary_map_or.rs:18:13
+   |
+LL |       let _ = Some(5).map_or(false, |n| {
+   |  _____________^
+LL | |         let _ = n;
+LL | |         6 >= 5
+LL | |     });
+   | |______^
+   |
+help: use is_some_and instead
+   |
+LL ~     let _ = Some(5).is_some_and(|n| {
+LL +         let _ = n;
+LL +         6 >= 5
+LL ~     });
+   |
+
+error: this `map_or` is redundant
+  --> tests/ui/unnecessary_map_or.rs:22:13
+   |
+LL |     let _ = Some(vec![5]).map_or(false, |n| n == [5]);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(vec![5]).is_some_and(|n| n == [5])`
+
+error: this `map_or` is redundant
+  --> tests/ui/unnecessary_map_or.rs:23:13
+   |
+LL |     let _ = Some(vec![1]).map_or(false, |n| vec![2] == n);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(vec![1]).is_some_and(|n| vec![2] == n)`
+
+error: this `map_or` is redundant
+  --> tests/ui/unnecessary_map_or.rs:24:13
+   |
+LL |     let _ = Some(5).map_or(false, |n| n == n);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(|n| n == n)`
+
+error: this `map_or` is redundant
+  --> tests/ui/unnecessary_map_or.rs:25:13
+   |
+LL |     let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 });
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(|n| n == if 2 > 1 { n } else { 0 })`
+
+error: this `map_or` is redundant
+  --> tests/ui/unnecessary_map_or.rs:26:13
+   |
+LL |     let _ = Ok::<Vec<i32>, i32>(vec![5]).map_or(false, |n| n == [5]);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `Ok::<Vec<i32>, i32>(vec![5]).is_ok_and(|n| n == [5])`
+
+error: this `map_or` is redundant
+  --> tests/ui/unnecessary_map_or.rs:27:13
+   |
+LL |     let _ = Ok::<i32, i32>(5).map_or(false, |n| n == 5);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Ok::<i32, i32>(5) == Ok(5))`
+
+error: this `map_or` is redundant
+  --> tests/ui/unnecessary_map_or.rs:28:13
+   |
+LL |     let _ = Some(5).map_or(false, |n| n == 5).then(|| 1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) == Some(5))`
+
+error: this `map_or` is redundant
+  --> tests/ui/unnecessary_map_or.rs:55:13
+   |
+LL |     let _ = r.map_or(false, |x| x == 7);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `r.is_ok_and(|x| x == 7)`
+
+error: this `map_or` is redundant
+  --> tests/ui/unnecessary_map_or.rs:60:13
+   |
+LL |     let _ = r.map_or(false, |x| x == 8);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(r == Ok(8))`
+
+error: aborting due to 13 previous errors
+
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index cef6b525a7b..b784bdb7139 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -14,7 +14,7 @@ unified-diff = "0.2.1"
 getopts = "0.2"
 indexmap = "2.0.0"
 miropt-test-tools = { path = "../miropt-test-tools" }
-build_helper = { path = "../build_helper" }
+build_helper = { path = "../../build_helper" }
 tracing = "0.1"
 tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
 regex = "1.0"
diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs
index 8570a8ce115..bdd0b80b395 100644
--- a/src/tools/compiletest/src/directive-list.rs
+++ b/src/tools/compiletest/src/directive-list.rs
@@ -25,6 +25,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "dont-check-failure-status",
     "edition",
     "error-pattern",
+    "exact-llvm-major-version",
     "exec-env",
     "failure-status",
     "filecheck-flags",
@@ -35,6 +36,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "ignore-64bit",
     "ignore-aarch64",
     "ignore-aarch64-unknown-linux-gnu",
+    "ignore-aix",
     "ignore-android",
     "ignore-apple",
     "ignore-arm",
@@ -118,6 +120,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "incremental",
     "known-bug",
     "llvm-cov-flags",
+    "max-llvm-major-version",
     "min-cdb-version",
     "min-gdb-version",
     "min-lldb-version",
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 300a03e5f33..3539e85ba63 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -1547,6 +1547,20 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
                 };
             }
         } else if let Some(version_string) =
+            config.parse_name_value_directive(line, "max-llvm-major-version")
+        {
+            let max_version = extract_llvm_version(&version_string);
+            // Ignore if actual major version is larger than the maximum required major version.
+            if actual_version.major > max_version.major {
+                return IgnoreDecision::Ignore {
+                    reason: format!(
+                        "ignored when the LLVM version ({actual_version}) is newer than major\
+                        version {}",
+                        max_version.major
+                    ),
+                };
+            }
+        } else if let Some(version_string) =
             config.parse_name_value_directive(line, "min-system-llvm-version")
         {
             let min_version = extract_llvm_version(&version_string);
@@ -1585,6 +1599,19 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
                     };
                 }
             }
+        } else if let Some(version_string) =
+            config.parse_name_value_directive(line, "exact-llvm-major-version")
+        {
+            // Syntax is "exact-llvm-major-version: <version>"
+            let version = extract_llvm_version(&version_string);
+            if actual_version.major != version.major {
+                return IgnoreDecision::Ignore {
+                    reason: format!(
+                        "ignored when the actual LLVM major version is {}, but the test only targets major version {}",
+                        actual_version.major, version.major
+                    ),
+                };
+            }
         }
     }
     IgnoreDecision::Continue
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index c3fb8d4ab80..4d75c38dd32 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -284,6 +284,30 @@ fn llvm_version() {
 
     let config: Config = cfg().llvm_version("10.0.0").build();
     assert!(!check_ignore(&config, "//@ min-llvm-version: 9.0"));
+
+    let config: Config = cfg().llvm_version("10.0.0").build();
+    assert!(check_ignore(&config, "//@ exact-llvm-major-version: 9.0"));
+
+    let config: Config = cfg().llvm_version("9.0.0").build();
+    assert!(check_ignore(&config, "//@ exact-llvm-major-version: 10.0"));
+
+    let config: Config = cfg().llvm_version("10.0.0").build();
+    assert!(!check_ignore(&config, "//@ exact-llvm-major-version: 10.0"));
+
+    let config: Config = cfg().llvm_version("10.0.0").build();
+    assert!(!check_ignore(&config, "//@ exact-llvm-major-version: 10"));
+
+    let config: Config = cfg().llvm_version("10.6.2").build();
+    assert!(!check_ignore(&config, "//@ exact-llvm-major-version: 10"));
+
+    let config: Config = cfg().llvm_version("19.0.0").build();
+    assert!(!check_ignore(&config, "//@ max-llvm-major-version: 19"));
+
+    let config: Config = cfg().llvm_version("19.1.2").build();
+    assert!(!check_ignore(&config, "//@ max-llvm-major-version: 19"));
+
+    let config: Config = cfg().llvm_version("20.0.0").build();
+    assert!(check_ignore(&config, "//@ max-llvm-major-version: 19"));
 }
 
 #[test]
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 07d41ad7fa3..6c84893627a 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-c22887b4d97400e8e024e19fb5f724eda65ad58d
+3bc6916f4ca50bb83b211d9013dac38e84618750
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 63591474120..41b7be37c37 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -195,7 +195,7 @@ pub fn prune_stacktrace<'tcx>(
                 // This len check ensures that we don't somehow remove every frame, as doing so breaks
                 // the primary error message.
                 while stacktrace.len() > 1
-                    && stacktrace.last().map_or(false, |frame| !machine.is_local(frame))
+                    && stacktrace.last().is_some_and(|frame| !machine.is_local(frame))
                 {
                     stacktrace.pop();
                 }
diff --git a/src/tools/opt-dist/Cargo.toml b/src/tools/opt-dist/Cargo.toml
index d34f8ad0520..d0413911014 100644
--- a/src/tools/opt-dist/Cargo.toml
+++ b/src/tools/opt-dist/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.1.0"
 edition = "2021"
 
 [dependencies]
-build_helper = { path = "../build_helper" }
+build_helper = { path = "../../build_helper" }
 env_logger = "0.11"
 log = "0.4"
 anyhow = { version = "1", features = ["backtrace"] }
diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml
index 3affa199fa5..3c172b2d956 100644
--- a/src/tools/run-make-support/Cargo.toml
+++ b/src/tools/run-make-support/Cargo.toml
@@ -10,7 +10,7 @@ similar = "2.5.0"
 wasmparser = { version = "0.216", default-features = false, features = ["std"] }
 regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace
 gimli = "0.31.0"
-build_helper = { path = "../build_helper" }
+build_helper = { path = "../../build_helper" }
 serde_json = "1.0"
 libc = "0.2"
 
diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs
index 35d983dc607..494daeca963 100644
--- a/src/tools/run-make-support/src/external_deps/rustc.rs
+++ b/src/tools/run-make-support/src/external_deps/rustc.rs
@@ -5,7 +5,7 @@ use crate::command::Command;
 use crate::env::env_var;
 use crate::path_helpers::cwd;
 use crate::util::set_host_rpath;
-use crate::{is_darwin, is_msvc, is_windows, uname};
+use crate::{is_aix, is_darwin, is_msvc, is_windows, uname};
 
 /// Construct a new `rustc` invocation. This will automatically set the library
 /// search path as `-L cwd()`. Use [`bare_rustc`] to avoid this.
@@ -346,7 +346,7 @@ impl Rustc {
         //     endif
         // endif
         // ```
-        let flag = if is_windows() {
+        if is_windows() {
             // So this is a bit hacky: we can't use the DLL version of libstdc++ because
             // it pulls in the DLL version of libgcc, which means that we end up with 2
             // instances of the DW2 unwinding implementation. This is a problem on
@@ -362,18 +362,19 @@ impl Rustc {
             // So we end up with the following hack: we link use static:-bundle to only
             // link the parts of libstdc++ that we actually use, which doesn't include
             // the dependency on the pthreads DLL.
-            if is_msvc() { None } else { Some("-lstatic:-bundle=stdc++") }
+            if !is_msvc() {
+                self.cmd.arg("-lstatic:-bundle=stdc++");
+            };
         } else if is_darwin() {
-            Some("-lc++")
+            self.cmd.arg("-lc++");
+        } else if is_aix() {
+            self.cmd.arg("-lc++");
+            self.cmd.arg("-lc++abi");
         } else {
-            match &uname()[..] {
-                "FreeBSD" | "SunOS" | "OpenBSD" => None,
-                _ => Some("-lstdc++"),
-            }
+            if !matches!(&uname()[..], "FreeBSD" | "SunOS" | "OpenBSD") {
+                self.cmd.arg("-lstdc++");
+            };
         };
-        if let Some(flag) = flag {
-            self.cmd.arg(flag);
-        }
         self
     }
 }
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 5765cb97a7e..6cf0aedfe9f 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -78,7 +78,7 @@ pub use env::{env_var, env_var_os, set_current_dir};
 pub use run::{cmd, run, run_fail, run_with_args};
 
 /// Helpers for checking target information.
-pub use targets::{is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname, apple_os};
+pub use targets::{is_aix, is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname, apple_os};
 
 /// Helpers for building names of output artifacts that are potentially target-specific.
 pub use artifact_names::{
diff --git a/src/tools/run-make-support/src/targets.rs b/src/tools/run-make-support/src/targets.rs
index 896abb73fc1..ae004fd0cbd 100644
--- a/src/tools/run-make-support/src/targets.rs
+++ b/src/tools/run-make-support/src/targets.rs
@@ -28,6 +28,12 @@ pub fn is_darwin() -> bool {
     target().contains("darwin")
 }
 
+/// Check if target uses AIX.
+#[must_use]
+pub fn is_aix() -> bool {
+    target().contains("aix")
+}
+
 /// Get the target OS on Apple operating systems.
 #[must_use]
 pub fn apple_os() -> &'static str {
diff --git a/src/tools/rust-analyzer/.github/workflows/autopublish.yaml b/src/tools/rust-analyzer/.github/workflows/autopublish.yaml
index e0135a0269a..5258d9ddd3a 100644
--- a/src/tools/rust-analyzer/.github/workflows/autopublish.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/autopublish.yaml
@@ -53,7 +53,6 @@ jobs:
           cargo workspaces rename --from project-model project_model
           cargo workspaces rename --from test-fixture test_fixture
           cargo workspaces rename --from test-utils test_utils
-          cargo workspaces rename --from text-edit text_edit
           # Remove library crates from the workspaces so we don't auto-publish them as well
           sed -i 's/ "lib\/\*",//' ./Cargo.toml
           cargo workspaces rename ra_ap_%n
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index 6d07dc8f9be..2a13f74aac7 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -13,7 +13,6 @@ use syntax::{ast, Parse};
 use triomphe::Arc;
 
 use crate::{
-    attr::Attrs,
     db::DefDatabase,
     expander::{Expander, Mark},
     item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, MacroCall, ModItem, TreeId},
@@ -37,8 +36,6 @@ pub struct FunctionData {
     pub name: Name,
     pub params: Box<[TypeRefId]>,
     pub ret_type: TypeRefId,
-    // FIXME: why are these stored here? They should be accessed via the query
-    pub attrs: Attrs,
     pub visibility: RawVisibility,
     pub abi: Option<Symbol>,
     pub legacy_const_generics_indices: Option<Box<Box<[u32]>>>,
@@ -115,7 +112,6 @@ impl FunctionData {
                 .filter_map(|(_, param)| param.type_ref)
                 .collect(),
             ret_type: func.ret_type,
-            attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
             visibility,
             abi: func.abi.clone(),
             legacy_const_generics_indices,
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
index 5c25a55362e..95dfe56ff54 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
@@ -633,6 +633,19 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
         "the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe"
     ),
     rustc_attr!(
+        rustc_intrinsic, Normal, template!(Word), ErrorFollowing,
+        "the `#[rustc_intrinsic]` attribute is used to declare intrinsics with function bodies",
+    ),
+    rustc_attr!(
+        rustc_no_mir_inline, Normal, template!(Word), WarnFollowing,
+        "#[rustc_no_mir_inline] prevents the MIR inliner from inlining a function while not affecting codegen"
+    ),
+    rustc_attr!(
+        rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing,
+        "the `#[rustc_intrinsic_must_be_overridden]` attribute is used to declare intrinsics without real bodies",
+    ),
+
+    rustc_attr!(
         rustc_deprecated_safe_2024, Normal, template!(Word), WarnFollowing,
         "the `#[rustc_safe_intrinsic]` marks functions as unsafe in Rust 2024",
     ),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index 05cd7bd37b4..53795c0b600 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
@@ -381,8 +381,9 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
         TyKind::Error.intern(Interner)
     }
 
+    // object safety was renamed to dyn-compatibility but still remains here in chalk.
+    // This will be removed since we are going to migrate to next-gen trait solver.
     fn is_object_safe(&self, trait_id: chalk_ir::TraitId<Interner>) -> bool {
-        // FIXME: When cargo is updated, change to dyn_compatibility
         let trait_ = from_chalk_trait_id(trait_id);
         crate::dyn_compatibility::dyn_compatibility(self.db, trait_).is_none()
     }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs
index c5706172b20..c1ac7ae173b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs
@@ -4,9 +4,8 @@ use super::*;
 fn size_of() {
     check_number(
         r#"
-        extern "rust-intrinsic" {
-            pub fn size_of<T>() -> usize;
-        }
+        #[rustc_intrinsic]
+        pub fn size_of<T>() -> usize;
 
         const GOAL: usize = size_of::<i32>();
         "#,
@@ -19,9 +18,8 @@ fn size_of_val() {
     check_number(
         r#"
         //- minicore: coerce_unsized
-        extern "rust-intrinsic" {
-            pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
-        }
+        #[rustc_intrinsic]
+        pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
 
         struct X(i32, u8);
 
@@ -32,9 +30,8 @@ fn size_of_val() {
     check_number(
         r#"
         //- minicore: coerce_unsized
-        extern "rust-intrinsic" {
-            pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
-        }
+        #[rustc_intrinsic]
+        pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
 
         const GOAL: usize = {
             let it: &[i32] = &[1, 2, 3];
@@ -48,9 +45,8 @@ fn size_of_val() {
         //- minicore: coerce_unsized, transmute
         use core::mem::transmute;
 
-        extern "rust-intrinsic" {
-            pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
-        }
+        #[rustc_intrinsic]
+        pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
 
         struct X {
             x: i64,
@@ -70,9 +66,8 @@ fn size_of_val() {
         //- minicore: coerce_unsized, transmute
         use core::mem::transmute;
 
-        extern "rust-intrinsic" {
-            pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
-        }
+        #[rustc_intrinsic]
+        pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
 
         struct X {
             x: i32,
@@ -90,9 +85,8 @@ fn size_of_val() {
     check_number(
         r#"
         //- minicore: coerce_unsized, fmt, builtin_impls, dispatch_from_dyn
-        extern "rust-intrinsic" {
-            pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
-        }
+        #[rustc_intrinsic]
+        pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
 
         const GOAL: usize = {
             let x: &i16 = &5;
@@ -106,9 +100,8 @@ fn size_of_val() {
     check_number(
         r#"
         //- minicore: coerce_unsized
-        extern "rust-intrinsic" {
-            pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
-        }
+        #[rustc_intrinsic]
+        pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
 
         const GOAL: usize = {
             size_of_val("salam")
@@ -123,9 +116,8 @@ fn min_align_of_val() {
     check_number(
         r#"
         //- minicore: coerce_unsized
-        extern "rust-intrinsic" {
-            pub fn min_align_of_val<T: ?Sized>(_: *const T) -> usize;
-        }
+        #[rustc_intrinsic]
+        pub fn min_align_of_val<T: ?Sized>(_: *const T) -> usize;
 
         struct X(i32, u8);
 
@@ -136,9 +128,8 @@ fn min_align_of_val() {
     check_number(
         r#"
         //- minicore: coerce_unsized
-        extern "rust-intrinsic" {
-            pub fn min_align_of_val<T: ?Sized>(_: *const T) -> usize;
-        }
+        #[rustc_intrinsic]
+        pub fn min_align_of_val<T: ?Sized>(_: *const T) -> usize;
 
         const GOAL: usize = {
             let x: &[i32] = &[1, 2, 3];
@@ -153,9 +144,8 @@ fn min_align_of_val() {
 fn type_name() {
     check_str(
         r#"
-        extern "rust-intrinsic" {
-            pub fn type_name<T: ?Sized>() -> &'static str;
-        }
+        #[rustc_intrinsic]
+        pub fn type_name<T: ?Sized>() -> &'static str;
 
         const GOAL: &str = type_name::<i32>();
         "#,
@@ -163,9 +153,8 @@ fn type_name() {
     );
     check_str(
         r#"
-        extern "rust-intrinsic" {
-            pub fn type_name<T: ?Sized>() -> &'static str;
-        }
+        #[rustc_intrinsic]
+        pub fn type_name<T: ?Sized>() -> &'static str;
 
         mod mod1 {
             pub mod mod2 {
@@ -183,9 +172,8 @@ fn type_name() {
 fn transmute() {
     check_number(
         r#"
-        extern "rust-intrinsic" {
-            pub fn transmute<T, U>(e: T) -> U;
-        }
+        #[rustc_intrinsic]
+        pub fn transmute<T, U>(e: T) -> U;
 
         const GOAL: i32 = transmute((1i16, 1i16));
         "#,
@@ -197,10 +185,10 @@ fn transmute() {
 fn read_via_copy() {
     check_number(
         r#"
-        extern "rust-intrinsic" {
-            pub fn read_via_copy<T>(e: *const T) -> T;
-            pub fn volatile_load<T>(e: *const T) -> T;
-        }
+        #[rustc_intrinsic]
+        pub fn read_via_copy<T>(e: *const T) -> T;
+        #[rustc_intrinsic]
+        pub fn volatile_load<T>(e: *const T) -> T;
 
         const GOAL: i32 = {
             let x = 2;
@@ -399,9 +387,14 @@ fn discriminant_value() {
 fn likely() {
     check_number(
         r#"
-        extern "rust-intrinsic" {
-            pub fn likely(b: bool) -> bool;
-            pub fn unlikely(b: bool) -> bool;
+        #[rustc_intrinsic]
+        pub const fn likely(b: bool) -> bool {
+            b
+        }
+
+        #[rustc_intrinsic]
+        pub const fn unlikely(b: bool) -> bool {
+            b
         }
 
         const GOAL: bool = likely(true) && unlikely(true) && !likely(false) && !unlikely(false);
@@ -704,9 +697,8 @@ fn rotate() {
     );
     check_number(
         r#"
-        extern "rust-intrinsic" {
-            pub fn rotate_right<T: Copy>(x: T, y: T) -> T;
-        }
+        #[rustc_intrinsic]
+        pub fn rotate_right<T: Copy>(x: T, y: T) -> T;
 
         const GOAL: i32 = rotate_right(10006016, 1020315);
         "#,
@@ -721,9 +713,8 @@ fn simd() {
         pub struct i8x16(
             i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,
         );
-        extern "platform-intrinsic" {
-            pub fn simd_bitmask<T, U>(x: T) -> U;
-        }
+        #[rustc_intrinsic]
+        pub fn simd_bitmask<T, U>(x: T) -> U;
         const GOAL: u16 = simd_bitmask(i8x16(
             0, 1, 0, 0, 2, 255, 100, 0, 50, 0, 1, 1, 0, 0, 0, 0
         ));
@@ -735,10 +726,10 @@ fn simd() {
         pub struct i8x16(
             i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,i8,
         );
-        extern "platform-intrinsic" {
-            pub fn simd_lt<T, U>(x: T, y: T) -> U;
-            pub fn simd_bitmask<T, U>(x: T) -> U;
-        }
+        #[rustc_intrinsic]
+        pub fn simd_lt<T, U>(x: T, y: T) -> U;
+        #[rustc_intrinsic]
+        pub fn simd_bitmask<T, U>(x: T) -> U;
         const GOAL: u16 = simd_bitmask(simd_lt::<i8x16, i8x16>(
             i8x16(
                 -105, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs
index c9ab0acc084..4991d173b9c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs
@@ -201,7 +201,7 @@ impl<'a> DeclValidator<'a> {
 
             // Don't run the lint on extern "[not Rust]" fn items with the
             // #[no_mangle] attribute.
-            let no_mangle = data.attrs.by_key(&sym::no_mangle).exists();
+            let no_mangle = self.db.attrs(func.into()).by_key(&sym::no_mangle).exists();
             if no_mangle && data.abi.as_ref().is_some_and(|abi| *abi != sym::Rust) {
                 cov_mark::hit!(extern_func_no_mangle_ignored);
             } else {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
index 3d21785a70a..fadf8aca998 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
@@ -472,7 +472,7 @@ fn receiver_is_dispatchable(
         return false;
     };
 
-    // `self: Self` can't be dispatched on, but this is already considered dyn compatible
+    // `self: Self` can't be dispatched on, but this is already considered dyn-compatible
     // See rustc's comment on https://github.com/rust-lang/rust/blob/3f121b9461cce02a703a0e7e450568849dfaa074/compiler/rustc_trait_selection/src/traits/object_safety.rs#L433-L437
     if sig
         .skip_binders()
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs
index 3f3e68eeb1c..8a56bd28b59 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs
@@ -66,7 +66,7 @@ fn check_dyn_compatibility<'a>(
             });
             ControlFlow::Continue(())
         });
-        assert_eq!(osvs, expected, "Dyn Compatibility violations for `{name}` do not match;");
+        assert_eq!(osvs, expected, "dyn-compatibility violations for `{name}` do not match;");
     }
 
     let remains: Vec<_> = expected.keys().collect();
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index 9c1d8bcf36f..22e7b1d920f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -98,7 +98,7 @@ pub use mapping::{
 };
 pub use method_resolution::check_orphan_rules;
 pub use traits::TraitEnvironment;
-pub use utils::{all_super_traits, is_fn_unsafe_to_call};
+pub use utils::{all_super_traits, direct_super_traits, is_fn_unsafe_to_call};
 
 pub use chalk_ir::{
     cast::Cast,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
index 0cdad74a4f6..0a78f4a5b24 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
@@ -9,7 +9,7 @@ use hir_def::{
     resolver::HasResolver,
 };
 use hir_expand::name::Name;
-use intern::sym;
+use intern::{sym, Symbol};
 
 use crate::{
     error_lifetime,
@@ -54,49 +54,32 @@ impl Evaluator<'_> {
         }
 
         let function_data = self.db.function_data(def);
-        let is_intrinsic = match &function_data.abi {
-            Some(abi) => *abi == sym::rust_dash_intrinsic,
-            None => match def.lookup(self.db.upcast()).container {
-                hir_def::ItemContainerId::ExternBlockId(block) => {
-                    let id = block.lookup(self.db.upcast()).id;
-                    id.item_tree(self.db.upcast())[id.value].abi.as_ref()
-                        == Some(&sym::rust_dash_intrinsic)
-                }
-                _ => false,
-            },
-        };
+        let attrs = self.db.attrs(def.into());
+        let is_intrinsic = attrs.by_key(&sym::rustc_intrinsic).exists()
+            // Keep this around for a bit until extern "rustc-intrinsic" abis are no longer used
+            || (match &function_data.abi {
+                Some(abi) => *abi == sym::rust_dash_intrinsic,
+                None => match def.lookup(self.db.upcast()).container {
+                    hir_def::ItemContainerId::ExternBlockId(block) => {
+                        let id = block.lookup(self.db.upcast()).id;
+                        id.item_tree(self.db.upcast())[id.value].abi.as_ref()
+                            == Some(&sym::rust_dash_intrinsic)
+                    }
+                    _ => false,
+                },
+            });
+
         if is_intrinsic {
-            self.exec_intrinsic(
+            return self.exec_intrinsic(
                 function_data.name.as_str(),
                 args,
                 generic_args,
                 destination,
                 locals,
                 span,
-            )?;
-            return Ok(true);
-        }
-        let is_platform_intrinsic = match &function_data.abi {
-            Some(abi) => *abi == sym::platform_dash_intrinsic,
-            None => match def.lookup(self.db.upcast()).container {
-                hir_def::ItemContainerId::ExternBlockId(block) => {
-                    let id = block.lookup(self.db.upcast()).id;
-                    id.item_tree(self.db.upcast())[id.value].abi.as_ref()
-                        == Some(&sym::platform_dash_intrinsic)
-                }
-                _ => false,
-            },
-        };
-        if is_platform_intrinsic {
-            self.exec_platform_intrinsic(
-                function_data.name.as_str(),
-                args,
-                generic_args,
-                destination,
-                locals,
-                span,
-            )?;
-            return Ok(true);
+                !function_data.has_body()
+                    || attrs.by_key(&sym::rustc_intrinsic_must_be_overridden).exists(),
+            );
         }
         let is_extern_c = match def.lookup(self.db.upcast()).container {
             hir_def::ItemContainerId::ExternBlockId(block) => {
@@ -106,27 +89,25 @@ impl Evaluator<'_> {
             _ => false,
         };
         if is_extern_c {
-            self.exec_extern_c(
-                function_data.name.as_str(),
-                args,
-                generic_args,
-                destination,
-                locals,
-                span,
-            )?;
-            return Ok(true);
+            return self
+                .exec_extern_c(
+                    function_data.name.as_str(),
+                    args,
+                    generic_args,
+                    destination,
+                    locals,
+                    span,
+                )
+                .map(|()| true);
         }
-        let alloc_fn = function_data
-            .attrs
-            .iter()
-            .filter_map(|it| it.path().as_ident())
-            .map(|it| it.as_str())
-            .find(|it| {
+
+        let alloc_fn =
+            attrs.iter().filter_map(|it| it.path().as_ident()).map(|it| it.symbol()).find(|it| {
                 [
-                    "rustc_allocator",
-                    "rustc_deallocator",
-                    "rustc_reallocator",
-                    "rustc_allocator_zeroed",
+                    &sym::rustc_allocator,
+                    &sym::rustc_deallocator,
+                    &sym::rustc_reallocator,
+                    &sym::rustc_allocator_zeroed,
                 ]
                 .contains(it)
             });
@@ -270,12 +251,12 @@ impl Evaluator<'_> {
 
     fn exec_alloc_fn(
         &mut self,
-        alloc_fn: &str,
+        alloc_fn: &Symbol,
         args: &[IntervalAndTy],
         destination: Interval,
     ) -> Result<()> {
         match alloc_fn {
-            "rustc_allocator_zeroed" | "rustc_allocator" => {
+            _ if *alloc_fn == sym::rustc_allocator_zeroed || *alloc_fn == sym::rustc_allocator => {
                 let [size, align] = args else {
                     return Err(MirEvalError::InternalError(
                         "rustc_allocator args are not provided".into(),
@@ -286,8 +267,8 @@ impl Evaluator<'_> {
                 let result = self.heap_allocate(size, align)?;
                 destination.write_from_bytes(self, &result.to_bytes())?;
             }
-            "rustc_deallocator" => { /* no-op for now */ }
-            "rustc_reallocator" => {
+            _ if *alloc_fn == sym::rustc_deallocator => { /* no-op for now */ }
+            _ if *alloc_fn == sym::rustc_reallocator => {
                 let [ptr, old_size, align, new_size] = args else {
                     return Err(MirEvalError::InternalError(
                         "rustc_allocator args are not provided".into(),
@@ -603,21 +584,6 @@ impl Evaluator<'_> {
         }
     }
 
-    fn exec_platform_intrinsic(
-        &mut self,
-        name: &str,
-        args: &[IntervalAndTy],
-        generic_args: &Substitution,
-        destination: Interval,
-        locals: &Locals,
-        span: MirSpan,
-    ) -> Result<()> {
-        if let Some(name) = name.strip_prefix("simd_") {
-            return self.exec_simd_intrinsic(name, args, generic_args, destination, locals, span);
-        }
-        not_supported!("unknown platform intrinsic {name}");
-    }
-
     fn exec_intrinsic(
         &mut self,
         name: &str,
@@ -626,9 +592,17 @@ impl Evaluator<'_> {
         destination: Interval,
         locals: &Locals,
         span: MirSpan,
-    ) -> Result<()> {
+        needs_override: bool,
+    ) -> Result<bool> {
         if let Some(name) = name.strip_prefix("atomic_") {
-            return self.exec_atomic_intrinsic(name, args, generic_args, destination, locals, span);
+            return self
+                .exec_atomic_intrinsic(name, args, generic_args, destination, locals, span)
+                .map(|()| true);
+        }
+        if let Some(name) = name.strip_prefix("simd_") {
+            return self
+                .exec_simd_intrinsic(name, args, generic_args, destination, locals, span)
+                .map(|()| true);
         }
         // FIXME(#17451): Add `f16` and `f128` intrinsics.
         if let Some(name) = name.strip_suffix("f64") {
@@ -701,7 +675,7 @@ impl Evaluator<'_> {
                 }
                 _ => not_supported!("unknown f64 intrinsic {name}"),
             };
-            return destination.write_from_bytes(self, &result.to_le_bytes());
+            return destination.write_from_bytes(self, &result.to_le_bytes()).map(|()| true);
         }
         if let Some(name) = name.strip_suffix("f32") {
             let result = match name {
@@ -773,7 +747,7 @@ impl Evaluator<'_> {
                 }
                 _ => not_supported!("unknown f32 intrinsic {name}"),
             };
-            return destination.write_from_bytes(self, &result.to_le_bytes());
+            return destination.write_from_bytes(self, &result.to_le_bytes()).map(|()| true);
         }
         match name {
             "size_of" => {
@@ -1146,12 +1120,6 @@ impl Evaluator<'_> {
                 };
                 destination.write_from_interval(self, arg.interval)
             }
-            "likely" | "unlikely" => {
-                let [arg] = args else {
-                    return Err(MirEvalError::InternalError("likely arg is not provided".into()));
-                };
-                destination.write_from_interval(self, arg.interval)
-            }
             "ctpop" => {
                 let [arg] = args else {
                     return Err(MirEvalError::InternalError("ctpop arg is not provided".into()));
@@ -1296,7 +1264,7 @@ impl Evaluator<'_> {
                             None,
                             span,
                         )?;
-                        return Ok(());
+                        return Ok(true);
                     }
                 }
                 not_supported!("FnOnce was not available for executing const_eval_select");
@@ -1349,8 +1317,10 @@ impl Evaluator<'_> {
                 self.write_memory_using_ref(dst, size)?.fill(val);
                 Ok(())
             }
-            _ => not_supported!("unknown intrinsic {name}"),
+            _ if needs_override => not_supported!("intrinsic {name} is not implemented"),
+            _ => return Ok(false),
         }
+        .map(|()| true)
     }
 
     fn size_align_of_unsized(
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
index 0a436ff2b41..28bda1e10e5 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -43,6 +43,17 @@ pub(crate) fn fn_traits(
         .flat_map(|it| it.as_trait())
 }
 
+/// Returns an iterator over the direct super traits (including the trait itself).
+pub fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[TraitId; 4]> {
+    let mut result = smallvec![trait_];
+    direct_super_traits_cb(db, trait_, |tt| {
+        if !result.contains(&tt) {
+            result.push(tt);
+        }
+    });
+    result
+}
+
 /// Returns an iterator over the whole super trait hierarchy (including the
 /// trait itself).
 pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[TraitId; 4]> {
@@ -54,7 +65,7 @@ pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[Trai
     while let Some(&t) = result.get(i) {
         // yeah this is quadratic, but trait hierarchies should be flat
         // enough that this doesn't matter
-        direct_super_traits(db, t, |tt| {
+        direct_super_traits_cb(db, t, |tt| {
             if !result.contains(&tt) {
                 result.push(tt);
             }
@@ -153,7 +164,7 @@ impl Iterator for ClauseElaborator<'_> {
     }
 }
 
-fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) {
+fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) {
     let resolver = trait_.resolver(db);
     let generic_params = db.generic_params(trait_.into());
     let trait_self = generic_params.trait_self_param();
@@ -259,25 +270,25 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
         return true;
     }
 
+    let is_intrinsic = db.attrs(func.into()).by_key(&sym::rustc_intrinsic).exists()
+        || data.abi.as_ref() == Some(&sym::rust_dash_intrinsic);
+
     let loc = func.lookup(db.upcast());
     match loc.container {
         hir_def::ItemContainerId::ExternBlockId(block) => {
-            // Function in an `extern` block are always unsafe to call, except when
-            // it is marked as `safe` or it has `"rust-intrinsic"` ABI there are a
-            // few exceptions.
-            let id = block.lookup(db.upcast()).id;
-
-            let is_intrinsic =
-                id.item_tree(db.upcast())[id.value].abi.as_ref() == Some(&sym::rust_dash_intrinsic);
-
-            if is_intrinsic {
+            if is_intrinsic || {
+                let id = block.lookup(db.upcast()).id;
+                id.item_tree(db.upcast())[id.value].abi.as_ref() == Some(&sym::rust_dash_intrinsic)
+            } {
                 // Intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute
-                !data.attrs.by_key(&sym::rustc_safe_intrinsic).exists()
+                !db.attrs(func.into()).by_key(&sym::rustc_safe_intrinsic).exists()
             } else {
-                // Extern items without `safe` modifier are always unsafe
+                // Function in an `extern` block are always unsafe to call, except when
+                // it is marked as `safe`.
                 !data.is_safe()
             }
         }
+        _ if is_intrinsic => !db.attrs(func.into()).by_key(&sym::rustc_safe_intrinsic).exists(),
         _ => false,
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index ebd84fd2be2..c9498b3aead 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -68,7 +68,7 @@ use hir_ty::{
     all_super_traits, autoderef, check_orphan_rules,
     consteval::{try_const_usize, unknown_const_as_generic, ConstExt},
     diagnostics::BodyValidationDiagnostic,
-    error_lifetime, known_const_to_ast,
+    direct_super_traits, error_lifetime, known_const_to_ast,
     layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
     method_resolution,
     mir::{interpret_mir, MutBorrowKind},
@@ -2246,35 +2246,33 @@ impl Function {
 
     /// Does this function have `#[test]` attribute?
     pub fn is_test(self, db: &dyn HirDatabase) -> bool {
-        db.function_data(self.id).attrs.is_test()
+        db.attrs(self.id.into()).is_test()
     }
 
     /// is this a `fn main` or a function with an `export_name` of `main`?
     pub fn is_main(self, db: &dyn HirDatabase) -> bool {
-        let data = db.function_data(self.id);
-        data.attrs.export_name() == Some(&sym::main)
-            || self.module(db).is_crate_root() && data.name == sym::main
+        db.attrs(self.id.into()).export_name() == Some(&sym::main)
+            || self.module(db).is_crate_root() && db.function_data(self.id).name == sym::main
     }
 
     /// Is this a function with an `export_name` of `main`?
     pub fn exported_main(self, db: &dyn HirDatabase) -> bool {
-        let data = db.function_data(self.id);
-        data.attrs.export_name() == Some(&sym::main)
+        db.attrs(self.id.into()).export_name() == Some(&sym::main)
     }
 
     /// Does this function have the ignore attribute?
     pub fn is_ignore(self, db: &dyn HirDatabase) -> bool {
-        db.function_data(self.id).attrs.is_ignore()
+        db.attrs(self.id.into()).is_ignore()
     }
 
     /// Does this function have `#[bench]` attribute?
     pub fn is_bench(self, db: &dyn HirDatabase) -> bool {
-        db.function_data(self.id).attrs.is_bench()
+        db.attrs(self.id.into()).is_bench()
     }
 
     /// Is this function marked as unstable with `#[feature]` attribute?
     pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
-        db.function_data(self.id).attrs.is_unstable()
+        db.attrs(self.id.into()).is_unstable()
     }
 
     pub fn is_unsafe_to_call(self, db: &dyn HirDatabase) -> bool {
@@ -2289,8 +2287,7 @@ impl Function {
     }
 
     pub fn as_proc_macro(self, db: &dyn HirDatabase) -> Option<Macro> {
-        let function_data = db.function_data(self.id);
-        let attrs = &function_data.attrs;
+        let attrs = db.attrs(self.id.into());
         // FIXME: Store this in FunctionData flags?
         if !(attrs.is_proc_macro()
             || attrs.is_proc_macro_attribute()
@@ -2707,13 +2704,22 @@ impl Trait {
         db.trait_data(self.id).name.clone()
     }
 
+    pub fn direct_supertraits(self, db: &dyn HirDatabase) -> Vec<Trait> {
+        let traits = direct_super_traits(db.upcast(), self.into());
+        traits.iter().map(|tr| Trait::from(*tr)).collect()
+    }
+
+    pub fn all_supertraits(self, db: &dyn HirDatabase) -> Vec<Trait> {
+        let traits = all_super_traits(db.upcast(), self.into());
+        traits.iter().map(|tr| Trait::from(*tr)).collect()
+    }
+
     pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
         db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
     }
 
     pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
-        let traits = all_super_traits(db.upcast(), self.into());
-        traits.iter().flat_map(|tr| Trait::from(*tr).items(db)).collect()
+        self.all_supertraits(db).into_iter().flat_map(|tr| tr.items(db)).collect()
     }
 
     pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
diff --git a/src/tools/rust-analyzer/crates/ide/src/file_structure.rs b/src/tools/rust-analyzer/crates/ide/src/file_structure.rs
index 055080ad17b..5ef65c209ca 100644
--- a/src/tools/rust-analyzer/crates/ide/src/file_structure.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/file_structure.rs
@@ -19,6 +19,7 @@ pub struct StructureNode {
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
 pub enum StructureNodeKind {
     SymbolKind(SymbolKind),
+    ExternBlock,
     Region,
 }
 
@@ -158,6 +159,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
             ast::Trait(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Trait)),
             ast::TraitAlias(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::TraitAlias)),
             ast::Module(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Module)),
+            ast::Macro(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Macro)),
             ast::TypeAlias(it) => decl_with_type_ref(&it, it.ty(), StructureNodeKind::SymbolKind(SymbolKind::TypeAlias)),
             ast::RecordField(it) => decl_with_type_ref(&it, it.ty(), StructureNodeKind::SymbolKind(SymbolKind::Field)),
             ast::Const(it) => decl_with_type_ref(&it, it.ty(), StructureNodeKind::SymbolKind(SymbolKind::Const)),
@@ -205,7 +207,23 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
 
                 Some(node)
             },
-            ast::Macro(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Macro)),
+            ast::ExternBlock(it) => {
+                let mut label = "extern".to_owned();
+                let abi = it.abi()?;
+                if let Some(abi) = abi.string_token() {
+                    label.push(' ');
+                    label.push_str(abi.text());
+                }
+                Some(StructureNode {
+                    parent: None,
+                    label,
+                    navigation_range: abi.syntax().text_range(),
+                    node_range: it.syntax().text_range(),
+                    kind: StructureNodeKind::ExternBlock,
+                    detail: None,
+                    deprecated: false,
+                })
+            },
             _ => None,
         }
     }
@@ -327,6 +345,8 @@ fn f() {}
 fn g() {}
 }
 
+extern "C" {}
+
 fn let_statements() {
     let x = 42;
     let mut y = x;
@@ -664,9 +684,18 @@ fn let_statements() {
                     },
                     StructureNode {
                         parent: None,
+                        label: "extern \"C\"",
+                        navigation_range: 638..648,
+                        node_range: 638..651,
+                        kind: ExternBlock,
+                        detail: None,
+                        deprecated: false,
+                    },
+                    StructureNode {
+                        parent: None,
                         label: "let_statements",
-                        navigation_range: 641..655,
-                        node_range: 638..798,
+                        navigation_range: 656..670,
+                        node_range: 653..813,
                         kind: SymbolKind(
                             Function,
                         ),
@@ -677,11 +706,11 @@ fn let_statements() {
                     },
                     StructureNode {
                         parent: Some(
-                            26,
+                            27,
                         ),
                         label: "x",
-                        navigation_range: 668..669,
-                        node_range: 664..675,
+                        navigation_range: 683..684,
+                        node_range: 679..690,
                         kind: SymbolKind(
                             Local,
                         ),
@@ -690,11 +719,11 @@ fn let_statements() {
                     },
                     StructureNode {
                         parent: Some(
-                            26,
+                            27,
                         ),
                         label: "mut y",
-                        navigation_range: 684..689,
-                        node_range: 680..694,
+                        navigation_range: 699..704,
+                        node_range: 695..709,
                         kind: SymbolKind(
                             Local,
                         ),
@@ -703,11 +732,11 @@ fn let_statements() {
                     },
                     StructureNode {
                         parent: Some(
-                            26,
+                            27,
                         ),
                         label: "Foo { .. }",
-                        navigation_range: 703..725,
-                        node_range: 699..738,
+                        navigation_range: 718..740,
+                        node_range: 714..753,
                         kind: SymbolKind(
                             Local,
                         ),
@@ -716,11 +745,11 @@ fn let_statements() {
                     },
                     StructureNode {
                         parent: Some(
-                            26,
+                            27,
                         ),
                         label: "_",
-                        navigation_range: 788..789,
-                        node_range: 784..796,
+                        navigation_range: 803..804,
+                        node_range: 799..811,
                         kind: SymbolKind(
                             Local,
                         ),
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
index d9ddc2d015b..5a00d635698 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
@@ -1009,10 +1009,10 @@ fn render_dyn_compatibility(
     safety: Option<DynCompatibilityViolation>,
 ) {
     let Some(osv) = safety else {
-        buf.push_str("Is Dyn compatible");
+        buf.push_str("Is dyn-compatible");
         return;
     };
-    buf.push_str("Is not Dyn compatible due to ");
+    buf.push_str("Is not dyn-compatible due to ");
     match osv {
         DynCompatibilityViolation::SizedSelf => {
             buf.push_str("having a `Self: Sized` bound");
@@ -1055,7 +1055,7 @@ fn render_dyn_compatibility(
         }
         DynCompatibilityViolation::HasNonCompatibleSuperTrait(super_trait) => {
             let name = hir::Trait::from(super_trait).name(db);
-            format_to!(buf, "having a dyn incompatible supertrait `{}`", name.as_str());
+            format_to!(buf, "having a dyn-incompatible supertrait `{}`", name.as_str());
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
index 0ffbf988c35..0986d5542cd 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -9371,7 +9371,7 @@ trait Compat$0 {}
 
             ---
 
-            Is Dyn compatible
+            Is dyn-compatible
         "#]],
     );
     check(
@@ -9393,7 +9393,7 @@ trait UnCompat$0 {
 
             ---
 
-            Is not Dyn compatible due to having a method `f` that is not dispatchable due to missing a receiver
+            Is not dyn-compatible due to having a method `f` that is not dispatchable due to missing a receiver
         "#]],
     );
     check(
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
index aecafb444c3..865518fe941 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
@@ -392,18 +392,22 @@ define_symbols! {
     rust_2024,
     rust_analyzer,
     Rust,
+    rustc_allocator_zeroed,
+    rustc_allocator,
     rustc_allow_incoherent_impl,
     rustc_builtin_macro,
     rustc_coherence_is_core,
     rustc_const_panic_str,
+    rustc_deallocator,
     rustc_deprecated_safe_2024,
     rustc_has_incoherent_inherent_impls,
-    rustc_intrinsic,
     rustc_intrinsic_must_be_overridden,
+    rustc_intrinsic,
     rustc_layout_scalar_valid_range_end,
     rustc_layout_scalar_valid_range_start,
     rustc_legacy_const_generics,
     rustc_macro_transparency,
+    rustc_reallocator,
     rustc_reservation_impl,
     rustc_safe_intrinsic,
     rustc_skip_array_during_method_dispatch,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
index fa584ab4d21..a5c9d2823e0 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
@@ -1131,7 +1131,7 @@ pub(crate) fn handle_completion_resolve(
     else {
         return Ok(original_completion);
     };
-    let resolved_completions = to_proto::completion_items(
+    let mut resolved_completions = to_proto::completion_items(
         &snap.config,
         &forced_resolve_completions_config.fields_to_resolve,
         &line_index,
@@ -1140,15 +1140,13 @@ pub(crate) fn handle_completion_resolve(
         resolve_data.trigger_character,
         resolved_completions,
     );
-    let Some(mut resolved_completion) = resolved_completions.into_iter().find(|completion| {
-        completion.label == original_completion.label
-            && completion.kind == original_completion.kind
-            && completion.deprecated == original_completion.deprecated
-            && completion.preselect == original_completion.preselect
-            && completion.sort_text == original_completion.sort_text
-    }) else {
-        return Ok(original_completion);
-    };
+
+    let mut resolved_completion =
+        if resolved_completions.get(resolve_data.completion_item_index).is_some() {
+            resolved_completions.swap_remove(resolve_data.completion_item_index)
+        } else {
+            return Ok(original_completion);
+        };
 
     if !resolve_data.imports.is_empty() {
         let additional_edits = snap
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
index 8039f0644ee..6ddfe118d5e 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
@@ -826,6 +826,7 @@ pub struct CompletionResolveData {
     pub imports: Vec<CompletionImport>,
     pub version: Option<i32>,
     pub trigger_character: Option<char>,
+    pub completion_item_index: usize,
 }
 
 #[derive(Debug, Serialize, Deserialize)]
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
index d654dc3e7f4..d444f90a131 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
@@ -88,6 +88,7 @@ pub(crate) fn structure_node_kind(kind: StructureNodeKind) -> lsp_types::SymbolK
     match kind {
         StructureNodeKind::SymbolKind(symbol) => symbol_kind(symbol),
         StructureNodeKind::Region => lsp_types::SymbolKind::NAMESPACE,
+        StructureNodeKind::ExternBlock => lsp_types::SymbolKind::NAMESPACE,
     }
 }
 
@@ -391,18 +392,36 @@ fn completion_item(
         } else {
             Vec::new()
         };
-    if something_to_resolve || !imports.is_empty() {
-        let data = lsp_ext::CompletionResolveData {
+    let (ref_resolve_data, resolve_data) = if something_to_resolve || !imports.is_empty() {
+        let mut item_index = acc.len();
+        let ref_resolve_data = if ref_match.is_some() {
+            let ref_resolve_data = lsp_ext::CompletionResolveData {
+                position: tdpp.clone(),
+                imports: Vec::new(),
+                version,
+                trigger_character: completion_trigger_character,
+                completion_item_index: item_index,
+            };
+            item_index += 1;
+            Some(to_value(ref_resolve_data).unwrap())
+        } else {
+            None
+        };
+        let resolve_data = lsp_ext::CompletionResolveData {
             position: tdpp.clone(),
             imports,
             version,
             trigger_character: completion_trigger_character,
+            completion_item_index: item_index,
         };
-        lsp_item.data = Some(to_value(data).unwrap());
-    }
+        (ref_resolve_data, Some(to_value(resolve_data).unwrap()))
+    } else {
+        (None, None)
+    };
 
     if let Some((label, indel, relevance)) = ref_match {
-        let mut lsp_item_with_ref = lsp_types::CompletionItem { label, ..lsp_item.clone() };
+        let mut lsp_item_with_ref =
+            lsp_types::CompletionItem { label, data: ref_resolve_data, ..lsp_item.clone() };
         lsp_item_with_ref
             .additional_text_edits
             .get_or_insert_with(Default::default)
@@ -411,6 +430,7 @@ fn completion_item(
         acc.push(lsp_item_with_ref);
     };
 
+    lsp_item.data = resolve_data;
     acc.push(lsp_item);
 
     fn set_score(
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
index 67629fcf7cc..07767d5ae9f 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
@@ -370,15 +370,13 @@ pub mod mem {
     // endregion:drop
 
     // region:transmute
-    extern "rust-intrinsic" {
-        pub fn transmute<Src, Dst>(src: Src) -> Dst;
-    }
+    #[rustc_intrinsic]
+    pub fn transmute<Src, Dst>(src: Src) -> Dst;
     // endregion:transmute
 
     // region:size_of
-    extern "rust-intrinsic" {
-        pub fn size_of<T>() -> usize;
-    }
+    #[rustc_intrinsic]
+    pub fn size_of<T>() -> usize;
     // endregion:size_of
 
     // region:discriminant
diff --git a/src/tools/rust-analyzer/docs/dev/README.md b/src/tools/rust-analyzer/docs/dev/README.md
index 12e6d829a08..cd0f49174cd 100644
--- a/src/tools/rust-analyzer/docs/dev/README.md
+++ b/src/tools/rust-analyzer/docs/dev/README.md
@@ -47,7 +47,7 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer
   Each triaged issue should have one of these labels.
 * [fun](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3Afun)
   is for cool, but probably hard stuff.
-* [Design](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%Design)
+* [C-Architecture](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aissue%20state%3Aopen%20label%3AC-Architecture)
   is for moderate/large scale architecture discussion.
   Also a kind of fun.
   These issues should generally include a link to a Zulip discussion thread.
diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
index 7764f7843a0..b7c536e0279 100644
--- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
+++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp/ext.rs hash: 90cf7718d54fe3c2
+lsp/ext.rs hash: 96f88b7a5d0080c6
 
 If you need to change the above hash to make the test pass, please check if you
 need to adjust this doc as well and ping this issue:
diff --git a/src/tools/rust-analyzer/editors/code/package-lock.json b/src/tools/rust-analyzer/editors/code/package-lock.json
index 10b633511d3..6027f813311 100644
--- a/src/tools/rust-analyzer/editors/code/package-lock.json
+++ b/src/tools/rust-analyzer/editors/code/package-lock.json
@@ -13,12 +13,12 @@
                 "anser": "^2.1.1",
                 "d3": "^7.8.5",
                 "d3-graphviz": "^5.0.2",
-                "vscode-languageclient": "^8.1.0"
+                "vscode-languageclient": "^9.0.1"
             },
             "devDependencies": {
                 "@tsconfig/strictest": "^2.0.1",
                 "@types/node": "~16.11.7",
-                "@types/vscode": "~1.78.1",
+                "@types/vscode": "~1.83",
                 "@typescript-eslint/eslint-plugin": "^6.0.0",
                 "@typescript-eslint/parser": "^6.0.0",
                 "@vscode/test-electron": "^2.3.8",
@@ -32,7 +32,7 @@
                 "typescript": "^5.6.0"
             },
             "engines": {
-                "vscode": "^1.78.0"
+                "vscode": "^1.83.0"
             }
         },
         "node_modules/@aashutoshrathi/word-wrap": {
@@ -880,9 +880,9 @@
             "dev": true
         },
         "node_modules/@types/vscode": {
-            "version": "1.78.1",
-            "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.78.1.tgz",
-            "integrity": "sha512-wEA+54axejHu7DhcUfnFBan1IqFD1gBDxAFz8LoX06NbNDMRJv/T6OGthOs52yZccasKfN588EyffHWABkR0fg==",
+            "version": "1.83.3",
+            "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.83.3.tgz",
+            "integrity": "sha512-ZPp5+OQNYrCSFoT4jWOZKdcuXijj+JdN2BJNDhWH4pPbVL6PRQycG9NT8C4a94oul1tFMbkVbXXa9HasI7cLUg==",
             "dev": true
         },
         "node_modules/@typescript-eslint/eslint-plugin": {
@@ -5059,24 +5059,24 @@
             }
         },
         "node_modules/vscode-jsonrpc": {
-            "version": "8.1.0",
-            "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.1.0.tgz",
-            "integrity": "sha512-6TDy/abTQk+zDGYazgbIPc+4JoXdwC8NHU9Pbn4UJP1fehUyZmM4RHp5IthX7A6L5KS30PRui+j+tbbMMMafdw==",
+            "version": "8.2.0",
+            "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz",
+            "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==",
             "engines": {
                 "node": ">=14.0.0"
             }
         },
         "node_modules/vscode-languageclient": {
-            "version": "8.1.0",
-            "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.1.0.tgz",
-            "integrity": "sha512-GL4QdbYUF/XxQlAsvYWZRV3V34kOkpRlvV60/72ghHfsYFnS/v2MANZ9P6sHmxFcZKOse8O+L9G7Czg0NUWing==",
+            "version": "9.0.1",
+            "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz",
+            "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==",
             "dependencies": {
                 "minimatch": "^5.1.0",
                 "semver": "^7.3.7",
-                "vscode-languageserver-protocol": "3.17.3"
+                "vscode-languageserver-protocol": "3.17.5"
             },
             "engines": {
-                "vscode": "^1.67.0"
+                "vscode": "^1.82.0"
             }
         },
         "node_modules/vscode-languageclient/node_modules/brace-expansion": {
@@ -5099,18 +5099,18 @@
             }
         },
         "node_modules/vscode-languageserver-protocol": {
-            "version": "3.17.3",
-            "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.3.tgz",
-            "integrity": "sha512-924/h0AqsMtA5yK22GgMtCYiMdCOtWTSGgUOkgEDX+wk2b0x4sAfLiO4NxBxqbiVtz7K7/1/RgVrVI0NClZwqA==",
+            "version": "3.17.5",
+            "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz",
+            "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==",
             "dependencies": {
-                "vscode-jsonrpc": "8.1.0",
-                "vscode-languageserver-types": "3.17.3"
+                "vscode-jsonrpc": "8.2.0",
+                "vscode-languageserver-types": "3.17.5"
             }
         },
         "node_modules/vscode-languageserver-types": {
-            "version": "3.17.3",
-            "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.3.tgz",
-            "integrity": "sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA=="
+            "version": "3.17.5",
+            "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz",
+            "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="
         },
         "node_modules/which": {
             "version": "2.0.2",
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index ccc8c0e3842..b868622b3a5 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -27,7 +27,7 @@
         }
     },
     "engines": {
-        "vscode": "^1.78.0"
+        "vscode": "^1.83.0"
     },
     "enabledApiProposals": [],
     "scripts": {
@@ -49,12 +49,12 @@
         "anser": "^2.1.1",
         "d3": "^7.8.5",
         "d3-graphviz": "^5.0.2",
-        "vscode-languageclient": "^8.1.0"
+        "vscode-languageclient": "^9.0.1"
     },
     "devDependencies": {
         "@tsconfig/strictest": "^2.0.1",
         "@types/node": "~16.11.7",
-        "@types/vscode": "~1.78.1",
+        "@types/vscode": "~1.83",
         "@typescript-eslint/eslint-plugin": "^6.0.0",
         "@typescript-eslint/parser": "^6.0.0",
         "@vscode/test-electron": "^2.3.8",
@@ -490,15 +490,19 @@
                         "type": "string",
                         "enum": [
                             "auto",
+                            "llvm-vs-code-extensions.lldb-dap",
                             "vadimcn.vscode-lldb",
-                            "ms-vscode.cpptools"
+                            "ms-vscode.cpptools",
+                            "webfreak.debug"
                         ],
                         "default": "auto",
                         "description": "Preferred debug engine.",
                         "markdownEnumDescriptions": [
-                            "First try to use [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb), if it's not installed try to use [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools).",
+                            "Use the first available extension out of [LLDB DAP](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.lldb-dap), [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb), [C/C++ for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools), and [Native Debug](https://marketplace.visualstudio.com/items?itemName=webfreak.debug).",
+                            "Use [LLDB DAP](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.lldb-dap)",
                             "Use [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)",
-                            "Use [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)"
+                            "Use [C/C++ for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)",
+                            "Use [Native Debug](https://marketplace.visualstudio.com/items?itemName=webfreak.debug)"
                         ]
                     },
                     "rust-analyzer.debug.sourceFileMap": {
diff --git a/src/tools/rust-analyzer/editors/code/src/client.ts b/src/tools/rust-analyzer/editors/code/src/client.ts
index bf58112916b..eac7b849fdb 100644
--- a/src/tools/rust-analyzer/editors/code/src/client.ts
+++ b/src/tools/rust-analyzer/editors/code/src/client.ts
@@ -350,6 +350,7 @@ class ExperimentalFeatures implements lc.StaticFeature {
         _documentSelector: lc.DocumentSelector | undefined,
     ): void {}
     dispose(): void {}
+    clear(): void {}
 }
 
 class OverrideFeatures implements lc.StaticFeature {
@@ -369,6 +370,7 @@ class OverrideFeatures implements lc.StaticFeature {
         _documentSelector: lc.DocumentSelector | undefined,
     ): void {}
     dispose(): void {}
+    clear(): void {}
 }
 
 function isCodeActionWithoutEditsAndCommands(value: any): boolean {
diff --git a/src/tools/rust-analyzer/triagebot.toml b/src/tools/rust-analyzer/triagebot.toml
index d62adb9144b..1138035d0e8 100644
--- a/src/tools/rust-analyzer/triagebot.toml
+++ b/src/tools/rust-analyzer/triagebot.toml
@@ -19,3 +19,5 @@ exclude_titles = [ # exclude syncs from subtree in rust-lang/rust
     "sync from rust",
 ]
 labels = ["has-merge-commits", "S-waiting-on-author"]
+
+[transfer]
diff --git a/src/tools/rustbook/.gitignore b/src/tools/rustbook/.gitignore
new file mode 100644
index 00000000000..ea8c4bf7f35
--- /dev/null
+++ b/src/tools/rustbook/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index 27ccb205b50..9e549348da3 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -47,9 +47,9 @@ dependencies = [
 
 [[package]]
 name = "anstream"
-version = "0.6.15"
+version = "0.6.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
+checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338"
 dependencies = [
  "anstyle",
  "anstyle-parse",
@@ -62,43 +62,43 @@ dependencies = [
 
 [[package]]
 name = "anstyle"
-version = "1.0.8"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
 
 [[package]]
 name = "anstyle-parse"
-version = "0.2.5"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
 dependencies = [
  "utf8parse",
 ]
 
 [[package]]
 name = "anstyle-query"
-version = "1.1.1"
+version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
 dependencies = [
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "anstyle-wincon"
-version = "3.0.4"
+version = "3.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
+checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
 dependencies = [
  "anstyle",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "anyhow"
-version = "1.0.89"
+version = "1.0.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
+checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13"
 
 [[package]]
 name = "autocfg"
@@ -161,9 +161,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
 [[package]]
 name = "cc"
-version = "1.1.22"
+version = "1.1.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"
+checksum = "67b9470d453346108f93a59222a9a1a5724db32d0a4727b7ab7ace4b4d822dc9"
 dependencies = [
  "shlex",
 ]
@@ -185,14 +185,14 @@ dependencies = [
  "js-sys",
  "num-traits",
  "wasm-bindgen",
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
 name = "clap"
-version = "4.5.18"
+version = "4.5.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3"
+checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -200,9 +200,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.5.18"
+version = "4.5.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b"
+checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
 dependencies = [
  "anstream",
  "anstyle",
@@ -213,9 +213,9 @@ dependencies = [
 
 [[package]]
 name = "clap_complete"
-version = "4.5.29"
+version = "4.5.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8937760c3f4c60871870b8c3ee5f9b30771f792a7045c48bcbba999d7d6b3b8e"
+checksum = "86bc73de94bc81e52f3bebec71bc4463e9748f7a59166663e32044669577b0e2"
 dependencies = [
  "clap",
 ]
@@ -240,9 +240,9 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
 
 [[package]]
 name = "colorchoice"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
 
 [[package]]
 name = "core-foundation-sys"
@@ -441,11 +441,12 @@ dependencies = [
 
 [[package]]
 name = "handlebars"
-version = "5.1.2"
+version = "6.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b"
+checksum = "fd4ccde012831f9a071a637b0d4e31df31c0f6c525784b35ae76a9ac6bc1e315"
 dependencies = [
  "log",
+ "num-order",
  "pest",
  "pest_derive",
  "serde",
@@ -455,9 +456,9 @@ dependencies = [
 
 [[package]]
 name = "hashbrown"
-version = "0.14.5"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
 
 [[package]]
 name = "heck"
@@ -535,9 +536,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.5.0"
+version = "2.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
+checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
 dependencies = [
  "equivalent",
  "hashbrown",
@@ -557,9 +558,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
 
 [[package]]
 name = "js-sys"
-version = "0.3.70"
+version = "0.3.72"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
+checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
 dependencies = [
  "wasm-bindgen",
 ]
@@ -572,9 +573,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
 
 [[package]]
 name = "libc"
-version = "0.2.159"
+version = "0.2.161"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
+checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
 
 [[package]]
 name = "libdbus-sys"
@@ -645,9 +646,9 @@ dependencies = [
 
 [[package]]
 name = "mdbook"
-version = "0.4.40"
+version = "0.4.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b45a38e19bd200220ef07c892b0157ad3d2365e5b5a267ca01ad12182491eea5"
+checksum = "7624879735513024d323e7267a0b3a7176aceb0db537939beb4ee31d9e8945e3"
 dependencies = [
  "ammonia",
  "anyhow",
@@ -763,6 +764,21 @@ dependencies = [
 ]
 
 [[package]]
+name = "num-modular"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f"
+
+[[package]]
+name = "num-order"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6"
+dependencies = [
+ "num-modular",
+]
+
+[[package]]
 name = "num-traits"
 version = "0.2.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -773,9 +789,9 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.19.0"
+version = "1.20.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
 
 [[package]]
 name = "onig"
@@ -831,14 +847,14 @@ dependencies = [
  "libc",
  "redox_syscall",
  "smallvec",
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
 name = "pathdiff"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
+checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361"
 
 [[package]]
 name = "percent-encoding"
@@ -848,9 +864,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
 
 [[package]]
 name = "pest"
-version = "2.7.13"
+version = "2.7.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9"
+checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442"
 dependencies = [
  "memchr",
  "thiserror",
@@ -859,9 +875,9 @@ dependencies = [
 
 [[package]]
 name = "pest_derive"
-version = "2.7.13"
+version = "2.7.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d3a6e3394ec80feb3b6393c725571754c6188490265c61aaf260810d6b95aa0"
+checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd"
 dependencies = [
  "pest",
  "pest_generator",
@@ -869,9 +885,9 @@ dependencies = [
 
 [[package]]
 name = "pest_generator"
-version = "2.7.13"
+version = "2.7.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94429506bde1ca69d1b5601962c73f4172ab4726571a59ea95931218cb0e930e"
+checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e"
 dependencies = [
  "pest",
  "pest_meta",
@@ -882,9 +898,9 @@ dependencies = [
 
 [[package]]
 name = "pest_meta"
-version = "2.7.13"
+version = "2.7.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac8a071862e93690b6e34e9a5fb8e33ff3734473ac0245b27232222c4906a33f"
+checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d"
 dependencies = [
  "once_cell",
  "pest",
@@ -980,9 +996,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.86"
+version = "1.0.89"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
+checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
 dependencies = [
  "unicode-ident",
 ]
@@ -1083,18 +1099,18 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.5.6"
+version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b"
+checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
 dependencies = [
  "bitflags 2.6.0",
 ]
 
 [[package]]
 name = "regex"
-version = "1.10.6"
+version = "1.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -1104,9 +1120,9 @@ dependencies = [
 
 [[package]]
 name = "regex-automata"
-version = "0.4.7"
+version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
+checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -1115,9 +1131,9 @@ dependencies = [
 
 [[package]]
 name = "regex-syntax"
-version = "0.8.4"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
 
 [[package]]
 name = "rustbook"
@@ -1134,9 +1150,9 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.38.37"
+version = "0.38.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
+checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a"
 dependencies = [
  "bitflags 2.6.0",
  "errno",
@@ -1174,18 +1190,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
 
 [[package]]
 name = "serde"
-version = "1.0.210"
+version = "1.0.214"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
+checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.210"
+version = "1.0.214"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
+checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1194,9 +1210,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.128"
+version = "1.0.132"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
+checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
 dependencies = [
  "itoa",
  "memchr",
@@ -1276,9 +1292,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
 
 [[package]]
 name = "syn"
-version = "2.0.79"
+version = "2.0.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
+checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1331,12 +1347,12 @@ dependencies = [
 
 [[package]]
 name = "terminal_size"
-version = "0.3.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
+checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef"
 dependencies = [
  "rustix",
- "windows-sys 0.48.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
@@ -1347,18 +1363,18 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
 
 [[package]]
 name = "thiserror"
-version = "1.0.64"
+version = "1.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
+checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.64"
+version = "1.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
+checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1437,24 +1453,21 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
 
 [[package]]
 name = "ucd-trie"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
+checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
 
 [[package]]
 name = "unicase"
-version = "2.7.0"
+version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
-dependencies = [
- "version_check",
-]
+checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df"
 
 [[package]]
 name = "unicode-bidi"
-version = "0.3.15"
+version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893"
 
 [[package]]
 name = "unicode-ident"
@@ -1524,9 +1537,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.93"
+version = "0.2.95"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
+checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
 dependencies = [
  "cfg-if",
  "once_cell",
@@ -1535,9 +1548,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.93"
+version = "0.2.95"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
+checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
 dependencies = [
  "bumpalo",
  "log",
@@ -1550,9 +1563,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.93"
+version = "0.2.95"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
+checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -1560,9 +1573,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.93"
+version = "0.2.95"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
+checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1573,9 +1586,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.93"
+version = "0.2.95"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
+checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
 
 [[package]]
 name = "winapi"
@@ -1614,16 +1627,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
 dependencies = [
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
-dependencies = [
- "windows-targets 0.48.5",
+ "windows-targets",
 ]
 
 [[package]]
@@ -1632,7 +1636,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
 dependencies = [
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
@@ -1641,22 +1645,7 @@ version = "0.59.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
 dependencies = [
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
-dependencies = [
- "windows_aarch64_gnullvm 0.48.5",
- "windows_aarch64_msvc 0.48.5",
- "windows_i686_gnu 0.48.5",
- "windows_i686_msvc 0.48.5",
- "windows_x86_64_gnu 0.48.5",
- "windows_x86_64_gnullvm 0.48.5",
- "windows_x86_64_msvc 0.48.5",
+ "windows-targets",
 ]
 
 [[package]]
@@ -1665,48 +1654,30 @@ version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
 dependencies = [
- "windows_aarch64_gnullvm 0.52.6",
- "windows_aarch64_msvc 0.52.6",
- "windows_i686_gnu 0.52.6",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
  "windows_i686_gnullvm",
- "windows_i686_msvc 0.52.6",
- "windows_x86_64_gnu 0.52.6",
- "windows_x86_64_gnullvm 0.52.6",
- "windows_x86_64_msvc 0.52.6",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
 ]
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
-
-[[package]]
-name = "windows_aarch64_gnullvm"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
-
-[[package]]
-name = "windows_aarch64_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
-
-[[package]]
-name = "windows_i686_gnu"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
@@ -1719,48 +1690,24 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
-
-[[package]]
-name = "windows_i686_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
-
-[[package]]
-name = "windows_x86_64_gnu"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
-
-[[package]]
-name = "windows_x86_64_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
diff --git a/src/tools/rustdoc-gui-test/Cargo.toml b/src/tools/rustdoc-gui-test/Cargo.toml
index 4cb200ebc7c..f7384a98f85 100644
--- a/src/tools/rustdoc-gui-test/Cargo.toml
+++ b/src/tools/rustdoc-gui-test/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.1.0"
 edition = "2021"
 
 [dependencies]
-build_helper = { path = "../build_helper" }
+build_helper = { path = "../../build_helper" }
 compiletest = { path = "../compiletest" }
 getopts = "0.2"
 walkdir = "2"
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index e162ba033cc..7aa5e102e6d 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -2,6 +2,14 @@
 const fs = require("fs");
 const path = require("path");
 
+
+function arrayToCode(array) {
+    return array.map((value, index) => {
+        value = value.split("&nbsp;").join(" ");
+        return (index % 2 === 1) ? ("`" + value + "`") : value;
+    }).join("");
+}
+
 function loadContent(content) {
     const Module = module.constructor;
     const m = new Module();
@@ -84,7 +92,6 @@ function checkNeededFields(fullPath, expected, error_text, queryName, position)
     if (fullPath.length === 0) {
         fieldsToCheck = [
             "foundElems",
-            "original",
             "returned",
             "userQuery",
             "error",
@@ -181,15 +188,7 @@ function valueCheck(fullPath, expected, result, error_text, queryName) {
                 if (!result_v.forEach) {
                     throw result_v;
                 }
-                result_v.forEach((value, index) => {
-                    value = value.split("&nbsp;").join(" ");
-                    if (index % 2 === 1) {
-                        result_v[index] = "`" + value + "`";
-                    } else {
-                        result_v[index] = value;
-                    }
-                });
-                result_v = result_v.join("");
+                result_v = arrayToCode(result_v);
             }
             const obj_path = fullPath + (fullPath.length > 0 ? "." : "") + key;
             valueCheck(obj_path, expected[key], result_v, error_text, queryName);
@@ -437,9 +436,41 @@ function loadSearchJS(doc_folder, resource_suffix) {
     searchModule.initSearch(searchIndex.searchIndex);
     const docSearch = searchModule.docSearch;
     return {
-        doSearch: function(queryStr, filterCrate, currentCrate) {
-            return docSearch.execQuery(searchModule.parseQuery(queryStr),
+        doSearch: async function(queryStr, filterCrate, currentCrate) {
+            const result = await docSearch.execQuery(searchModule.parseQuery(queryStr),
                 filterCrate, currentCrate);
+            for (const tab in result) {
+                if (!Object.prototype.hasOwnProperty.call(result, tab)) {
+                    continue;
+                }
+                if (!(result[tab] instanceof Array)) {
+                    continue;
+                }
+                for (const entry of result[tab]) {
+                    for (const key in entry) {
+                        if (!Object.prototype.hasOwnProperty.call(entry, key)) {
+                            continue;
+                        }
+                        if (key === "displayTypeSignature") {
+                            const {type, mappedNames, whereClause} =
+                                await entry.displayTypeSignature;
+                            entry.displayType = arrayToCode(type);
+                            entry.displayMappedNames = [...mappedNames.entries()]
+                                .map(([name, qname]) => {
+                                    return `${name} = ${qname}`;
+                                }).join(", ");
+                            entry.displayWhereClause = [...whereClause.entries()]
+                                .flatMap(([name, value]) => {
+                                    if (value.length === 0) {
+                                        return [];
+                                    }
+                                    return [`${name}: ${arrayToCode(value)}`];
+                                }).join(", ");
+                        }
+                    }
+                }
+            }
+            return result;
         },
         getCorrections: function(queryStr, filterCrate, currentCrate) {
             const parsedQuery = searchModule.parseQuery(queryStr);
diff --git a/src/tools/suggest-tests/Cargo.toml b/src/tools/suggest-tests/Cargo.toml
index 7c048d53a50..d6f86078d7e 100644
--- a/src/tools/suggest-tests/Cargo.toml
+++ b/src/tools/suggest-tests/Cargo.toml
@@ -5,4 +5,4 @@ edition = "2021"
 
 [dependencies]
 glob = "0.3.0"
-build_helper = { version = "0.1.0", path = "../build_helper" }
+build_helper = { version = "0.1.0", path = "../../build_helper" }
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index 42e608ff5ce..bc75787fb1a 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
 autobins = false
 
 [dependencies]
-build_helper = { path = "../build_helper" }
+build_helper = { path = "../../build_helper" }
 cargo_metadata = "0.18"
 regex = "1"
 miropt-test-tools = { path = "../miropt-test-tools" }
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 8e12db409ec..e065f01ebba 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -24,6 +24,7 @@ const LICENSES: &[&str] = &[
     "BSD-2-Clause OR Apache-2.0 OR MIT",                   // zerocopy
     "ISC",
     "MIT / Apache-2.0",
+    "MIT AND (MIT OR Apache-2.0)",
     "MIT AND Apache-2.0 WITH LLVM-exception AND (MIT OR Apache-2.0)", // compiler-builtins
     "MIT OR Apache-2.0 OR LGPL-2.1-or-later",              // r-efi, r-efi-alloc
     "MIT OR Apache-2.0 OR Zlib",                           // tinyvec_macros
@@ -92,6 +93,7 @@ const EXCEPTIONS: ExceptionList = &[
     ("constant_time_eq", "CC0-1.0 OR MIT-0 OR Apache-2.0"),  // rustc
     ("dissimilar", "Apache-2.0"),                            // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps)
     ("fluent-langneg", "Apache-2.0"),                        // rustc (fluent translations)
+    ("foldhash", "Zlib"),                                    // rustc
     ("instant", "BSD-3-Clause"),                             // rustc_driver/tracing-subscriber/parking_lot
     ("mdbook", "MPL-2.0"),                                   // mdbook
     ("option-ext", "MPL-2.0"),                               // cargo-miri (via `directories`)
@@ -283,6 +285,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "fluent-langneg",
     "fluent-syntax",
     "fnv",
+    "foldhash",
     "generic-array",
     "getopts",
     "getrandom",
diff --git a/src/tools/tidy/src/known_bug.rs b/src/tools/tidy/src/known_bug.rs
index 182a81c6ec9..a8771654144 100644
--- a/src/tools/tidy/src/known_bug.rs
+++ b/src/tools/tidy/src/known_bug.rs
@@ -6,8 +6,22 @@ use crate::walk::*;
 
 pub fn check(filepath: &Path, bad: &mut bool) {
     walk(filepath, |path, _is_dir| filter_not_rust(path), &mut |entry, contents| {
-        let file = entry.path();
-        if !contents.lines().any(|line| line.starts_with("//@ known-bug: ")) {
+        let file: &Path = entry.path();
+
+        // files in "auxiliary" do not need to crash by themselves
+        let test_path_segments =
+            file.iter().map(|s| s.to_string_lossy().into()).collect::<Vec<String>>();
+        let test_path_segments_str =
+            test_path_segments.iter().map(|s| s.as_str()).collect::<Vec<&str>>();
+
+        if !matches!(test_path_segments_str[..], [
+            ..,
+            "tests",
+            "crashes",
+            "auxiliary",
+            _aux_file_rs
+        ]) && !contents.lines().any(|line| line.starts_with("//@ known-bug: "))
+        {
             tidy_error!(
                 bad,
                 "{} crash/ice test does not have a \"//@ known-bug: \" directive",
diff --git a/src/tools/unicode-table-generator/src/range_search.rs b/src/tools/unicode-table-generator/src/range_search.rs
index 9a51979a2f0..14da876eda7 100644
--- a/src/tools/unicode-table-generator/src/range_search.rs
+++ b/src/tools/unicode-table-generator/src/range_search.rs
@@ -1,4 +1,5 @@
 #[inline(always)]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))]
 const fn bitset_search<
     const N: usize,
     const CHUNK_SIZE: usize,
diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs
index 46010692fe5..dd064c59283 100644
--- a/src/tools/unicode-table-generator/src/raw_emitter.rs
+++ b/src/tools/unicode-table-generator/src/raw_emitter.rs
@@ -97,6 +97,10 @@ impl RawEmitter {
 
         self.blank_line();
 
+        writeln!(
+            &mut self.file,
+            r#"#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))]"#
+        ).unwrap();
         writeln!(&mut self.file, "pub const fn lookup(c: char) -> bool {{").unwrap();
         if first_code_point > 0x7f {
             writeln!(&mut self.file, "    (c as u32) >= {first_code_point:#04x} &&").unwrap();