about summary refs log tree commit diff
path: root/src/tools
diff options
context:
space:
mode:
authorLaurențiu Nicola <lnicola@users.noreply.github.com>2025-05-01 07:33:30 +0000
committerGitHub <noreply@github.com>2025-05-01 07:33:30 +0000
commit00d2f60efd516bc7ea658bd0a6de5e2f1f1df322 (patch)
tree9375885343e27ab26b20dfe5a3714e00d5d378d0 /src/tools
parente7502210ce5ab2d92cb87c372dab51b637ba6df4 (diff)
parent1c5de64814d72effc6890ca823fa4d248041a0bd (diff)
downloadrust-00d2f60efd516bc7ea658bd0a6de5e2f1f1df322.tar.gz
rust-00d2f60efd516bc7ea658bd0a6de5e2f1f1df322.zip
Merge pull request #19726 from lnicola/sync-from-rust
Sync from downstream again
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs5
-rw-r--r--src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr2
-rw-r--r--src/tools/compiletest/src/common.rs8
-rw-r--r--src/tools/compiletest/src/errors.rs35
-rw-r--r--src/tools/compiletest/src/executor.rs1
-rw-r--r--src/tools/compiletest/src/executor/libtest.rs111
-rw-r--r--src/tools/compiletest/src/header.rs2
-rw-r--r--src/tools/compiletest/src/json.rs8
-rw-r--r--src/tools/compiletest/src/lib.rs19
-rw-r--r--src/tools/compiletest/src/runtest.rs22
-rw-r--r--src/tools/compiletest/src/runtest/ui.rs6
-rw-r--r--src/tools/miri/.github/workflows/ci.yml72
-rw-r--r--src/tools/miri/README.md2
-rw-r--r--src/tools/miri/bench-cargo-miri/mse/src/main.rs2
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/alloc_addresses/mod.rs111
-rw-r--r--src/tools/miri/src/bin/miri.rs4
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs15
-rw-r--r--src/tools/miri/src/concurrency/data_race.rs2
-rw-r--r--src/tools/miri/src/helpers.rs2
-rw-r--r--src/tools/miri/src/intrinsics/mod.rs27
-rw-r--r--src/tools/miri/src/machine.rs15
-rw-r--r--src/tools/miri/src/math.rs26
-rw-r--r--src/tools/miri/src/shims/time.rs33
-rw-r--r--src/tools/miri/src/shims/unix/foreign_items.rs433
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs17
-rw-r--r--src/tools/miri/src/shims/windows/foreign_items.rs5
-rw-r--r--src/tools/miri/src/shims/windows/fs.rs19
-rw-r--r--src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs9
-rw-r--r--src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs9
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs6
-rw-r--r--src/tools/miri/tests/fail/no_main.stderr2
-rw-r--r--src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs2
-rw-r--r--src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr4
-rw-r--r--src/tools/miri/tests/pass-dep/shims/windows-fs.rs25
-rw-r--r--src/tools/miri/tests/pass/async-drop.rs107
-rw-r--r--src/tools/miri/tests/pass/async-drop.stack.stdout37
-rw-r--r--src/tools/miri/tests/pass/async-drop.tree.stdout37
-rw-r--r--src/tools/miri/tests/pass/dst-raw.rs2
-rw-r--r--src/tools/miri/tests/pass/float.rs119
-rw-r--r--src/tools/miri/tests/pass/shims/fs.rs2
-rw-r--r--src/tools/miri/tests/pass/slices.rs3
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/interior_mutability.rs2
-rw-r--r--src/tools/miri/tests/pass/tree_borrows/interior_mutability.rs178
-rw-r--r--src/tools/rust-analyzer/Cargo.lock12
-rw-r--r--src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/rust-version2
-rw-r--r--src/tools/rustfmt/src/pairs.rs14
-rw-r--r--src/tools/rustfmt/src/types.rs13
-rw-r--r--src/tools/rustfmt/tests/source/let_chains.rs10
-rw-r--r--src/tools/rustfmt/tests/target/let_chains.rs8
-rw-r--r--src/tools/tidy/src/issues.txt1
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
77 files changed, 1079 insertions, 671 deletions
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 7da5a530eaa..5edb5c23570 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -853,7 +853,7 @@ impl TyCoercionStability {
                     continue;
                 },
                 ty::Param(_) if for_return => Self::Deref,
-                ty::Alias(ty::Weak | ty::Inherent, _) => unreachable!("should have been normalized away above"),
+                ty::Alias(ty::Free | ty::Inherent, _) => unreachable!("should have been normalized away above"),
                 ty::Alias(ty::Projection, _) if !for_return && ty.has_non_region_param() => Self::Reborrow,
                 ty::Infer(_)
                 | ty::Error(_)
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
index 67537a251da..1f142bc3ba6 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -197,7 +197,7 @@ fn fn_inputs_has_impl_trait_ty(cx: &LateContext<'_>, def_id: LocalDefId) -> bool
     inputs.iter().any(|input| {
         matches!(
             input.kind(),
-            ty::Alias(ty::AliasTyKind::Weak, alias_ty) if cx.tcx.type_of(alias_ty.def_id).skip_binder().is_impl_trait()
+            ty::Alias(ty::AliasTyKind::Free, alias_ty) if cx.tcx.type_of(alias_ty.def_id).skip_binder().is_impl_trait()
         )
     })
 }
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index fe1fd70a9fa..17368a7530d 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -1117,6 +1117,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 self.hash_const_arg(s);
                 self.hash_const_arg(e);
             },
+            TyPatKind::Or(variants) => {
+                for variant in variants.iter() {
+                    self.hash_ty_pat(variant)
+                }
+            },
             TyPatKind::Err(_) => {},
         }
     }
diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
index bdac1e42309..ad3c420270c 100644
--- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
+++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
@@ -236,7 +236,7 @@ LL |     if result.is_ok() {
 LL |         result.as_mut().unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: creating a shared reference to mutable static is discouraged
+error: creating a shared reference to mutable static
   --> tests/ui/checked_unwrap/simple_conditionals.rs:183:12
    |
 LL |         if X.is_some() {
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index e0132056d6c..4f93b498741 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -413,14 +413,6 @@ pub struct Config {
     /// cross-compilation scenarios that do not otherwise want/need to `-Zbuild-std`. Used in e.g.
     /// ABI tests.
     pub minicore_path: Utf8PathBuf,
-
-    /// If true, disable the "new" executor, and use the older libtest-based
-    /// executor to run tests instead. This is a temporary fallback, to make
-    /// manual comparative testing easier if bugs are found in the new executor.
-    ///
-    /// FIXME(Zalathar): Eventually remove this flag and remove the libtest
-    /// dependency.
-    pub no_new_executor: bool,
 }
 
 impl Config {
diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs
index 3bb98276bf5..a45f39b036c 100644
--- a/src/tools/compiletest/src/errors.rs
+++ b/src/tools/compiletest/src/errors.rs
@@ -30,24 +30,20 @@ impl ErrorKind {
 
     /// Either the canonical uppercase string, or some additional versions for compatibility.
     /// FIXME: consider keeping only the canonical versions here.
-    fn from_user_str(s: &str) -> Option<ErrorKind> {
-        Some(match s {
+    pub fn from_user_str(s: &str) -> ErrorKind {
+        match s {
             "HELP" | "help" => ErrorKind::Help,
             "ERROR" | "error" => ErrorKind::Error,
-            "NOTE" | "note" => ErrorKind::Note,
+            // `MONO_ITEM` makes annotations in `codegen-units` tests syntactically correct,
+            // but those tests never use the error kind later on.
+            "NOTE" | "note" | "MONO_ITEM" => ErrorKind::Note,
             "SUGGESTION" => ErrorKind::Suggestion,
             "WARN" | "WARNING" | "warn" | "warning" => ErrorKind::Warning,
-            _ => return None,
-        })
-    }
-
-    pub fn expect_from_user_str(s: &str) -> ErrorKind {
-        ErrorKind::from_user_str(s).unwrap_or_else(|| {
-            panic!(
+            _ => panic!(
                 "unexpected diagnostic kind `{s}`, expected \
                  `ERROR`, `WARN`, `NOTE`, `HELP` or `SUGGESTION`"
-            )
-        })
+            ),
+        }
     }
 }
 
@@ -67,8 +63,7 @@ impl fmt::Display for ErrorKind {
 pub struct Error {
     pub line_num: Option<usize>,
     /// What kind of message we expect (e.g., warning, error, suggestion).
-    /// `None` if not specified or unknown message kind.
-    pub kind: Option<ErrorKind>,
+    pub kind: ErrorKind,
     pub msg: String,
     /// For some `Error`s, like secondary lines of multi-line diagnostics, line annotations
     /// are not mandatory, even if they would otherwise be mandatory for primary errors.
@@ -79,12 +74,7 @@ pub struct Error {
 impl Error {
     pub fn render_for_expected(&self) -> String {
         use colored::Colorize;
-        format!(
-            "{: <10}line {: >3}: {}",
-            self.kind.map(|kind| kind.to_string()).unwrap_or_default(),
-            self.line_num_str(),
-            self.msg.cyan(),
-        )
+        format!("{: <10}line {: >3}: {}", self.kind, self.line_num_str(), self.msg.cyan())
     }
 
     pub fn line_num_str(&self) -> String {
@@ -173,9 +163,10 @@ fn parse_expected(
     // Get the part of the comment after the sigil (e.g. `~^^` or ~|).
     let tag = captures.get(0).unwrap();
     let rest = line[tag.end()..].trim_start();
-    let (kind_str, _) = rest.split_once(|c: char| !c.is_ascii_alphabetic()).unwrap_or((rest, ""));
+    let (kind_str, _) =
+        rest.split_once(|c: char| c != '_' && !c.is_ascii_alphabetic()).unwrap_or((rest, ""));
     let kind = ErrorKind::from_user_str(kind_str);
-    let untrimmed_msg = if kind.is_some() { &rest[kind_str.len()..] } else { rest };
+    let untrimmed_msg = &rest[kind_str.len()..];
     let msg = untrimmed_msg.strip_prefix(':').unwrap_or(untrimmed_msg).trim().to_owned();
 
     let line_num_adjust = &captures["adjust"];
diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs
index 990be56ce0c..e774c5e2047 100644
--- a/src/tools/compiletest/src/executor.rs
+++ b/src/tools/compiletest/src/executor.rs
@@ -12,7 +12,6 @@ use crate::common::{Config, TestPaths};
 
 mod deadline;
 mod json;
-pub(crate) mod libtest;
 
 pub(crate) fn run_tests(config: &Config, tests: Vec<CollectedTest>) -> bool {
     let tests_len = tests.len();
diff --git a/src/tools/compiletest/src/executor/libtest.rs b/src/tools/compiletest/src/executor/libtest.rs
deleted file mode 100644
index 032b3f4fa9a..00000000000
--- a/src/tools/compiletest/src/executor/libtest.rs
+++ /dev/null
@@ -1,111 +0,0 @@
-//! This submodule encapsulates all of the code that actually interacts with
-//! libtest, so that it can be easily removed after the new executor becomes
-//! the default.
-
-use std::borrow::Cow;
-use std::io;
-
-use crate::common::Config;
-use crate::executor::{CollectedTest, CollectedTestDesc, ColorConfig, OutputFormat, ShouldPanic};
-
-/// Delegates to libtest to run the list of collected tests.
-///
-/// Returns `Ok(true)` if all tests passed, or `Ok(false)` if one or more tests failed.
-pub(crate) fn execute_tests(config: &Config, tests: Vec<CollectedTest>) -> io::Result<bool> {
-    let opts = test_opts(config);
-    let tests = tests.into_iter().map(|t| t.into_libtest()).collect::<Vec<_>>();
-
-    test::run_tests_console(&opts, tests)
-}
-
-impl CollectedTest {
-    fn into_libtest(self) -> test::TestDescAndFn {
-        let Self { desc, config, testpaths, revision } = self;
-        let CollectedTestDesc { name, ignore, ignore_message, should_panic } = desc;
-
-        // Libtest requires the ignore message to be a &'static str, so we might
-        // have to leak memory to create it. This is fine, as we only do so once
-        // per test, so the leak won't grow indefinitely.
-        let ignore_message = ignore_message.map(|msg| match msg {
-            Cow::Borrowed(s) => s,
-            Cow::Owned(s) => &*String::leak(s),
-        });
-
-        let desc = test::TestDesc {
-            name: test::DynTestName(name),
-            ignore,
-            ignore_message,
-            source_file: "",
-            start_line: 0,
-            start_col: 0,
-            end_line: 0,
-            end_col: 0,
-            should_panic: should_panic.to_libtest(),
-            compile_fail: false,
-            no_run: false,
-            test_type: test::TestType::Unknown,
-        };
-
-        // This closure is invoked when libtest returns control to compiletest
-        // to execute the test.
-        let testfn = test::DynTestFn(Box::new(move || {
-            crate::runtest::run(config, &testpaths, revision.as_deref());
-            Ok(())
-        }));
-
-        test::TestDescAndFn { desc, testfn }
-    }
-}
-
-impl ColorConfig {
-    fn to_libtest(self) -> test::ColorConfig {
-        match self {
-            Self::AutoColor => test::ColorConfig::AutoColor,
-            Self::AlwaysColor => test::ColorConfig::AlwaysColor,
-            Self::NeverColor => test::ColorConfig::NeverColor,
-        }
-    }
-}
-
-impl OutputFormat {
-    fn to_libtest(self) -> test::OutputFormat {
-        match self {
-            Self::Pretty => test::OutputFormat::Pretty,
-            Self::Terse => test::OutputFormat::Terse,
-            Self::Json => test::OutputFormat::Json,
-        }
-    }
-}
-
-impl ShouldPanic {
-    fn to_libtest(self) -> test::ShouldPanic {
-        match self {
-            Self::No => test::ShouldPanic::No,
-            Self::Yes => test::ShouldPanic::Yes,
-        }
-    }
-}
-
-fn test_opts(config: &Config) -> test::TestOpts {
-    test::TestOpts {
-        exclude_should_panic: false,
-        filters: config.filters.clone(),
-        filter_exact: config.filter_exact,
-        run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No },
-        format: config.format.to_libtest(),
-        logfile: None,
-        run_tests: true,
-        bench_benchmarks: true,
-        nocapture: config.nocapture,
-        color: config.color.to_libtest(),
-        shuffle: false,
-        shuffle_seed: None,
-        test_threads: None,
-        skip: config.skip.clone(),
-        list: false,
-        options: test::Options::new(),
-        time_options: None,
-        force_run_in_process: false,
-        fail_fast: config.fail_fast,
-    }
-}
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 2b203bb309c..8bee9caacc9 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -593,7 +593,7 @@ impl TestProps {
                         config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS)
                     {
                         self.dont_require_annotations
-                            .insert(ErrorKind::expect_from_user_str(err_kind.trim()));
+                            .insert(ErrorKind::from_user_str(err_kind.trim()));
                     }
                 },
             );
diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs
index 62fe538ee32..960f5ba5888 100644
--- a/src/tools/compiletest/src/json.rs
+++ b/src/tools/compiletest/src/json.rs
@@ -229,7 +229,7 @@ fn push_actual_errors(
     // Convert multi-line messages into multiple errors.
     // We expect to replace these with something more structured anyhow.
     let mut message_lines = diagnostic.message.lines();
-    let kind = Some(ErrorKind::from_compiler_str(&diagnostic.level));
+    let kind = ErrorKind::from_compiler_str(&diagnostic.level);
     let first_line = message_lines.next().unwrap_or(&diagnostic.message);
     if primary_spans.is_empty() {
         static RE: OnceLock<Regex> = OnceLock::new();
@@ -278,7 +278,7 @@ fn push_actual_errors(
             for (index, line) in suggested_replacement.lines().enumerate() {
                 errors.push(Error {
                     line_num: Some(span.line_start + index),
-                    kind: Some(ErrorKind::Suggestion),
+                    kind: ErrorKind::Suggestion,
                     msg: line.to_string(),
                     require_annotation: true,
                 });
@@ -297,7 +297,7 @@ fn push_actual_errors(
     for span in spans_in_this_file.iter().filter(|span| span.label.is_some()) {
         errors.push(Error {
             line_num: Some(span.line_start),
-            kind: Some(ErrorKind::Note),
+            kind: ErrorKind::Note,
             msg: span.label.clone().unwrap(),
             require_annotation: true,
         });
@@ -317,7 +317,7 @@ fn push_backtrace(
     if Path::new(&expansion.span.file_name) == Path::new(&file_name) {
         errors.push(Error {
             line_num: Some(expansion.span.line_start),
-            kind: Some(ErrorKind::Note),
+            kind: ErrorKind::Note,
             msg: format!("in this expansion of {}", expansion.macro_decl_name),
             require_annotation: true,
         });
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 788bafaa724..0db4d3f6a41 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -1,11 +1,10 @@
 #![crate_name = "compiletest"]
-// Needed by the libtest-based test executor.
-#![feature(test)]
 // Needed by the "new" test executor that does not depend on libtest.
+// FIXME(Zalathar): We should be able to get rid of `internal_output_capture`,
+// by having `runtest` manually capture all of its println-like output instead.
+// That would result in compiletest being written entirely in stable Rust!
 #![feature(internal_output_capture)]
 
-extern crate test;
-
 #[cfg(test)]
 mod tests;
 
@@ -448,8 +447,6 @@ pub fn parse_config(args: Vec<String>) -> Config {
         diff_command: matches.opt_str("compiletest-diff-tool"),
 
         minicore_path: opt_path(matches, "minicore-path"),
-
-        no_new_executor: matches.opt_present("no-new-executor"),
     }
 }
 
@@ -576,12 +573,10 @@ pub fn run_tests(config: Arc<Config>) {
     // Delegate to the executor to filter and run the big list of test structures
     // created during test discovery. When the executor decides to run a test,
     // it will return control to the rest of compiletest by calling `runtest::run`.
-    let res = if !config.no_new_executor {
-        Ok(executor::run_tests(&config, tests))
-    } else {
-        // FIXME(Zalathar): Eventually remove the libtest executor entirely.
-        crate::executor::libtest::execute_tests(&config, tests)
-    };
+    // FIXME(Zalathar): Once we're confident that we won't need to revert the
+    // removal of the libtest-based executor, remove this Result and other
+    // remnants of the old executor.
+    let res: io::Result<bool> = Ok(executor::run_tests(&config, tests));
 
     // Check the outcome reported by libtest.
     match res {
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index fe23cce81e9..97cb82c9e36 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -675,9 +675,7 @@ impl<'test> TestCx<'test> {
             "check_expected_errors: expected_errors={:?} proc_res.status={:?}",
             expected_errors, proc_res.status
         );
-        if proc_res.status.success()
-            && expected_errors.iter().any(|x| x.kind == Some(ErrorKind::Error))
-        {
+        if proc_res.status.success() && expected_errors.iter().any(|x| x.kind == ErrorKind::Error) {
             self.fatal_proc_rec("process did not return an error status", proc_res);
         }
 
@@ -709,7 +707,7 @@ impl<'test> TestCx<'test> {
         // if one of them actually occurs in the test.
         let expected_kinds: HashSet<_> = [ErrorKind::Error, ErrorKind::Warning]
             .into_iter()
-            .chain(expected_errors.iter().filter_map(|e| e.kind))
+            .chain(expected_errors.iter().map(|e| e.kind))
             .collect();
 
         // Parse the JSON output from the compiler and extract out the messages.
@@ -723,8 +721,7 @@ impl<'test> TestCx<'test> {
                 expected_errors.iter().enumerate().position(|(index, expected_error)| {
                     !found[index]
                         && actual_error.line_num == expected_error.line_num
-                        && (expected_error.kind.is_none()
-                            || actual_error.kind == expected_error.kind)
+                        && actual_error.kind == expected_error.kind
                         && actual_error.msg.contains(&expected_error.msg)
                 });
 
@@ -737,19 +734,14 @@ impl<'test> TestCx<'test> {
 
                 None => {
                     if actual_error.require_annotation
-                        && actual_error.kind.map_or(false, |kind| {
-                            expected_kinds.contains(&kind)
-                                && !self.props.dont_require_annotations.contains(&kind)
-                        })
+                        && expected_kinds.contains(&actual_error.kind)
+                        && !self.props.dont_require_annotations.contains(&actual_error.kind)
                     {
                         self.error(&format!(
                             "{}:{}: unexpected {}: '{}'",
                             file_name,
                             actual_error.line_num_str(),
-                            actual_error
-                                .kind
-                                .as_ref()
-                                .map_or(String::from("message"), |k| k.to_string()),
+                            actual_error.kind,
                             actual_error.msg
                         ));
                         unexpected.push(actual_error);
@@ -766,7 +758,7 @@ impl<'test> TestCx<'test> {
                     "{}:{}: expected {} not found: {}",
                     file_name,
                     expected_error.line_num_str(),
-                    expected_error.kind.as_ref().map_or("message".into(), |k| k.to_string()),
+                    expected_error.kind,
                     expected_error.msg
                 ));
                 not_found.push(expected_error);
diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs
index e87b037cd28..cf0ae14f81b 100644
--- a/src/tools/compiletest/src/runtest/ui.rs
+++ b/src/tools/compiletest/src/runtest/ui.rs
@@ -6,8 +6,8 @@ use rustfix::{Filter, apply_suggestions, get_suggestions_from_json};
 use tracing::debug;
 
 use super::{
-    AllowUnused, Emit, ErrorKind, FailMode, LinkToAux, PassMode, TargetLocation, TestCx,
-    TestOutput, Truncated, UI_FIXED, WillExecute,
+    AllowUnused, Emit, FailMode, LinkToAux, PassMode, TargetLocation, TestCx, TestOutput,
+    Truncated, UI_FIXED, WillExecute,
 };
 use crate::{errors, json};
 
@@ -176,7 +176,7 @@ impl TestCx<'_> {
             let msg = format!(
                 "line {}: cannot combine `--error-format` with {} annotations; use `error-pattern` instead",
                 expected_errors[0].line_num_str(),
-                expected_errors[0].kind.unwrap_or(ErrorKind::Error),
+                expected_errors[0].kind,
             );
             self.fatal(&msg);
         }
diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml
index 59bae513a58..9dbf51e9796 100644
--- a/src/tools/miri/.github/workflows/ci.yml
+++ b/src/tools/miri/.github/workflows/ci.yml
@@ -89,41 +89,16 @@ jobs:
             # Check if all jobs that we depend on (in the needs array) were successful.
             jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'
 
-  cron-fail-notify:
-    name: cronjob failure notification
+  cron-rustc-pull:
+    name: automatic pull from rustc
     runs-on: ubuntu-latest
     permissions:
         # The cronjob needs to be able to push to the repo...
         contents: write
         # ... and create a PR.
         pull-requests: write
-    needs: [build, style, coverage]
-    if: ${{ github.event_name == 'schedule' && failure() }}
+    if: ${{ github.event_name == 'schedule' }}
     steps:
-      # Send a Zulip notification
-      - name: Install zulip-send
-        run: pip3 install zulip
-      - name: Send Zulip notification
-        env:
-          ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }}
-          ZULIP_API_TOKEN: ${{ secrets.ZULIP_API_TOKEN }}
-        run: |
-          ~/.local/bin/zulip-send --user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com \
-            --stream miri --subject "Miri Build Failure ($(date -u +%Y-%m))" \
-            --message 'Dear @*T-miri*,
-
-          It would appear that the [Miri cron job build]('"https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"') failed.
-
-          This likely means that rustc changed the miri directory and
-          we now need to do a [`./miri rustc-pull`](https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.md#importing-changes-from-the-rustc-repo).
-
-          Would you mind investigating this issue?
-
-          Thanks in advance!
-          Sincerely,
-          The Miri Cronjobs Bot'
-
-      # Attempt to auto-sync with rustc
       - uses: actions/checkout@v4
         with:
           fetch-depth: 256 # get a bit more of the history
@@ -143,18 +118,45 @@ jobs:
         run: |
           ./miri toolchain
           ./miri fmt --check || (./miri fmt && git commit -am "fmt")
-      - name: Push changes to a branch
+      - name: Push changes to a branch and create PR
         run: |
+          # `git diff --exit-code` "succeeds" if the diff is empty.
+          if git diff --exit-code HEAD^; then echo "Nothing changed in rustc, skipping PR"; exit 0; fi
+          # The diff is non-empty, create a PR.
           BRANCH="rustup-$(date -u +%Y-%m-%d)"
           git switch -c $BRANCH
           git push -u origin $BRANCH
-      - name: Create Pull Request
-        run: |
-          PR=$(gh pr create -B master --title 'Automatic Rustup' --body 'Please close and re-open this PR to trigger CI, then enable auto-merge.')
-          ~/.local/bin/zulip-send --user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com \
-            --stream miri --subject "Miri Build Failure ($(date -u +%Y-%m))" \
-            --message "A PR doing a rustc-pull [has been automatically created]($PR) for your convenience."
+          gh pr create -B master --title 'Automatic Rustup' --body 'Please close and re-open this PR to trigger CI, then enable auto-merge.'
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
           ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }}
           ZULIP_API_TOKEN: ${{ secrets.ZULIP_API_TOKEN }}
+
+  cron-fail-notify:
+    name: cronjob failure notification
+    runs-on: ubuntu-latest
+    needs: [build, style, coverage]
+    if: ${{ github.event_name == 'schedule' && failure() }}
+    steps:
+      # Send a Zulip notification
+      - name: Install zulip-send
+        run: pip3 install zulip
+      - name: Send Zulip notification
+        env:
+          ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }}
+          ZULIP_API_TOKEN: ${{ secrets.ZULIP_API_TOKEN }}
+        run: |
+          ~/.local/bin/zulip-send --user $ZULIP_BOT_EMAIL --api-key $ZULIP_API_TOKEN --site https://rust-lang.zulipchat.com \
+            --stream miri --subject "Miri Build Failure ($(date -u +%Y-%m))" \
+            --message 'Dear @*T-miri*,
+
+          It would appear that the [Miri cron job build]('"https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"') failed.
+
+          This likely means that rustc changed the miri directory and
+          we now need to do a [`./miri rustc-pull`](https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.md#importing-changes-from-the-rustc-repo).
+
+          Would you mind investigating this issue?
+
+          Thanks in advance!
+          Sincerely,
+          The Miri Cronjobs Bot'
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index e8ea988558c..95e1770aa7b 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -489,7 +489,7 @@ Miri knows where it is supposed to start execution:
 
 ```rust
 #[cfg(miri)]
-#[no_mangle]
+#[unsafe(no_mangle)]
 fn miri_start(argc: isize, argv: *const *const u8) -> isize {
     // Call the actual start function that your project implements, based on your target's conventions.
 }
diff --git a/src/tools/miri/bench-cargo-miri/mse/src/main.rs b/src/tools/miri/bench-cargo-miri/mse/src/main.rs
index 06d5487d1d4..69c7c39cdd7 100644
--- a/src/tools/miri/bench-cargo-miri/mse/src/main.rs
+++ b/src/tools/miri/bench-cargo-miri/mse/src/main.rs
@@ -13,7 +13,7 @@ fn read_i16(buffer: &[u8], index: usize) -> i16 {
     const SIZE: usize = size_of::<i16>();
     let mut bytes: [u8; SIZE] = [0u8; SIZE];
     bytes.copy_from_slice(&buffer[(index * SIZE)..(index * SIZE + SIZE)]);
-    unsafe { std::mem::transmute(bytes) }
+    i16::from_ne_bytes(bytes)
 }
 
 fn mse(samples: usize, frame_buf: &[i16], buf_ref: &[u8]) -> f64 {
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index d1107e51509..59d53891217 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-1bc56185ee257ed829a0aea7abdc3b03c5fed887
+1b8ab72680f36e783af84c1a3c4f8508572bd9f9
diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs
index c263e86c082..335e8d76999 100644
--- a/src/tools/miri/src/alloc_addresses/mod.rs
+++ b/src/tools/miri/src/alloc_addresses/mod.rs
@@ -107,47 +107,6 @@ fn align_addr(addr: u64, align: u64) -> u64 {
 
 impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
 trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
-    // Returns the exposed `AllocId` that corresponds to the specified addr,
-    // or `None` if the addr is out of bounds
-    fn alloc_id_from_addr(&self, addr: u64, size: i64) -> Option<AllocId> {
-        let this = self.eval_context_ref();
-        let global_state = this.machine.alloc_addresses.borrow();
-        assert!(global_state.provenance_mode != ProvenanceMode::Strict);
-
-        // We always search the allocation to the right of this address. So if the size is structly
-        // negative, we have to search for `addr-1` instead.
-        let addr = if size >= 0 { addr } else { addr.saturating_sub(1) };
-        let pos = global_state.int_to_ptr_map.binary_search_by_key(&addr, |(addr, _)| *addr);
-
-        // Determine the in-bounds provenance for this pointer.
-        let alloc_id = match pos {
-            Ok(pos) => Some(global_state.int_to_ptr_map[pos].1),
-            Err(0) => None,
-            Err(pos) => {
-                // This is the largest of the addresses smaller than `int`,
-                // i.e. the greatest lower bound (glb)
-                let (glb, alloc_id) = global_state.int_to_ptr_map[pos - 1];
-                // This never overflows because `addr >= glb`
-                let offset = addr - glb;
-                // We require this to be strict in-bounds of the allocation. This arm is only
-                // entered for addresses that are not the base address, so even zero-sized
-                // allocations will get recognized at their base address -- but all other
-                // allocations will *not* be recognized at their "end" address.
-                let size = this.get_alloc_info(alloc_id).size;
-                if offset < size.bytes() { Some(alloc_id) } else { None }
-            }
-        }?;
-
-        // We only use this provenance if it has been exposed.
-        if global_state.exposed.contains(&alloc_id) {
-            // This must still be live, since we remove allocations from `int_to_ptr_map` when they get freed.
-            debug_assert!(this.is_alloc_live(alloc_id));
-            Some(alloc_id)
-        } else {
-            None
-        }
-    }
-
     fn addr_from_alloc_id_uncached(
         &self,
         global_state: &mut GlobalStateInner,
@@ -242,11 +201,65 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
             interp_ok(base_addr)
         }
     }
+}
 
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
+    // Returns the `AllocId` that corresponds to the specified addr,
+    // or `None` if the addr is out of bounds.
+    // Setting `only_exposed_allocations` selects whether only exposed allocations are considered.
+    fn alloc_id_from_addr(
+        &self,
+        addr: u64,
+        size: i64,
+        only_exposed_allocations: bool,
+    ) -> Option<AllocId> {
+        let this = self.eval_context_ref();
+        let global_state = this.machine.alloc_addresses.borrow();
+        assert!(global_state.provenance_mode != ProvenanceMode::Strict);
+
+        // We always search the allocation to the right of this address. So if the size is strictly
+        // negative, we have to search for `addr-1` instead.
+        let addr = if size >= 0 { addr } else { addr.saturating_sub(1) };
+        let pos = global_state.int_to_ptr_map.binary_search_by_key(&addr, |(addr, _)| *addr);
+
+        // Determine the in-bounds provenance for this pointer.
+        let alloc_id = match pos {
+            Ok(pos) => Some(global_state.int_to_ptr_map[pos].1),
+            Err(0) => None,
+            Err(pos) => {
+                // This is the largest of the addresses smaller than `int`,
+                // i.e. the greatest lower bound (glb)
+                let (glb, alloc_id) = global_state.int_to_ptr_map[pos - 1];
+                // This never overflows because `addr >= glb`
+                let offset = addr - glb;
+                // We require this to be strict in-bounds of the allocation. This arm is only
+                // entered for addresses that are not the base address, so even zero-sized
+                // allocations will get recognized at their base address -- but all other
+                // allocations will *not* be recognized at their "end" address.
+                let size = this.get_alloc_info(alloc_id).size;
+                if offset < size.bytes() { Some(alloc_id) } else { None }
+            }
+        }?;
+
+        // We only use this provenance if it has been exposed, or if the caller requested also non-exposed allocations
+        if !only_exposed_allocations || global_state.exposed.contains(&alloc_id) {
+            // This must still be live, since we remove allocations from `int_to_ptr_map` when they get freed.
+            debug_assert!(this.is_alloc_live(alloc_id));
+            Some(alloc_id)
+        } else {
+            None
+        }
+    }
+
+    /// Returns the base address of an allocation, or an error if no base address could be found
+    ///
+    /// # Panics
+    /// If `memory_kind = None` and the `alloc_id` is not cached, meaning that the first call to this function per `alloc_id` must get the `memory_kind`.
     fn addr_from_alloc_id(
         &self,
         alloc_id: AllocId,
-        memory_kind: MemoryKind,
+        memory_kind: Option<MemoryKind>,
     ) -> InterpResult<'tcx, u64> {
         let this = self.eval_context_ref();
         let mut global_state = this.machine.alloc_addresses.borrow_mut();
@@ -256,8 +269,10 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
             Some(&addr) => interp_ok(addr),
             None => {
                 // First time we're looking for the absolute address of this allocation.
+                let memory_kind =
+                    memory_kind.expect("memory_kind is required since alloc_id is not cached");
                 let base_addr =
-                    self.addr_from_alloc_id_uncached(global_state, alloc_id, memory_kind)?;
+                    this.addr_from_alloc_id_uncached(global_state, alloc_id, memory_kind)?;
                 trace!("Assigning base address {:#x} to allocation {:?}", base_addr, alloc_id);
 
                 // Store address in cache.
@@ -283,10 +298,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
         }
     }
-}
 
-impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
-pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn expose_provenance(&self, provenance: Provenance) -> InterpResult<'tcx> {
         let this = self.eval_context_ref();
         let mut global_state = this.machine.alloc_addresses.borrow_mut();
@@ -365,7 +377,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         let alloc_id = prov.alloc_id();
 
         // Get a pointer to the beginning of this allocation.
-        let base_addr = this.addr_from_alloc_id(alloc_id, kind)?;
+        let base_addr = this.addr_from_alloc_id(alloc_id, Some(kind))?;
         let base_ptr = interpret::Pointer::new(
             Provenance::Concrete { alloc_id, tag },
             Size::from_bytes(base_addr),
@@ -388,7 +400,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             // In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`.
             // This additional call ensures that some `MiriAllocBytes` are always prepared, just in case
             // this function gets called before the first time `addr_from_alloc_id` gets called.
-            this.addr_from_alloc_id(id, MiriMemoryKind::Global.into())?;
+            this.addr_from_alloc_id(id, Some(MiriMemoryKind::Global.into()))?;
             // The memory we need here will have already been allocated during an earlier call to
             // `addr_from_alloc_id` for this allocation. So don't create a new `MiriAllocBytes` here, instead
             // fetch the previously prepared bytes from `prepared_alloc_bytes`.
@@ -423,7 +435,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             alloc_id
         } else {
             // A wildcard pointer.
-            this.alloc_id_from_addr(addr.bytes(), size)?
+            let only_exposed_allocations = true;
+            this.alloc_id_from_addr(addr.bytes(), size, only_exposed_allocations)?
         };
 
         // This cannot fail: since we already have a pointer with that provenance, adjust_alloc_root_pointer
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 4e8fe0ca8ad..8ff1c9d6ff0 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -106,7 +106,7 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) {
         } else {
             tcx.dcx().fatal(
                 "`miri_start` must have the following signature:\n\
-                        fn miri_start(argc: isize, argv: *const *const u8) -> isize",
+                fn miri_start(argc: isize, argv: *const *const u8) -> isize",
             );
         }
     } else {
@@ -115,7 +115,7 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) {
             Alternatively, you can export a `miri_start` function:\n\
             \n\
             #[cfg(miri)]\n\
-            #[no_mangle]\n\
+            #[unsafe(no_mangle)]\n\
             fn miri_start(argc: isize, argv: *const *const u8) -> isize {\
             \n    // Call the actual start function that your project implements, based on your target's conventions.\n\
             }"
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs
index a429940748c..dbfa9807e3b 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs
@@ -61,8 +61,7 @@ fn all_read_accesses_commute() {
                 // ... and produce the same final result.
                 assert_eq!(
                     loc12, loc21,
-                    "Read accesses {:?} followed by {:?} do not commute !",
-                    rel1, rel2
+                    "Read accesses {rel1:?} followed by {rel2:?} do not commute !"
                 );
             }
         }
@@ -674,8 +673,8 @@ mod spurious_read {
         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             let (x, y) = self.retag_permissions();
             write!(f, "{}; ", self.xy_rel)?;
-            write!(f, "y: ({}); ", y,)?;
-            write!(f, "retag x ({}); ", x)?;
+            write!(f, "y: ({y}); ")?;
+            write!(f, "retag x ({x}); ")?;
 
             write!(f, "<arbitrary code>; <spurious read x>;")?;
             Ok(())
@@ -730,17 +729,17 @@ mod spurious_read {
                         // protector.
                         final_source
                             .distinguishable::</*X*/ AllowRet, /*Y*/ AllowRet>(&final_target)
-                            .then_some(format!("{}", final_target))
+                            .then_some(format!("{final_target}"))
                     } else {
                         Some(format!("UB"))
                     }
                 };
                 if let Some(final_target) = distinguishable {
                     eprintln!(
-                        "For pattern '{}', inserting a spurious read through x makes the final state '{}' instead of '{}' which is observable",
-                        pat, final_target, final_source
+                        "For pattern '{pat}', inserting a spurious read through x makes the final state '{final_target}' \
+                        instead of '{final_source}' which is observable"
                     );
-                    eprintln!("  (arbitrary code instanciated with '{}')", opaque);
+                    eprintln!("  (arbitrary code instanciated with '{opaque}')");
                     err += 1;
                     // We found an instanciation of the opaque code that makes this Pattern
                     // fail, we don't really need to check the rest.
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index 923031dbbd1..847c6823475 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -381,7 +381,7 @@ impl AccessType {
         });
 
         if let Some(ty) = ty {
-            msg.push_str(&format!(" of type `{}`", ty));
+            msg.push_str(&format!(" of type `{ty}`"));
         }
 
         msg
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 1af3d1abc64..a3aa8bbbfb3 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -1017,7 +1017,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     /// Check that the given `caller_fn_abi` matches the expected ABI described by
-    /// `callee_abi`, `callee_input_tys`, `callee_output_ty`, and the return the list of
+    /// `callee_abi`, `callee_input_tys`, `callee_output_ty`, and then returns the list of
     /// arguments.
     fn check_shim_abi<'a, const N: usize>(
         &mut self,
diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs
index 7d60a7e5c48..3334c0b5edf 100644
--- a/src/tools/miri/src/intrinsics/mod.rs
+++ b/src/tools/miri/src/intrinsics/mod.rs
@@ -7,13 +7,13 @@ use rand::Rng;
 use rustc_abi::Size;
 use rustc_apfloat::{Float, Round};
 use rustc_middle::mir;
-use rustc_middle::ty::{self, FloatTy, ScalarInt};
+use rustc_middle::ty::{self, FloatTy};
 use rustc_span::{Symbol, sym};
 
 use self::atomic::EvalContextExt as _;
 use self::helpers::{ToHost, ToSoft, check_intrinsic_arg_count};
 use self::simd::EvalContextExt as _;
-use crate::math::apply_random_float_error_ulp;
+use crate::math::apply_random_float_error_to_imm;
 use crate::*;
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
@@ -473,26 +473,3 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         interp_ok(EmulateItemResult::NeedsReturn)
     }
 }
-
-/// Applies a random 16ULP floating point error to `val` and returns the new value.
-/// Will fail if `val` is not a floating point number.
-fn apply_random_float_error_to_imm<'tcx>(
-    ecx: &mut MiriInterpCx<'tcx>,
-    val: ImmTy<'tcx>,
-    ulp_exponent: u32,
-) -> InterpResult<'tcx, ImmTy<'tcx>> {
-    let scalar = val.to_scalar_int()?;
-    let res: ScalarInt = match val.layout.ty.kind() {
-        ty::Float(FloatTy::F16) =>
-            apply_random_float_error_ulp(ecx, scalar.to_f16(), ulp_exponent).into(),
-        ty::Float(FloatTy::F32) =>
-            apply_random_float_error_ulp(ecx, scalar.to_f32(), ulp_exponent).into(),
-        ty::Float(FloatTy::F64) =>
-            apply_random_float_error_ulp(ecx, scalar.to_f64(), ulp_exponent).into(),
-        ty::Float(FloatTy::F128) =>
-            apply_random_float_error_ulp(ecx, scalar.to_f128(), ulp_exponent).into(),
-        _ => bug!("intrinsic called with non-float input type"),
-    };
-
-    interp_ok(ImmTy::from_scalar_int(res, val.layout))
-}
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index ea59d327be8..55aa3d6fa68 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -721,9 +721,8 @@ impl<'tcx> MiriMachine<'tcx> {
                 // Check if host target == the session target.
                 if host_triple != target_triple {
                     panic!(
-                        "calling external C functions in linked .so file requires host and target to be the same: host={}, target={}",
-                        host_triple,
-                        target_triple,
+                        "calling native C functions in linked .so file requires host and target to be the same: \
+                        host={host_triple}, target={target_triple}",
                     );
                 }
                 // Note: it is the user's responsibility to provide a correct SO file.
@@ -1200,6 +1199,16 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
     }
 
     #[inline(always)]
+    fn apply_float_nondet(
+        ecx: &mut InterpCx<'tcx, Self>,
+        val: ImmTy<'tcx>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx>> {
+        crate::math::apply_random_float_error_to_imm(
+            ecx, val, 2 /* log2(4) */
+        )
+    }
+
+    #[inline(always)]
     fn equal_float_min_max<F: Float>(ecx: &MiriInterpCx<'tcx>, a: F, b: F) -> F {
         ecx.equal_float_min_max(a, b)
     }
diff --git a/src/tools/miri/src/math.rs b/src/tools/miri/src/math.rs
index fdd021f8539..2ff29c7ac1a 100644
--- a/src/tools/miri/src/math.rs
+++ b/src/tools/miri/src/math.rs
@@ -1,6 +1,9 @@
 use rand::Rng as _;
 use rustc_apfloat::Float as _;
 use rustc_apfloat::ieee::IeeeFloat;
+use rustc_middle::ty::{self, FloatTy, ScalarInt};
+
+use crate::*;
 
 /// Disturbes a floating-point result by a relative error in the range (-2^scale, 2^scale).
 ///
@@ -43,6 +46,29 @@ pub(crate) fn apply_random_float_error_ulp<F: rustc_apfloat::Float>(
     apply_random_float_error(ecx, val, err_scale)
 }
 
+/// Applies a random 16ULP floating point error to `val` and returns the new value.
+/// Will fail if `val` is not a floating point number.
+pub(crate) fn apply_random_float_error_to_imm<'tcx>(
+    ecx: &mut MiriInterpCx<'tcx>,
+    val: ImmTy<'tcx>,
+    ulp_exponent: u32,
+) -> InterpResult<'tcx, ImmTy<'tcx>> {
+    let scalar = val.to_scalar_int()?;
+    let res: ScalarInt = match val.layout.ty.kind() {
+        ty::Float(FloatTy::F16) =>
+            apply_random_float_error_ulp(ecx, scalar.to_f16(), ulp_exponent).into(),
+        ty::Float(FloatTy::F32) =>
+            apply_random_float_error_ulp(ecx, scalar.to_f32(), ulp_exponent).into(),
+        ty::Float(FloatTy::F64) =>
+            apply_random_float_error_ulp(ecx, scalar.to_f64(), ulp_exponent).into(),
+        ty::Float(FloatTy::F128) =>
+            apply_random_float_error_ulp(ecx, scalar.to_f128(), ulp_exponent).into(),
+        _ => bug!("intrinsic called with non-float input type"),
+    };
+
+    interp_ok(ImmTy::from_scalar_int(res, val.layout))
+}
+
 pub(crate) fn sqrt<S: rustc_apfloat::ieee::Semantics>(x: IeeeFloat<S>) -> IeeeFloat<S> {
     match x.category() {
         // preserve zero sign
diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs
index fb80a36af9f..28f4ca5bb1b 100644
--- a/src/tools/miri/src/shims/time.rs
+++ b/src/tools/miri/src/shims/time.rs
@@ -21,7 +21,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         clk_id_op: &OpTy<'tcx>,
         tp_op: &OpTy<'tcx>,
-    ) -> InterpResult<'tcx, Scalar> {
+        dest: &MPlaceTy<'tcx>,
+    ) -> InterpResult<'tcx> {
         // This clock support is deliberately minimal because a lot of clock types have fiddly
         // properties (is it possible for Miri to be suspended independently of the host?). If you
         // have a use for another clock type, please open an issue.
@@ -29,8 +30,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         let this = self.eval_context_mut();
 
         this.assert_target_os_is_unix("clock_gettime");
+        let clockid_t_size = this.libc_ty_layout("clockid_t").size;
 
-        let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
+        let clk_id = this.read_scalar(clk_id_op)?.to_int(clockid_t_size)?;
         let tp = this.deref_pointer_as(tp_op, this.libc_ty_layout("timespec"))?;
 
         let absolute_clocks;
@@ -43,34 +45,34 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 // Linux further distinguishes regular and "coarse" clocks, but the "coarse" version
                 // is just specified to be "faster and less precise", so we implement both the same way.
                 absolute_clocks = vec![
-                    this.eval_libc_i32("CLOCK_REALTIME"),
-                    this.eval_libc_i32("CLOCK_REALTIME_COARSE"),
+                    this.eval_libc("CLOCK_REALTIME").to_int(clockid_t_size)?,
+                    this.eval_libc("CLOCK_REALTIME_COARSE").to_int(clockid_t_size)?,
                 ];
                 // The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are
                 // never allowed to go backwards. We don't need to do any additional monotonicity
                 // enforcement because std::time::Instant already guarantees that it is monotonic.
                 relative_clocks = vec![
-                    this.eval_libc_i32("CLOCK_MONOTONIC"),
-                    this.eval_libc_i32("CLOCK_MONOTONIC_COARSE"),
+                    this.eval_libc("CLOCK_MONOTONIC").to_int(clockid_t_size)?,
+                    this.eval_libc("CLOCK_MONOTONIC_COARSE").to_int(clockid_t_size)?,
                 ];
             }
             "macos" => {
-                absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")];
-                relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")];
+                absolute_clocks = vec![this.eval_libc("CLOCK_REALTIME").to_int(clockid_t_size)?];
+                relative_clocks = vec![this.eval_libc("CLOCK_MONOTONIC").to_int(clockid_t_size)?];
                 // `CLOCK_UPTIME_RAW` supposed to not increment while the system is asleep... but
                 // that's not really something a program running inside Miri can tell, anyway.
                 // We need to support it because std uses it.
-                relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW"));
+                relative_clocks.push(this.eval_libc("CLOCK_UPTIME_RAW").to_int(clockid_t_size)?);
             }
             "solaris" | "illumos" => {
                 // The REALTIME clock returns the actual time since the Unix epoch.
-                absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")];
+                absolute_clocks = vec![this.eval_libc("CLOCK_REALTIME").to_int(clockid_t_size)?];
                 // MONOTONIC, in the other hand, is the high resolution, non-adjustable
                 // clock from an arbitrary time in the past.
                 // Note that the man page mentions HIGHRES but it is just
                 // an alias of MONOTONIC and the libc crate does not expose it anyway.
                 // https://docs.oracle.com/cd/E23824_01/html/821-1465/clock-gettime-3c.html
-                relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")];
+                relative_clocks = vec![this.eval_libc("CLOCK_MONOTONIC").to_int(clockid_t_size)?];
             }
             target => throw_unsup_format!("`clock_gettime` is not supported on target OS {target}"),
         }
@@ -81,15 +83,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         } else if relative_clocks.contains(&clk_id) {
             this.machine.monotonic_clock.now().duration_since(this.machine.monotonic_clock.epoch())
         } else {
-            return this.set_last_error_and_return_i32(LibcError("EINVAL"));
+            return this.set_last_error_and_return(LibcError("EINVAL"), dest);
         };
 
         let tv_sec = duration.as_secs();
         let tv_nsec = duration.subsec_nanos();
 
         this.write_int_fields(&[tv_sec.into(), tv_nsec.into()], &tp)?;
+        this.write_int(0, dest)?;
 
-        interp_ok(Scalar::from_i32(0))
+        interp_ok(())
     }
 
     fn gettimeofday(
@@ -188,10 +191,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 tm_zone.push('+');
             }
             let offset_hour = offset_in_seconds.abs() / 3600;
-            write!(tm_zone, "{:02}", offset_hour).unwrap();
+            write!(tm_zone, "{offset_hour:02}").unwrap();
             let offset_min = (offset_in_seconds.abs() % 3600) / 60;
             if offset_min != 0 {
-                write!(tm_zone, "{:02}", offset_min).unwrap();
+                write!(tm_zone, "{offset_min:02}").unwrap();
             }
 
             // Add null terminator for C string compatibility.
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index 5e6259c3574..026aa1f9503 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -112,51 +112,122 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         match link_name.as_str() {
             // Environment related shims
             "getenv" => {
-                let [name] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [name] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.const_raw_ptr.ty],
+                    this.machine.layouts.mut_raw_ptr.ty,
+                    args,
+                )?;
                 let result = this.getenv(name)?;
                 this.write_pointer(result, dest)?;
             }
             "unsetenv" => {
-                let [name] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [name] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.const_raw_ptr.ty],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let result = this.unsetenv(name)?;
                 this.write_scalar(result, dest)?;
             }
             "setenv" => {
-                let [name, value, overwrite] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [name, value, overwrite] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [
+                        this.machine.layouts.const_raw_ptr.ty,
+                        this.machine.layouts.const_raw_ptr.ty,
+                        this.tcx.types.i32,
+                    ],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 this.read_scalar(overwrite)?.to_i32()?;
                 let result = this.setenv(name, value)?;
                 this.write_scalar(result, dest)?;
             }
             "getcwd" => {
-                let [buf, size] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [buf, size] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.mut_raw_ptr.ty, this.tcx.types.usize],
+                    this.machine.layouts.mut_raw_ptr.ty,
+                    args,
+                )?;
                 let result = this.getcwd(buf, size)?;
                 this.write_pointer(result, dest)?;
             }
             "chdir" => {
-                let [path] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [path] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.const_raw_ptr.ty],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let result = this.chdir(path)?;
                 this.write_scalar(result, dest)?;
             }
             "getpid" => {
-                let [] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [],
+                    this.libc_ty_layout("pid_t").ty,
+                    args,
+                )?;
                 let result = this.getpid()?;
                 this.write_scalar(result, dest)?;
             }
             "sysconf" => {
-                let [val] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [val] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.tcx.types.i32],
+                    this.tcx.types.isize,
+                    args,
+                )?;
                 let result = this.sysconf(val)?;
                 this.write_scalar(result, dest)?;
             }
             // File descriptors
             "read" => {
-                let [fd, buf, count] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [fd, buf, count] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.tcx.types.i32, this.machine.layouts.mut_raw_ptr.ty, this.tcx.types.usize],
+                    this.tcx.types.isize,
+                    args,
+                )?;
                 let fd = this.read_scalar(fd)?.to_i32()?;
                 let buf = this.read_pointer(buf)?;
                 let count = this.read_target_usize(count)?;
                 this.read(fd, buf, count, None, dest)?;
             }
             "write" => {
-                let [fd, buf, n] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [fd, buf, n] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [
+                        this.tcx.types.i32,
+                        this.machine.layouts.const_raw_ptr.ty,
+                        this.tcx.types.usize,
+                    ],
+                    this.tcx.types.isize,
+                    args,
+                )?;
                 let fd = this.read_scalar(fd)?.to_i32()?;
                 let buf = this.read_pointer(buf)?;
                 let count = this.read_target_usize(n)?;
@@ -164,38 +235,88 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write(fd, buf, count, None, dest)?;
             }
             "pread" => {
-                let [fd, buf, count, offset] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let off_t = this.libc_ty_layout("off_t");
+                let [fd, buf, count, offset] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [
+                        this.tcx.types.i32,
+                        this.machine.layouts.mut_raw_ptr.ty,
+                        this.tcx.types.usize,
+                        off_t.ty,
+                    ],
+                    this.tcx.types.isize,
+                    args,
+                )?;
                 let fd = this.read_scalar(fd)?.to_i32()?;
                 let buf = this.read_pointer(buf)?;
                 let count = this.read_target_usize(count)?;
-                let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
+                let offset = this.read_scalar(offset)?.to_int(off_t.size)?;
                 this.read(fd, buf, count, Some(offset), dest)?;
             }
             "pwrite" => {
-                let [fd, buf, n, offset] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let off_t = this.libc_ty_layout("off_t");
+                let [fd, buf, n, offset] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [
+                        this.tcx.types.i32,
+                        this.machine.layouts.const_raw_ptr.ty,
+                        this.tcx.types.usize,
+                        off_t.ty,
+                    ],
+                    this.tcx.types.isize,
+                    args,
+                )?;
                 let fd = this.read_scalar(fd)?.to_i32()?;
                 let buf = this.read_pointer(buf)?;
                 let count = this.read_target_usize(n)?;
-                let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
+                let offset = this.read_scalar(offset)?.to_int(off_t.size)?;
                 trace!("Called pwrite({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset);
                 this.write(fd, buf, count, Some(offset), dest)?;
             }
             "pread64" => {
-                let [fd, buf, count, offset] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let off64_t = this.libc_ty_layout("off64_t");
+                let [fd, buf, count, offset] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [
+                        this.tcx.types.i32,
+                        this.machine.layouts.mut_raw_ptr.ty,
+                        this.tcx.types.usize,
+                        off64_t.ty,
+                    ],
+                    this.tcx.types.isize,
+                    args,
+                )?;
                 let fd = this.read_scalar(fd)?.to_i32()?;
                 let buf = this.read_pointer(buf)?;
                 let count = this.read_target_usize(count)?;
-                let offset =
-                    this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?;
+                let offset = this.read_scalar(offset)?.to_int(off64_t.size)?;
                 this.read(fd, buf, count, Some(offset), dest)?;
             }
             "pwrite64" => {
-                let [fd, buf, n, offset] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let off64_t = this.libc_ty_layout("off64_t");
+                let [fd, buf, n, offset] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [
+                        this.tcx.types.i32,
+                        this.machine.layouts.const_raw_ptr.ty,
+                        this.tcx.types.usize,
+                        off64_t.ty,
+                    ],
+                    this.tcx.types.isize,
+                    args,
+                )?;
                 let fd = this.read_scalar(fd)?.to_i32()?;
                 let buf = this.read_pointer(buf)?;
                 let count = this.read_target_usize(n)?;
-                let offset =
-                    this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?;
+                let offset = this.read_scalar(offset)?.to_int(off64_t.size)?;
                 trace!("Called pwrite64({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset);
                 this.write(fd, buf, count, Some(offset), dest)?;
             }
@@ -218,13 +339,27 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_scalar(result, dest)?;
             }
             "dup" => {
-                let [old_fd] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [old_fd] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.tcx.types.i32],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let old_fd = this.read_scalar(old_fd)?.to_i32()?;
                 let new_fd = this.dup(old_fd)?;
                 this.write_scalar(new_fd, dest)?;
             }
             "dup2" => {
-                let [old_fd, new_fd] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [old_fd, new_fd] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.tcx.types.i32, this.tcx.types.i32],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let old_fd = this.read_scalar(old_fd)?.to_i32()?;
                 let new_fd = this.read_scalar(new_fd)?.to_i32()?;
                 let result = this.dup2(old_fd, new_fd)?;
@@ -233,7 +368,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             "flock" => {
                 // Currently this function does not exist on all Unixes, e.g. on Solaris.
                 this.check_target_os(&["linux", "freebsd", "macos", "illumos"], link_name)?;
-                let [fd, op] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [fd, op] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.tcx.types.i32, this.tcx.types.i32],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let fd = this.read_scalar(fd)?.to_i32()?;
                 let op = this.read_scalar(op)?.to_i32()?;
                 let result = this.flock(fd, op)?;
@@ -250,140 +392,311 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_scalar(result, dest)?;
             }
             "unlink" => {
-                let [path] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [path] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.const_raw_ptr.ty],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let result = this.unlink(path)?;
                 this.write_scalar(result, dest)?;
             }
             "symlink" => {
-                let [target, linkpath] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [target, linkpath] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.const_raw_ptr.ty, this.machine.layouts.const_raw_ptr.ty],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let result = this.symlink(target, linkpath)?;
                 this.write_scalar(result, dest)?;
             }
             "rename" => {
-                let [oldpath, newpath] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [oldpath, newpath] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.const_raw_ptr.ty, this.machine.layouts.const_raw_ptr.ty],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let result = this.rename(oldpath, newpath)?;
                 this.write_scalar(result, dest)?;
             }
             "mkdir" => {
-                let [path, mode] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [path, mode] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.const_raw_ptr.ty, this.libc_ty_layout("mode_t").ty],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let result = this.mkdir(path, mode)?;
                 this.write_scalar(result, dest)?;
             }
             "rmdir" => {
-                let [path] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [path] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.const_raw_ptr.ty],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let result = this.rmdir(path)?;
                 this.write_scalar(result, dest)?;
             }
             "opendir" => {
-                let [name] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [name] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.const_raw_ptr.ty],
+                    this.machine.layouts.mut_raw_ptr.ty,
+                    args,
+                )?;
                 let result = this.opendir(name)?;
                 this.write_scalar(result, dest)?;
             }
             "closedir" => {
-                let [dirp] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [dirp] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.mut_raw_ptr.ty],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let result = this.closedir(dirp)?;
                 this.write_scalar(result, dest)?;
             }
             "lseek64" => {
-                let [fd, offset, whence] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let off64_t = this.libc_ty_layout("off64_t");
+                let [fd, offset, whence] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.tcx.types.i32, off64_t.ty, this.tcx.types.i32],
+                    off64_t.ty,
+                    args,
+                )?;
                 let fd = this.read_scalar(fd)?.to_i32()?;
-                let offset = this.read_scalar(offset)?.to_i64()?;
+                let offset = this.read_scalar(offset)?.to_int(off64_t.size)?;
                 let whence = this.read_scalar(whence)?.to_i32()?;
-                let result = this.lseek64(fd, offset.into(), whence)?;
-                this.write_scalar(result, dest)?;
+                this.lseek64(fd, offset, whence, dest)?;
             }
             "lseek" => {
-                let [fd, offset, whence] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let off_t = this.libc_ty_layout("off_t");
+                let [fd, offset, whence] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.tcx.types.i32, off_t.ty, this.tcx.types.i32],
+                    off_t.ty,
+                    args,
+                )?;
                 let fd = this.read_scalar(fd)?.to_i32()?;
-                let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
+                let offset = this.read_scalar(offset)?.to_int(off_t.size)?;
                 let whence = this.read_scalar(whence)?.to_i32()?;
-                let result = this.lseek64(fd, offset, whence)?;
-                this.write_scalar(result, dest)?;
+                this.lseek64(fd, offset, whence, dest)?;
             }
             "ftruncate64" => {
-                let [fd, length] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let off64_t = this.libc_ty_layout("off64_t");
+                let [fd, length] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.tcx.types.i32, off64_t.ty],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let fd = this.read_scalar(fd)?.to_i32()?;
-                let length = this.read_scalar(length)?.to_i64()?;
-                let result = this.ftruncate64(fd, length.into())?;
+                let length = this.read_scalar(length)?.to_int(off64_t.size)?;
+                let result = this.ftruncate64(fd, length)?;
                 this.write_scalar(result, dest)?;
             }
             "ftruncate" => {
-                let [fd, length] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let off_t = this.libc_ty_layout("off_t");
+                let [fd, length] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.tcx.types.i32, off_t.ty],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let fd = this.read_scalar(fd)?.to_i32()?;
-                let length = this.read_scalar(length)?.to_int(this.libc_ty_layout("off_t").size)?;
+                let length = this.read_scalar(length)?.to_int(off_t.size)?;
                 let result = this.ftruncate64(fd, length)?;
                 this.write_scalar(result, dest)?;
             }
             "fsync" => {
-                let [fd] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [fd] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.tcx.types.i32],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let result = this.fsync(fd)?;
                 this.write_scalar(result, dest)?;
             }
             "fdatasync" => {
-                let [fd] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [fd] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.tcx.types.i32],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let result = this.fdatasync(fd)?;
                 this.write_scalar(result, dest)?;
             }
             "readlink" => {
-                let [pathname, buf, bufsize] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [pathname, buf, bufsize] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [
+                        this.machine.layouts.const_raw_ptr.ty,
+                        this.machine.layouts.mut_raw_ptr.ty,
+                        this.tcx.types.usize,
+                    ],
+                    this.tcx.types.isize,
+                    args,
+                )?;
                 let result = this.readlink(pathname, buf, bufsize)?;
                 this.write_scalar(Scalar::from_target_isize(result, this), dest)?;
             }
             "posix_fadvise" => {
-                let [fd, offset, len, advice] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let off_t = this.libc_ty_layout("off_t");
+                let [fd, offset, len, advice] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.tcx.types.i32, off_t.ty, off_t.ty, this.tcx.types.i32],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 this.read_scalar(fd)?.to_i32()?;
-                this.read_target_isize(offset)?;
-                this.read_target_isize(len)?;
+                this.read_scalar(offset)?.to_int(off_t.size)?;
+                this.read_scalar(len)?.to_int(off_t.size)?;
                 this.read_scalar(advice)?.to_i32()?;
                 // fadvise is only informational, we can ignore it.
                 this.write_null(dest)?;
             }
             "realpath" => {
-                let [path, resolved_path] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [path, resolved_path] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.const_raw_ptr.ty, this.machine.layouts.mut_raw_ptr.ty],
+                    this.machine.layouts.mut_raw_ptr.ty,
+                    args,
+                )?;
                 let result = this.realpath(path, resolved_path)?;
                 this.write_scalar(result, dest)?;
             }
             "mkstemp" => {
-                let [template] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [template] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.mut_raw_ptr.ty],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let result = this.mkstemp(template)?;
                 this.write_scalar(result, dest)?;
             }
 
             // Unnamed sockets and pipes
             "socketpair" => {
-                let [domain, type_, protocol, sv] =
-                    this.check_shim(abi, Conv::C, link_name, args)?;
+                let [domain, type_, protocol, sv] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [
+                        this.tcx.types.i32,
+                        this.tcx.types.i32,
+                        this.tcx.types.i32,
+                        this.machine.layouts.mut_raw_ptr.ty,
+                    ],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let result = this.socketpair(domain, type_, protocol, sv)?;
                 this.write_scalar(result, dest)?;
             }
             "pipe" => {
-                let [pipefd] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [pipefd] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.mut_raw_ptr.ty],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let result = this.pipe2(pipefd, /*flags*/ None)?;
                 this.write_scalar(result, dest)?;
             }
             "pipe2" => {
                 // Currently this function does not exist on all Unixes, e.g. on macOS.
                 this.check_target_os(&["linux", "freebsd", "solaris", "illumos"], link_name)?;
-                let [pipefd, flags] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [pipefd, flags] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.mut_raw_ptr.ty, this.tcx.types.i32],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let result = this.pipe2(pipefd, Some(flags))?;
                 this.write_scalar(result, dest)?;
             }
 
             // Time
             "gettimeofday" => {
-                let [tv, tz] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [tv, tz] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.mut_raw_ptr.ty, this.machine.layouts.mut_raw_ptr.ty],
+                    this.tcx.types.i32,
+                    args,
+                )?;
                 let result = this.gettimeofday(tv, tz)?;
                 this.write_scalar(result, dest)?;
             }
             "localtime_r" => {
-                let [timep, result_op] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let [timep, result_op] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.machine.layouts.const_raw_ptr.ty, this.machine.layouts.mut_raw_ptr.ty],
+                    this.machine.layouts.mut_raw_ptr.ty,
+                    args,
+                )?;
                 let result = this.localtime_r(timep, result_op)?;
                 this.write_pointer(result, dest)?;
             }
             "clock_gettime" => {
-                let [clk_id, tp] = this.check_shim(abi, Conv::C, link_name, args)?;
-                let result = this.clock_gettime(clk_id, tp)?;
-                this.write_scalar(result, dest)?;
+                let [clk_id, tp] = this.check_shim_abi(
+                    link_name,
+                    abi,
+                    ExternAbi::C { unwind: false },
+                    [this.libc_ty_layout("clockid_t").ty, this.machine.layouts.mut_raw_ptr.ty],
+                    this.tcx.types.i32,
+                    args,
+                )?;
+                this.clock_gettime(clk_id, tp, dest)?;
             }
 
             // Allocation
@@ -834,7 +1147,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             // These shims are enabled only when the caller is in the standard library.
             "pthread_attr_getguardsize" if this.frame_in_std() => {
                 let [_attr, guard_size] = this.check_shim(abi, Conv::C, link_name, args)?;
-                let guard_size_layout = this.libc_ty_layout("size_t");
+                let guard_size_layout = this.machine.layouts.usize;
                 let guard_size = this.deref_pointer_as(guard_size, guard_size_layout)?;
                 this.write_scalar(
                     Scalar::from_uint(this.machine.page_size, guard_size_layout.size),
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index fc0f57694a7..1f6acff0787 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -502,7 +502,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         interp_ok(Scalar::from_i32(this.try_unwrap_io_result(fd)?))
     }
 
-    fn lseek64(&mut self, fd_num: i32, offset: i128, whence: i32) -> InterpResult<'tcx, Scalar> {
+    fn lseek64(
+        &mut self,
+        fd_num: i32,
+        offset: i128,
+        whence: i32,
+        dest: &MPlaceTy<'tcx>,
+    ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
         // Isolation check is done via `FileDescription` trait.
@@ -510,7 +516,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         let seek_from = if whence == this.eval_libc_i32("SEEK_SET") {
             if offset < 0 {
                 // Negative offsets return `EINVAL`.
-                return this.set_last_error_and_return_i64(LibcError("EINVAL"));
+                return this.set_last_error_and_return(LibcError("EINVAL"), dest);
             } else {
                 SeekFrom::Start(u64::try_from(offset).unwrap())
             }
@@ -519,19 +525,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         } else if whence == this.eval_libc_i32("SEEK_END") {
             SeekFrom::End(i64::try_from(offset).unwrap())
         } else {
-            return this.set_last_error_and_return_i64(LibcError("EINVAL"));
+            return this.set_last_error_and_return(LibcError("EINVAL"), dest);
         };
 
         let communicate = this.machine.communicate();
 
         let Some(fd) = this.machine.fds.get(fd_num) else {
-            return this.set_last_error_and_return_i64(LibcError("EBADF"));
+            return this.set_last_error_and_return(LibcError("EBADF"), dest);
         };
         let result = fd.seek(communicate, seek_from)?.map(|offset| i64::try_from(offset).unwrap());
         drop(fd);
 
         let result = this.try_unwrap_io_result(result)?;
-        interp_ok(Scalar::from_i64(result))
+        this.write_int(result, dest)?;
+        interp_ok(())
     }
 
     fn unlink(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index 8dcadbed130..c80858c6363 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -317,6 +317,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 let res = this.GetFileInformationByHandle(handle, info)?;
                 this.write_scalar(res, dest)?;
             }
+            "DeleteFileW" => {
+                let [file_name] = this.check_shim(abi, sys_conv, link_name, args)?;
+                let res = this.DeleteFileW(file_name)?;
+                this.write_scalar(res, dest)?;
+            }
 
             // Allocation
             "HeapAlloc" => {
diff --git a/src/tools/miri/src/shims/windows/fs.rs b/src/tools/miri/src/shims/windows/fs.rs
index 32bab548969..7561bf45219 100644
--- a/src/tools/miri/src/shims/windows/fs.rs
+++ b/src/tools/miri/src/shims/windows/fs.rs
@@ -371,6 +371,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
         interp_ok(this.eval_windows("c", "TRUE"))
     }
+
+    fn DeleteFileW(
+        &mut self,
+        file_name: &OpTy<'tcx>, // LPCWSTR
+    ) -> InterpResult<'tcx, Scalar> {
+        // ^ Returns BOOL (i32 on Windows)
+        let this = self.eval_context_mut();
+        this.assert_target_os("windows", "DeleteFileW");
+        this.check_no_isolation("`DeleteFileW`")?;
+
+        let file_name = this.read_path_from_wide_str(this.read_pointer(file_name)?)?;
+        match std::fs::remove_file(file_name) {
+            Ok(_) => interp_ok(this.eval_windows("c", "TRUE")),
+            Err(e) => {
+                this.set_last_error(e)?;
+                interp_ok(this.eval_windows("c", "FALSE"))
+            }
+        }
+    }
 }
 
 /// Windows FILETIME is measured in 100-nanosecs since 1601
diff --git a/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs b/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs
index f73c1b6acb7..3da54b91882 100644
--- a/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs
@@ -1,13 +1,8 @@
-#![feature(intrinsics)]
-
-mod rusti {
-    #[rustc_intrinsic]
-    pub unsafe fn ctlz_nonzero<T>(x: T) -> u32;
-}
+#![feature(core_intrinsics)]
 
 pub fn main() {
     unsafe {
-        use crate::rusti::*;
+        use std::intrinsics::*;
 
         ctlz_nonzero(0u8); //~ ERROR: `ctlz_nonzero` called on 0
     }
diff --git a/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs b/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs
index a41cb8b1553..2b68f6713d8 100644
--- a/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs
+++ b/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs
@@ -1,13 +1,8 @@
-#![feature(intrinsics)]
-
-mod rusti {
-    #[rustc_intrinsic]
-    pub unsafe fn cttz_nonzero<T>(x: T) -> u32;
-}
+#![feature(core_intrinsics)]
 
 pub fn main() {
     unsafe {
-        use crate::rusti::*;
+        use std::intrinsics::*;
 
         cttz_nonzero(0u8); //~ ERROR: `cttz_nonzero` called on 0
     }
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs
index 7ee0117ffb3..831a65966ce 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs
index 22bf881cef0..a7032e97430 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs
index 571121f4019..e8c98761956 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs
index 12600ef6125..c8b29cbcfe9 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs
index f848a137c27..0996d0244e8 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs
index 43ef4a95738..f28227134d8 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs
index 83432c2b77c..9e400b4ad40 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs
index 609443e6d4e..9aca349b918 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs
index fb3eb11c0bb..54361f6c32c 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs
index b46c4777ba7..75f52296367 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs
index 8a3b9dbdc71..20d8fa1ae80 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs
index e0c826cb046..611a0ade0a5 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs
index c7c5bf40226..8ff8c3bee00 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs
index fb3d7bda4e4..1f662e6c32a 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs
index 2cf27b33553..fad172801ea 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs
index 22dca505e64..7eb3559527a 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs
index b59c8fa8e0c..351fc6c6f1c 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs
index 4ad0cd343a4..a6f73c79710 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs
index fd47dfc03d7..b01ff3aafc0 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs
index 680ebda1c96..a573e4e852c 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs
index e4cb36c5d2e..4fb38c9bc2e 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs
index fe4bac92bd3..c4c0d3c17f0 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs
index 219efd80316..de7d2215fd6 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs
@@ -1,8 +1,6 @@
-#![feature(intrinsics)]
-
+#![feature(core_intrinsics)]
 // Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+use std::intrinsics::float_to_int_unchecked;
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/no_main.stderr b/src/tools/miri/tests/fail/no_main.stderr
index e9b9e5d65b1..e7f63be794f 100644
--- a/src/tools/miri/tests/fail/no_main.stderr
+++ b/src/tools/miri/tests/fail/no_main.stderr
@@ -2,7 +2,7 @@ error: Miri can only run programs that have a main function.
        Alternatively, you can export a `miri_start` function:
        
        #[cfg(miri)]
-       #[no_mangle]
+       #[unsafe(no_mangle)]
        fn miri_start(argc: isize, argv: *const *const u8) -> isize {
            // Call the actual start function that your project implements, based on your target's conventions.
        }
diff --git a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs
index 515e467fb54..ac6e221fcd8 100644
--- a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs
+++ b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs
@@ -9,6 +9,6 @@ extern "C" {
 fn main() {
     let mut fds = [-1, -1];
     let res = unsafe { pipe(fds.as_mut_ptr()) };
-    //~^ ERROR: calling a non-variadic function with a variadic caller-side signature
+    //~^ ERROR: ABI mismatch: calling a non-variadic function with a variadic caller-side signature
     assert_eq!(res, 0);
 }
diff --git a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr
index 2782f3b3269..0f642aca322 100644
--- a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr
+++ b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: calling a non-variadic function with a variadic caller-side signature
+error: Undefined Behavior: ABI mismatch: calling a non-variadic function with a variadic caller-side signature
   --> tests/fail/shims/vararg_caller_signature_mismatch.rs:LL:CC
    |
 LL |     let res = unsafe { pipe(fds.as_mut_ptr()) };
-   |                        ^^^^^^^^^^^^^^^^^^^^^^ calling a non-variadic function with a variadic caller-side signature
+   |                        ^^^^^^^^^^^^^^^^^^^^^^ ABI mismatch: calling a non-variadic function with a variadic caller-side signature
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs
index a015464dbde..698ca4e0b4b 100644
--- a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs
+++ b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs
@@ -2,6 +2,7 @@
 //@compile-flags: -Zmiri-disable-isolation
 #![allow(nonstandard_style)]
 
+use std::io::ErrorKind;
 use std::os::windows::ffi::OsStrExt;
 use std::path::Path;
 use std::ptr;
@@ -15,10 +16,10 @@ use windows_sys::Win32::Foundation::{
     STATUS_IO_DEVICE_ERROR,
 };
 use windows_sys::Win32::Storage::FileSystem::{
-    BY_HANDLE_FILE_INFORMATION, CREATE_ALWAYS, CREATE_NEW, CreateFileW, FILE_ATTRIBUTE_DIRECTORY,
-    FILE_ATTRIBUTE_NORMAL, FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT,
-    FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, GetFileInformationByHandle, OPEN_ALWAYS,
-    OPEN_EXISTING,
+    BY_HANDLE_FILE_INFORMATION, CREATE_ALWAYS, CREATE_NEW, CreateFileW, DeleteFileW,
+    FILE_ATTRIBUTE_DIRECTORY, FILE_ATTRIBUTE_NORMAL, FILE_FLAG_BACKUP_SEMANTICS,
+    FILE_FLAG_OPEN_REPARSE_POINT, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE,
+    GetFileInformationByHandle, OPEN_ALWAYS, OPEN_EXISTING,
 };
 
 fn main() {
@@ -28,6 +29,7 @@ fn main() {
         test_create_always_twice();
         test_open_always_twice();
         test_open_dir_reparse();
+        test_delete_file();
         test_ntstatus_to_dos();
     }
 }
@@ -194,6 +196,21 @@ unsafe fn test_open_dir_reparse() {
     };
 }
 
+unsafe fn test_delete_file() {
+    let temp = utils::tmp().join("test_delete_file.txt");
+    let raw_path = to_wide_cstr(&temp);
+    let _ = std::fs::File::create(&temp).unwrap();
+
+    if DeleteFileW(raw_path.as_ptr()) == 0 {
+        panic!("Failed to delete file");
+    }
+
+    match std::fs::File::open(temp) {
+        Ok(_) => panic!("File not deleted"),
+        Err(e) => assert!(e.kind() == ErrorKind::NotFound, "File not deleted"),
+    }
+}
+
 unsafe fn test_ntstatus_to_dos() {
     // We won't test all combinations, just a couple common ones
     assert_eq!(RtlNtStatusToDosError(STATUS_IO_DEVICE_ERROR), ERROR_IO_DEVICE);
diff --git a/src/tools/miri/tests/pass/async-drop.rs b/src/tools/miri/tests/pass/async-drop.rs
index 6d556b77795..4fa84384d9b 100644
--- a/src/tools/miri/tests/pass/async-drop.rs
+++ b/src/tools/miri/tests/pass/async-drop.rs
@@ -4,7 +4,7 @@
 
 // WARNING: If you would ever want to modify this test,
 // please consider modifying rustc's async drop test at
-// `tests/ui/async-await/async-drop.rs`.
+// `tests/ui/async-await/async-drop/async-drop-initial.rs`.
 
 #![feature(async_drop, impl_trait_in_assoc_type)]
 #![allow(incomplete_features, dead_code)]
@@ -68,7 +68,8 @@ fn main() {
         test_async_drop(SyncThenAsync { i: 15, a: AsyncInt(16), b: SyncInt(17), c: AsyncInt(18) })
             .await;
 
-        let async_drop_fut = pin!(core::future::async_drop(AsyncInt(19)));
+        let mut ptr19 = mem::MaybeUninit::new(AsyncInt(19));
+        let async_drop_fut = pin!(unsafe { async_drop_in_place(ptr19.as_mut_ptr()) });
         test_idempotency(async_drop_fut).await;
 
         let foo = AsyncInt(20);
@@ -89,13 +90,14 @@ fn main() {
 
 struct AsyncInt(i32);
 
+impl Drop for AsyncInt {
+    fn drop(&mut self) {
+        println!("AsyncInt::drop: {}", self.0);
+    }
+}
 impl AsyncDrop for AsyncInt {
-    type Dropper<'a> = impl Future<Output = ()>;
-
-    fn async_drop(self: Pin<&mut Self>) -> Self::Dropper<'_> {
-        async move {
-            println!("AsyncInt::Dropper::poll: {}", self.0);
-        }
+    async fn drop(self: Pin<&mut Self>) {
+        println!("AsyncInt::async_drop: {}", self.0);
     }
 }
 
@@ -124,16 +126,14 @@ struct AsyncReference<'a> {
     foo: &'a AsyncInt,
 }
 
+impl Drop for AsyncReference<'_> {
+    fn drop(&mut self) {
+        println!("AsyncReference::drop: {}", self.foo.0);
+    }
+}
 impl AsyncDrop for AsyncReference<'_> {
-    type Dropper<'a>
-        = impl Future<Output = ()>
-    where
-        Self: 'a;
-
-    fn async_drop(self: Pin<&mut Self>) -> Self::Dropper<'_> {
-        async move {
-            println!("AsyncReference::Dropper::poll: {}", self.foo.0);
-        }
+    async fn drop(self: Pin<&mut Self>) {
+        println!("AsyncReference::async_drop: {}", self.foo.0);
     }
 }
 
@@ -145,13 +145,14 @@ struct AsyncStruct {
     b: AsyncInt,
 }
 
+impl Drop for AsyncStruct {
+    fn drop(&mut self) {
+        println!("AsyncStruct::drop: {}", self.i);
+    }
+}
 impl AsyncDrop for AsyncStruct {
-    type Dropper<'a> = impl Future<Output = ()>;
-
-    fn async_drop(self: Pin<&mut Self>) -> Self::Dropper<'_> {
-        async move {
-            println!("AsyncStruct::Dropper::poll: {}", self.i);
-        }
+    async fn drop(self: Pin<&mut Self>) {
+        println!("AsyncStruct::async_drop: {}", self.i);
     }
 }
 
@@ -160,23 +161,34 @@ enum AsyncEnum {
     B(SyncInt),
 }
 
+impl Drop for AsyncEnum {
+    fn drop(&mut self) {
+        let new_self = match self {
+            AsyncEnum::A(foo) => {
+                println!("AsyncEnum(A)::drop: {}", foo.0);
+                AsyncEnum::B(SyncInt(foo.0))
+            }
+            AsyncEnum::B(foo) => {
+                println!("AsyncEnum(B)::drop: {}", foo.0);
+                AsyncEnum::A(AsyncInt(foo.0))
+            }
+        };
+        mem::forget(mem::replace(&mut *self, new_self));
+    }
+}
 impl AsyncDrop for AsyncEnum {
-    type Dropper<'a> = impl Future<Output = ()>;
-
-    fn async_drop(mut self: Pin<&mut Self>) -> Self::Dropper<'_> {
-        async move {
-            let new_self = match &*self {
-                AsyncEnum::A(foo) => {
-                    println!("AsyncEnum(A)::Dropper::poll: {}", foo.0);
-                    AsyncEnum::B(SyncInt(foo.0))
-                }
-                AsyncEnum::B(foo) => {
-                    println!("AsyncEnum(B)::Dropper::poll: {}", foo.0);
-                    AsyncEnum::A(AsyncInt(foo.0))
-                }
-            };
-            mem::forget(mem::replace(&mut *self, new_self));
-        }
+    async fn drop(mut self: Pin<&mut Self>) {
+        let new_self = match &*self {
+            AsyncEnum::A(foo) => {
+                println!("AsyncEnum(A)::async_drop: {}", foo.0);
+                AsyncEnum::B(SyncInt(foo.0))
+            }
+            AsyncEnum::B(foo) => {
+                println!("AsyncEnum(B)::async_drop: {}", foo.0);
+                AsyncEnum::A(AsyncInt(foo.0))
+            }
+        };
+        mem::forget(mem::replace(&mut *self, new_self));
     }
 }
 
@@ -186,14 +198,15 @@ union AsyncUnion {
     unsigned: u32,
 }
 
+impl Drop for AsyncUnion {
+    fn drop(&mut self) {
+        println!("AsyncUnion::drop: {}, {}", unsafe { self.signed }, unsafe { self.unsigned },);
+    }
+}
 impl AsyncDrop for AsyncUnion {
-    type Dropper<'a> = impl Future<Output = ()>;
-
-    fn async_drop(self: Pin<&mut Self>) -> Self::Dropper<'_> {
-        async move {
-            println!("AsyncUnion::Dropper::poll: {}, {}", unsafe { self.signed }, unsafe {
-                self.unsigned
-            });
-        }
+    async fn drop(self: Pin<&mut Self>) {
+        println!("AsyncUnion::async_drop: {}, {}", unsafe { self.signed }, unsafe {
+            self.unsigned
+        });
     }
 }
diff --git a/src/tools/miri/tests/pass/async-drop.stack.stdout b/src/tools/miri/tests/pass/async-drop.stack.stdout
index 9cae4331caf..fc53df2f1b4 100644
--- a/src/tools/miri/tests/pass/async-drop.stack.stdout
+++ b/src/tools/miri/tests/pass/async-drop.stack.stdout
@@ -1,22 +1,23 @@
-AsyncInt::Dropper::poll: 0
-AsyncInt::Dropper::poll: 1
-AsyncInt::Dropper::poll: 2
-AsyncInt::Dropper::poll: 3
-AsyncInt::Dropper::poll: 4
-AsyncStruct::Dropper::poll: 6
-AsyncInt::Dropper::poll: 7
-AsyncInt::Dropper::poll: 8
-AsyncReference::Dropper::poll: 10
-AsyncInt::Dropper::poll: 11
-AsyncEnum(A)::Dropper::poll: 12
+AsyncInt::async_drop: 0
+AsyncInt::async_drop: 1
+AsyncInt::async_drop: 2
+AsyncInt::async_drop: 3
+AsyncInt::async_drop: 4
+AsyncStruct::async_drop: 6
+AsyncInt::async_drop: 7
+AsyncInt::async_drop: 8
+AsyncReference::async_drop: 10
+AsyncInt::async_drop: 11
+AsyncEnum(A)::async_drop: 12
 SyncInt::drop: 12
-AsyncEnum(B)::Dropper::poll: 13
-AsyncInt::Dropper::poll: 13
+AsyncEnum(B)::async_drop: 13
+AsyncInt::async_drop: 13
 SyncInt::drop: 14
 SyncThenAsync::drop: 15
-AsyncInt::Dropper::poll: 16
+AsyncInt::async_drop: 16
 SyncInt::drop: 17
-AsyncInt::Dropper::poll: 18
-AsyncInt::Dropper::poll: 19
-AsyncInt::Dropper::poll: 20
-AsyncUnion::Dropper::poll: 21, 21
+AsyncInt::async_drop: 18
+AsyncInt::async_drop: 19
+AsyncInt::async_drop: 20
+AsyncUnion::async_drop: 21, 21
+AsyncInt::async_drop: 10
diff --git a/src/tools/miri/tests/pass/async-drop.tree.stdout b/src/tools/miri/tests/pass/async-drop.tree.stdout
index 9cae4331caf..fc53df2f1b4 100644
--- a/src/tools/miri/tests/pass/async-drop.tree.stdout
+++ b/src/tools/miri/tests/pass/async-drop.tree.stdout
@@ -1,22 +1,23 @@
-AsyncInt::Dropper::poll: 0
-AsyncInt::Dropper::poll: 1
-AsyncInt::Dropper::poll: 2
-AsyncInt::Dropper::poll: 3
-AsyncInt::Dropper::poll: 4
-AsyncStruct::Dropper::poll: 6
-AsyncInt::Dropper::poll: 7
-AsyncInt::Dropper::poll: 8
-AsyncReference::Dropper::poll: 10
-AsyncInt::Dropper::poll: 11
-AsyncEnum(A)::Dropper::poll: 12
+AsyncInt::async_drop: 0
+AsyncInt::async_drop: 1
+AsyncInt::async_drop: 2
+AsyncInt::async_drop: 3
+AsyncInt::async_drop: 4
+AsyncStruct::async_drop: 6
+AsyncInt::async_drop: 7
+AsyncInt::async_drop: 8
+AsyncReference::async_drop: 10
+AsyncInt::async_drop: 11
+AsyncEnum(A)::async_drop: 12
 SyncInt::drop: 12
-AsyncEnum(B)::Dropper::poll: 13
-AsyncInt::Dropper::poll: 13
+AsyncEnum(B)::async_drop: 13
+AsyncInt::async_drop: 13
 SyncInt::drop: 14
 SyncThenAsync::drop: 15
-AsyncInt::Dropper::poll: 16
+AsyncInt::async_drop: 16
 SyncInt::drop: 17
-AsyncInt::Dropper::poll: 18
-AsyncInt::Dropper::poll: 19
-AsyncInt::Dropper::poll: 20
-AsyncUnion::Dropper::poll: 21, 21
+AsyncInt::async_drop: 18
+AsyncInt::async_drop: 19
+AsyncInt::async_drop: 20
+AsyncUnion::async_drop: 21, 21
+AsyncInt::async_drop: 10
diff --git a/src/tools/miri/tests/pass/dst-raw.rs b/src/tools/miri/tests/pass/dst-raw.rs
index f26191a1d59..3d0b843b3da 100644
--- a/src/tools/miri/tests/pass/dst-raw.rs
+++ b/src/tools/miri/tests/pass/dst-raw.rs
@@ -1,5 +1,7 @@
 // Test DST raw pointers
 
+#![allow(dangerous_implicit_autorefs)]
+
 trait Trait {
     fn foo(&self) -> isize;
 }
diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs
index 575d70579a4..98a88cfd62d 100644
--- a/src/tools/miri/tests/pass/float.rs
+++ b/src/tools/miri/tests/pass/float.rs
@@ -1292,8 +1292,7 @@ fn test_non_determinism() {
             }
         }
         // We saw the same thing N times.
-        // FIXME: temporarily disabled as it breaks std tests.
-        //panic!("expected non-determinism, got {rounds} times the same result: {first:?}");
+        panic!("expected non-determinism, got {rounds} times the same result: {first:?}");
     }
 
     macro_rules! test_operations_f {
@@ -1319,66 +1318,68 @@ fn test_non_determinism() {
     }
     pub fn test_operations_f32(a: f32, b: f32) {
         test_operations_f!(a, b);
-        ensure_nondet(|| a.log(b));
-        ensure_nondet(|| a.exp());
-        ensure_nondet(|| 10f32.exp2());
-        ensure_nondet(|| f32::consts::E.ln());
-        ensure_nondet(|| 1f32.ln_1p());
-        ensure_nondet(|| 10f32.log10());
-        ensure_nondet(|| 8f32.log2());
-        ensure_nondet(|| 27.0f32.cbrt());
-        ensure_nondet(|| 3.0f32.hypot(4.0f32));
-        ensure_nondet(|| 1f32.sin());
-        ensure_nondet(|| 0f32.cos());
-        // On i686-pc-windows-msvc , these functions are implemented by calling the `f64` version,
-        // which means the little rounding errors Miri introduces are discard by the cast down to `f32`.
-        // Just skip the test for them.
-        if !cfg!(all(target_os = "windows", target_env = "msvc", target_arch = "x86")) {
-            ensure_nondet(|| 1.0f32.tan());
-            ensure_nondet(|| 1.0f32.asin());
-            ensure_nondet(|| 5.0f32.acos());
-            ensure_nondet(|| 1.0f32.atan());
-            ensure_nondet(|| 1.0f32.atan2(2.0f32));
-            ensure_nondet(|| 1.0f32.sinh());
-            ensure_nondet(|| 1.0f32.cosh());
-            ensure_nondet(|| 1.0f32.tanh());
-        }
-        ensure_nondet(|| 1.0f32.asinh());
-        ensure_nondet(|| 2.0f32.acosh());
-        ensure_nondet(|| 0.5f32.atanh());
-        ensure_nondet(|| 5.0f32.gamma());
-        ensure_nondet(|| 5.0f32.ln_gamma());
-        ensure_nondet(|| 5.0f32.erf());
-        ensure_nondet(|| 5.0f32.erfc());
+        // FIXME: temporarily disabled as it breaks std tests.
+        // ensure_nondet(|| a.log(b));
+        // ensure_nondet(|| a.exp());
+        // ensure_nondet(|| 10f32.exp2());
+        // ensure_nondet(|| f32::consts::E.ln());
+        // ensure_nondet(|| 1f32.ln_1p());
+        // ensure_nondet(|| 10f32.log10());
+        // ensure_nondet(|| 8f32.log2());
+        // ensure_nondet(|| 27.0f32.cbrt());
+        // ensure_nondet(|| 3.0f32.hypot(4.0f32));
+        // ensure_nondet(|| 1f32.sin());
+        // ensure_nondet(|| 0f32.cos());
+        // // On i686-pc-windows-msvc , these functions are implemented by calling the `f64` version,
+        // // which means the little rounding errors Miri introduces are discard by the cast down to `f32`.
+        // // Just skip the test for them.
+        // if !cfg!(all(target_os = "windows", target_env = "msvc", target_arch = "x86")) {
+        //     ensure_nondet(|| 1.0f32.tan());
+        //     ensure_nondet(|| 1.0f32.asin());
+        //     ensure_nondet(|| 5.0f32.acos());
+        //     ensure_nondet(|| 1.0f32.atan());
+        //     ensure_nondet(|| 1.0f32.atan2(2.0f32));
+        //     ensure_nondet(|| 1.0f32.sinh());
+        //     ensure_nondet(|| 1.0f32.cosh());
+        //     ensure_nondet(|| 1.0f32.tanh());
+        // }
+        // ensure_nondet(|| 1.0f32.asinh());
+        // ensure_nondet(|| 2.0f32.acosh());
+        // ensure_nondet(|| 0.5f32.atanh());
+        // ensure_nondet(|| 5.0f32.gamma());
+        // ensure_nondet(|| 5.0f32.ln_gamma());
+        // ensure_nondet(|| 5.0f32.erf());
+        // ensure_nondet(|| 5.0f32.erfc());
     }
     pub fn test_operations_f64(a: f64, b: f64) {
         test_operations_f!(a, b);
-        ensure_nondet(|| a.log(b));
-        ensure_nondet(|| a.exp());
-        ensure_nondet(|| 50f64.exp2());
-        ensure_nondet(|| 3f64.ln());
-        ensure_nondet(|| 1f64.ln_1p());
-        ensure_nondet(|| f64::consts::E.log10());
-        ensure_nondet(|| f64::consts::E.log2());
-        ensure_nondet(|| 27.0f64.cbrt());
-        ensure_nondet(|| 3.0f64.hypot(4.0f64));
-        ensure_nondet(|| 1f64.sin());
-        ensure_nondet(|| 0f64.cos());
-        ensure_nondet(|| 1.0f64.tan());
-        ensure_nondet(|| 1.0f64.asin());
-        ensure_nondet(|| 5.0f64.acos());
-        ensure_nondet(|| 1.0f64.atan());
-        ensure_nondet(|| 1.0f64.atan2(2.0f64));
-        ensure_nondet(|| 1.0f64.sinh());
-        ensure_nondet(|| 1.0f64.cosh());
-        ensure_nondet(|| 1.0f64.tanh());
-        ensure_nondet(|| 1.0f64.asinh());
-        ensure_nondet(|| 3.0f64.acosh());
-        ensure_nondet(|| 0.5f64.atanh());
-        ensure_nondet(|| 5.0f64.gamma());
-        ensure_nondet(|| 5.0f64.ln_gamma());
-        ensure_nondet(|| 5.0f64.erf());
-        ensure_nondet(|| 5.0f64.erfc());
+        // FIXME: temporarily disabled as it breaks std tests.
+        // ensure_nondet(|| a.log(b));
+        // ensure_nondet(|| a.exp());
+        // ensure_nondet(|| 50f64.exp2());
+        // ensure_nondet(|| 3f64.ln());
+        // ensure_nondet(|| 1f64.ln_1p());
+        // ensure_nondet(|| f64::consts::E.log10());
+        // ensure_nondet(|| f64::consts::E.log2());
+        // ensure_nondet(|| 27.0f64.cbrt());
+        // ensure_nondet(|| 3.0f64.hypot(4.0f64));
+        // ensure_nondet(|| 1f64.sin());
+        // ensure_nondet(|| 0f64.cos());
+        // ensure_nondet(|| 1.0f64.tan());
+        // ensure_nondet(|| 1.0f64.asin());
+        // ensure_nondet(|| 5.0f64.acos());
+        // ensure_nondet(|| 1.0f64.atan());
+        // ensure_nondet(|| 1.0f64.atan2(2.0f64));
+        // ensure_nondet(|| 1.0f64.sinh());
+        // ensure_nondet(|| 1.0f64.cosh());
+        // ensure_nondet(|| 1.0f64.tanh());
+        // ensure_nondet(|| 1.0f64.asinh());
+        // ensure_nondet(|| 3.0f64.acosh());
+        // ensure_nondet(|| 0.5f64.atanh());
+        // ensure_nondet(|| 5.0f64.gamma());
+        // ensure_nondet(|| 5.0f64.ln_gamma());
+        // ensure_nondet(|| 5.0f64.erf());
+        // ensure_nondet(|| 5.0f64.erfc());
     }
     pub fn test_operations_f128(a: f128, b: f128) {
         test_operations_f!(a, b);
diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs
index 6ad23055f30..d0a7f245ee0 100644
--- a/src/tools/miri/tests/pass/shims/fs.rs
+++ b/src/tools/miri/tests/pass/shims/fs.rs
@@ -17,10 +17,10 @@ mod utils;
 
 fn main() {
     test_path_conversion();
+    test_file_create_new();
     // Windows file handling is very incomplete.
     if cfg!(not(windows)) {
         test_file();
-        test_file_create_new();
         test_seek();
         test_file_clone();
         test_metadata();
diff --git a/src/tools/miri/tests/pass/slices.rs b/src/tools/miri/tests/pass/slices.rs
index dd18a061cdd..686683c3a25 100644
--- a/src/tools/miri/tests/pass/slices.rs
+++ b/src/tools/miri/tests/pass/slices.rs
@@ -1,7 +1,6 @@
 //@revisions: stack tree
 //@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-strict-provenance
-#![feature(slice_as_chunks)]
 #![feature(slice_partition_dedup)]
 #![feature(layout_for_ptr)]
 
@@ -227,7 +226,7 @@ fn test_for_invalidated_pointers() {
 
     buffer.reverse();
 
-    // Calls `fn as_chunks_unchecked_mut` internally (requires unstable `#![feature(slice_as_chunks)]`):
+    // Calls `fn as_chunks_unchecked_mut` internally:
     assert_eq!(2, buffer.as_chunks_mut::<32>().0.len());
     for chunk in buffer.as_chunks_mut::<32>().0 {
         for elem in chunk {
diff --git a/src/tools/miri/tests/pass/stacked-borrows/interior_mutability.rs b/src/tools/miri/tests/pass/stacked-borrows/interior_mutability.rs
index 830e9c33847..e86cb3711ac 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/interior_mutability.rs
+++ b/src/tools/miri/tests/pass/stacked-borrows/interior_mutability.rs
@@ -1,3 +1,5 @@
+#![allow(dangerous_implicit_autorefs)]
+
 use std::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};
 use std::mem::{self, MaybeUninit};
 
diff --git a/src/tools/miri/tests/pass/tree_borrows/interior_mutability.rs b/src/tools/miri/tests/pass/tree_borrows/interior_mutability.rs
new file mode 100644
index 00000000000..6dde593d2cf
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree_borrows/interior_mutability.rs
@@ -0,0 +1,178 @@
+//@revisions: default uniq
+//@compile-flags: -Zmiri-tree-borrows
+//@[uniq]compile-flags: -Zmiri-unique-is-unique
+#![allow(dangerous_implicit_autorefs)]
+use std::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};
+use std::mem::{self, MaybeUninit};
+
+fn main() {
+    aliasing_mut_and_shr();
+    aliasing_frz_and_shr();
+    into_interior_mutability();
+    unsafe_cell_2phase();
+    unsafe_cell_deallocate();
+    unsafe_cell_invalidate();
+    refcell_basic();
+    ref_protector();
+    ref_mut_protector();
+    rust_issue_68303();
+}
+
+fn aliasing_mut_and_shr() {
+    fn inner(rc: &RefCell<i32>, aliasing: &mut i32) {
+        *aliasing += 4;
+        let _escape_to_raw = rc as *const _;
+        *aliasing += 4;
+        let _shr = &*rc;
+        *aliasing += 4;
+        // also turning this into a frozen ref now must work
+        let aliasing = &*aliasing;
+        let _val = *aliasing;
+        let _escape_to_raw = rc as *const _; // this must NOT unfreeze
+        let _val = *aliasing;
+        let _shr = &*rc; // this must NOT unfreeze
+        let _val = *aliasing;
+    }
+
+    let rc = RefCell::new(23);
+    let mut bmut = rc.borrow_mut();
+    inner(&rc, &mut *bmut);
+    drop(bmut);
+    assert_eq!(*rc.borrow(), 23 + 12);
+}
+
+fn aliasing_frz_and_shr() {
+    fn inner(rc: &RefCell<i32>, aliasing: &i32) {
+        let _val = *aliasing;
+        let _escape_to_raw = rc as *const _; // this must NOT unfreeze
+        let _val = *aliasing;
+        let _shr = &*rc; // this must NOT unfreeze
+        let _val = *aliasing;
+    }
+
+    let rc = RefCell::new(23);
+    let bshr = rc.borrow();
+    inner(&rc, &*bshr);
+    assert_eq!(*rc.borrow(), 23);
+}
+
+// Getting a pointer into a union with interior mutability used to be tricky
+// business (https://github.com/rust-lang/miri/issues/615), but it should work
+// now.
+fn into_interior_mutability() {
+    let mut x: MaybeUninit<(Cell<u32>, u32)> = MaybeUninit::uninit();
+    x.as_ptr();
+    x.write((Cell::new(0), 1));
+    let ptr = unsafe { x.assume_init_ref() };
+    assert_eq!(ptr.1, 1);
+}
+
+// Two-phase borrows of the pointer returned by UnsafeCell::get() should not
+// invalidate aliases.
+fn unsafe_cell_2phase() {
+    unsafe {
+        let x = &UnsafeCell::new(vec![]);
+        let x2 = &*x;
+        (*x.get()).push(0);
+        let _val = (*x2.get()).get(0);
+    }
+}
+
+/// Make sure we can deallocate an UnsafeCell that was passed to an active fn call.
+/// (This is the fix for https://github.com/rust-lang/rust/issues/55005.)
+fn unsafe_cell_deallocate() {
+    fn f(x: &UnsafeCell<i32>) {
+        let b: Box<i32> = unsafe { Box::from_raw(x as *const _ as *mut i32) };
+        drop(b)
+    }
+
+    let b = Box::new(0i32);
+    f(unsafe { mem::transmute(Box::into_raw(b)) });
+}
+
+/// As a side-effect of the above, we also allow this -- at least for now.
+fn unsafe_cell_invalidate() {
+    fn f(_x: &UnsafeCell<i32>, y: *mut i32) {
+        // Writing to y invalidates x, but that is okay.
+        unsafe {
+            *y += 1;
+        }
+    }
+
+    let mut x = 0i32;
+    let raw1 = &mut x as *mut _;
+    let ref1 = unsafe { &mut *raw1 };
+    let raw2 = ref1 as *mut _;
+    // Now the borrow stack is: raw1, ref2, raw2.
+    // So using raw1 invalidates raw2.
+    f(unsafe { mem::transmute(raw2) }, raw1);
+}
+
+fn refcell_basic() {
+    let c = RefCell::new(42);
+    {
+        let s1 = c.borrow();
+        let _x: i32 = *s1;
+        let s2 = c.borrow();
+        let _x: i32 = *s1;
+        let _y: i32 = *s2;
+        let _x: i32 = *s1;
+        let _y: i32 = *s2;
+    }
+    {
+        let mut m = c.borrow_mut();
+        let _z: i32 = *m;
+        {
+            let s: &i32 = &*m;
+            let _x = *s;
+        }
+        *m = 23;
+        let _z: i32 = *m;
+    }
+    {
+        let s1 = c.borrow();
+        let _x: i32 = *s1;
+        let s2 = c.borrow();
+        let _x: i32 = *s1;
+        let _y: i32 = *s2;
+        let _x: i32 = *s1;
+        let _y: i32 = *s2;
+    }
+}
+
+// Adding a Stacked Borrows protector for `Ref` would break this
+fn ref_protector() {
+    fn break_it(rc: &RefCell<i32>, r: Ref<'_, i32>) {
+        // `r` has a shared reference, it is passed in as argument and hence
+        // a protector is added that marks this memory as read-only for the entire
+        // duration of this function.
+        drop(r);
+        // *oops* here we can mutate that memory.
+        *rc.borrow_mut() = 2;
+    }
+
+    let rc = RefCell::new(0);
+    break_it(&rc, rc.borrow())
+}
+
+fn ref_mut_protector() {
+    fn break_it(rc: &RefCell<i32>, r: RefMut<'_, i32>) {
+        // `r` has a shared reference, it is passed in as argument and hence
+        // a protector is added that marks this memory as inaccessible for the entire
+        // duration of this function
+        drop(r);
+        // *oops* here we can mutate that memory.
+        *rc.borrow_mut() = 2;
+    }
+
+    let rc = RefCell::new(0);
+    break_it(&rc, rc.borrow_mut())
+}
+
+/// Make sure we do not have bad enum layout optimizations.
+fn rust_issue_68303() {
+    let optional = Some(RefCell::new(false));
+    let mut handle = optional.as_ref().unwrap().borrow_mut();
+    assert!(optional.is_some());
+    *handle = true;
+}
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index d257988a57a..8d6c8284e44 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -2039,9 +2039,9 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
 
 [[package]]
 name = "salsa"
-version = "0.21.0"
+version = "0.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4deeb38b4c80ac90a8d4796f83da941b0d76c23783550d15d37eb43ccddcb5bc"
+checksum = "6f80d5cf3c3fcab2cef898012f242a670477a1baa609267376af9cb4409026c5"
 dependencies = [
  "boxcar",
  "crossbeam-queue",
@@ -2062,15 +2062,15 @@ dependencies = [
 
 [[package]]
 name = "salsa-macro-rules"
-version = "0.21.0"
+version = "0.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4e6166fa2802d86a77dbcae1bfe75f0ac46fdf952660c233ed64855a53dd603"
+checksum = "05303d72606fbf2b9c9523cda2039bb8ecb00304027a3cd7e52b02a65c7d9185"
 
 [[package]]
 name = "salsa-macros"
-version = "0.21.0"
+version = "0.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf358e645a835d9901ee4d812d9812266e046ee92a28d2e37a73b7169a6503b7"
+checksum = "eb2f0e2a30c65cb3cd63440c491dde68d9af7e1be2b77832ac7057141107db50"
 dependencies = [
  "heck",
  "proc-macro2",
diff --git a/src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs b/src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs
index 6b81928c91e..357e56ddfaa 100644
--- a/src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs
@@ -159,7 +159,7 @@ impl Parse for Cycle {
         }
 
         impl Parse for Option {
-            fn parse(input: ParseStream) -> syn::Result<Self> {
+            fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
                 let name = input.parse()?;
                 input.parse::<Token![=]>()?;
                 let value = input.parse()?;
diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version
index 09c127f6bcd..90e4d65bf96 100644
--- a/src/tools/rust-analyzer/rust-version
+++ b/src/tools/rust-analyzer/rust-version
@@ -1 +1 @@
-21079f53a359d9fc82668d4175d49dafdb600563
+6e23095adf9209614a45f7f75fea36dad7b92afb
diff --git a/src/tools/rustfmt/src/pairs.rs b/src/tools/rustfmt/src/pairs.rs
index 9c51298416b..17ff041d775 100644
--- a/src/tools/rustfmt/src/pairs.rs
+++ b/src/tools/rustfmt/src/pairs.rs
@@ -1,4 +1,4 @@
-use rustc_ast::ast;
+use rustc_ast::{ast, token};
 use rustc_span::Span;
 
 use crate::config::IndentStyle;
@@ -272,13 +272,17 @@ struct PairList<'a, 'b, T: Rewrite> {
     span: Span,
 }
 
-fn is_ident(expr: &ast::Expr) -> bool {
+fn is_ident_or_bool_lit(expr: &ast::Expr) -> bool {
     match &expr.kind {
         ast::ExprKind::Path(None, path) if path.segments.len() == 1 => true,
+        ast::ExprKind::Lit(token::Lit {
+            kind: token::LitKind::Bool,
+            ..
+        }) => true,
         ast::ExprKind::Unary(_, expr)
         | ast::ExprKind::AddrOf(_, _, expr)
         | ast::ExprKind::Paren(expr)
-        | ast::ExprKind::Try(expr) => is_ident(expr),
+        | ast::ExprKind::Try(expr) => is_ident_or_bool_lit(expr),
         _ => false,
     }
 }
@@ -296,10 +300,10 @@ impl<'a, 'b> PairList<'a, 'b, ast::Expr> {
             return false;
         }
 
-        let fist_item_is_ident = is_ident(self.list[0].0);
+        let fist_item_is_ident_or_bool_lit = is_ident_or_bool_lit(self.list[0].0);
         let second_item_is_let_chain = matches!(self.list[1].0.kind, ast::ExprKind::Let(..));
 
-        fist_item_is_ident && second_item_is_let_chain
+        fist_item_is_ident_or_bool_lit && second_item_is_let_chain
     }
 }
 
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 75a5a8532b8..7ec1032dcb4 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -1093,6 +1093,19 @@ impl Rewrite for ast::TyPat {
             ast::TyPatKind::Range(ref lhs, ref rhs, ref end_kind) => {
                 rewrite_range_pat(context, shape, lhs, rhs, end_kind, self.span)
             }
+            ast::TyPatKind::Or(ref variants) => {
+                let mut first = true;
+                let mut s = String::new();
+                for variant in variants {
+                    if first {
+                        first = false
+                    } else {
+                        s.push_str(" | ");
+                    }
+                    s.push_str(&variant.rewrite_result(context, shape)?);
+                }
+                Ok(s)
+            }
             ast::TyPatKind::Err(_) => Err(RewriteError::Unknown),
         }
     }
diff --git a/src/tools/rustfmt/tests/source/let_chains.rs b/src/tools/rustfmt/tests/source/let_chains.rs
index b7c1f811096..0c4d8aa85ea 100644
--- a/src/tools/rustfmt/tests/source/let_chains.rs
+++ b/src/tools/rustfmt/tests/source/let_chains.rs
@@ -20,6 +20,11 @@ fn test_single_line_let_chain() {
     if a && let Some(b) = foo() {
     }
 
+    // first item in let-chain is a bool literal
+    if true && let Some(x) = y {
+
+    }
+
     // first item in let-chain is a unary ! with an ident
     let unary_not = if !from_hir_call
         && let Some(p) = parent
@@ -94,11 +99,6 @@ fn test_multi_line_let_chain() {
 
     }
 
-    // bool literal
-    if true && let Some(x) = y {
-
-    }
-
     // cast to a bool
     if 1 as bool && let Some(x) = y {
 
diff --git a/src/tools/rustfmt/tests/target/let_chains.rs b/src/tools/rustfmt/tests/target/let_chains.rs
index 1ceecac8abc..204937b4cac 100644
--- a/src/tools/rustfmt/tests/target/let_chains.rs
+++ b/src/tools/rustfmt/tests/target/let_chains.rs
@@ -50,6 +50,9 @@ fn test_single_line_let_chain() {
     // first item in let-chain is an ident
     if a && let Some(b) = foo() {}
 
+    // first item in let-chain is a bool literal
+    if true && let Some(x) = y {}
+
     // first item in let-chain is a unary ! with an ident
     let unary_not = if !from_hir_call && let Some(p) = parent {};
 
@@ -102,11 +105,6 @@ fn test_multi_line_let_chain() {
         && let Some(x) = y
     {}
 
-    // bool literal
-    if true
-        && let Some(x) = y
-    {}
-
     // cast to a bool
     if 1 as bool
         && let Some(x) = y
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index f1ce3ccda04..e6b5aa59622 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -1979,7 +1979,6 @@ ui/issues/issue-27997.rs
 ui/issues/issue-28105.rs
 ui/issues/issue-28109.rs
 ui/issues/issue-28181.rs
-ui/issues/issue-2823.rs
 ui/issues/issue-28279.rs
 ui/issues/issue-28344.rs
 ui/issues/issue-28433.rs
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 2e069af23d6..44dd1e50f5b 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -17,7 +17,7 @@ use ignore::Walk;
 const ENTRY_LIMIT: u32 = 901;
 // FIXME: The following limits should be reduced eventually.
 
-const ISSUES_ENTRY_LIMIT: u32 = 1626;
+const ISSUES_ENTRY_LIMIT: u32 = 1624;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
     "rs",     // test source files