summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock90
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch13
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs5
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs7
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs10
-rw-r--r--compiler/rustc_interface/src/interface.rs2
-rw-r--r--compiler/rustc_lint/src/if_let_rescope.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs105
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coroutine/by_move_body.rs10
-rw-r--r--compiler/rustc_mir_transform/src/single_use_consts.rs5
-rw-r--r--compiler/rustc_pattern_analysis/src/constructor.rs8
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs6
-rw-r--r--library/Cargo.lock4
-rw-r--r--library/alloc/Cargo.toml2
-rw-r--r--library/alloc/benches/str.rs2
-rw-r--r--library/alloc/src/slice.rs67
-rw-r--r--library/alloc/src/str.rs129
-rw-r--r--library/alloc/tests/str.rs3
-rw-r--r--library/core/src/alloc/global.rs32
-rw-r--r--library/core/src/cell.rs51
-rw-r--r--library/core/src/cell/once.rs3
-rw-r--r--library/core/src/cmp.rs356
-rw-r--r--library/core/src/intrinsics.rs15
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/panic/location.rs2
-rw-r--r--library/core/src/sync/atomic.rs6
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/build.rs25
-rw-r--r--library/std/src/net/tcp.rs2
-rw-r--r--library/std/src/net/udp.rs2
-rw-r--r--library/std/src/panic.rs58
-rw-r--r--library/std/src/thread/mod.rs27
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs2
-rw-r--r--src/bootstrap/src/core/config/config.rs22
-rw-r--r--src/bootstrap/src/lib.rs21
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
-rw-r--r--src/doc/rustdoc/src/write-documentation/documentation-tests.md4
-rw-r--r--src/librustdoc/doctest.rs2
-rw-r--r--src/librustdoc/doctest/make.rs2
-rw-r--r--src/librustdoc/html/markdown.rs77
-rw-r--r--src/librustdoc/visit.rs11
-rw-r--r--src/tools/build_helper/src/ci.rs9
-rw-r--r--src/tools/compiletest/src/header.rs8
-rw-r--r--src/tools/compiletest/src/runtest.rs11
-rw-r--r--src/tools/rustbook/Cargo.lock52
-rw-r--r--tests/codegen/issues/issue-123712-str-to-lower-autovectorization.rs23
-rw-r--r--tests/crashes/130521.rs13
-rw-r--r--tests/crashes/130524.rs22
-rw-r--r--tests/crashes/130627.rs20
-rw-r--r--tests/crashes/130687.rs4
-rw-r--r--tests/crashes/130779.rs11
-rw-r--r--tests/crashes/130921.rs10
-rw-r--r--tests/crashes/130970.rs9
-rw-r--r--tests/run-make/doctests-merge/doctest-standalone.rs4
-rw-r--r--tests/rustdoc-gui/docblock-code-block-line-number.goml18
-rw-r--r--tests/rustdoc-ui/doctest/check-attr-test.stderr48
-rw-r--r--tests/rustdoc-ui/doctest/standalone-warning-2024.rs16
-rw-r--r--tests/rustdoc-ui/doctest/standalone-warning-2024.stderr38
-rw-r--r--tests/rustdoc-ui/doctest/standalone-warning.rs10
-rw-r--r--tests/rustdoc-ui/lints/check-attr.stderr52
-rw-r--r--tests/rustdoc-ui/lints/check-fail.stderr8
-rw-r--r--tests/ui/errors/remap-path-prefix-sysroot.rs24
-rw-r--r--tests/ui/errors/remap-path-prefix-sysroot.with-remap.stderr17
-rw-r--r--tests/ui/errors/remap-path-prefix-sysroot.without-remap.stderr17
67 files changed, 1062 insertions, 586 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ebb8d114f2a..d00bf4b1292 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -207,9 +207,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "autocfg"
-version = "1.3.0"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "backtrace"
@@ -505,7 +505,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -534,7 +534,7 @@ dependencies = [
"rustc_tools_util",
"serde",
"serde_json",
- "syn 2.0.77",
+ "syn 2.0.79",
"tempfile",
"termize",
"tokio",
@@ -643,7 +643,7 @@ dependencies = [
"nom",
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -861,7 +861,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -872,7 +872,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -898,7 +898,7 @@ version = "0.1.83"
dependencies = [
"itertools",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -918,7 +918,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -939,7 +939,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -949,7 +949,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4abae7035bf79b9877b779505d8cf3749285b80c43941eda66604841889451dc"
dependencies = [
"derive_builder_core",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -961,7 +961,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -1039,7 +1039,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -1192,9 +1192,9 @@ dependencies = [
[[package]]
name = "flate2"
-version = "1.0.33"
+version = "1.0.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253"
+checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0"
dependencies = [
"crc32fast",
"miniz_oxide 0.8.0",
@@ -1330,7 +1330,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -1554,7 +1554,7 @@ dependencies = [
"markup5ever",
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -1686,7 +1686,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -2661,7 +2661,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -2763,9 +2763,9 @@ dependencies = [
[[package]]
name = "portable-atomic"
-version = "1.8.0"
+version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce"
+checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2"
[[package]]
name = "powerfmt"
@@ -3073,7 +3073,7 @@ dependencies = [
"rinja_parser",
"rustc-hash 2.0.0",
"serde",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -3671,7 +3671,7 @@ dependencies = [
"fluent-syntax",
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
"unic-langid",
]
@@ -3805,7 +3805,7 @@ version = "0.0.0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -3954,7 +3954,7 @@ version = "0.0.0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
"synstructure",
]
@@ -4535,7 +4535,7 @@ version = "0.0.0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
"synstructure",
]
@@ -4623,7 +4623,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -4760,7 +4760,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -5024,9 +5024,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.77"
+version = "2.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
+checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
dependencies = [
"proc-macro2",
"quote",
@@ -5041,7 +5041,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -5078,9 +5078,9 @@ dependencies = [
[[package]]
name = "tempfile"
-version = "3.12.0"
+version = "3.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64"
+checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b"
dependencies = [
"cfg-if",
"fastrand",
@@ -5174,7 +5174,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -5365,7 +5365,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -5536,7 +5536,7 @@ checksum = "1ed7f4237ba393424195053097c1516bd4590dc82b84f2f97c5c69e12704555b"
dependencies = [
"proc-macro-hack",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
"unic-langid-impl",
]
@@ -5734,7 +5734,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
"wasm-bindgen-shared",
]
@@ -5756,7 +5756,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -5923,7 +5923,7 @@ dependencies = [
"rayon",
"serde",
"serde_json",
- "syn 2.0.77",
+ "syn 2.0.79",
"windows-metadata",
]
@@ -5956,7 +5956,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -5967,7 +5967,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -6234,7 +6234,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
"synstructure",
]
@@ -6256,7 +6256,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
[[package]]
@@ -6276,7 +6276,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
"synstructure",
]
@@ -6299,5 +6299,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.77",
+ "syn 2.0.79",
]
diff --git a/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch
index a3f370af916..646928893e9 100644
--- a/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch
@@ -82,19 +82,6 @@ index d9de37e..8293fce 100644
#[cfg(target_has_atomic_load_store = "ptr")]
macro_rules! atomic_int_ptr_sized {
( $($target_pointer_width:literal $align:literal)* ) => { $(
-diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
-index 58b9ba4..91bbd0a 100644
---- a/library/core/src/cell.rs
-+++ b/library/core/src/cell.rs
-@@ -2246,8 +2246,6 @@ unsafe_cell_primitive_into_inner! {
- u32 "32"
- i64 "64"
- u64 "64"
-- i128 "128"
-- u128 "128"
- isize "ptr"
- usize "ptr"
- }
--
2.26.2.7.g19db9cfb68
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index a2a5499597c..201cfbb1918 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -536,6 +536,11 @@ pub(crate) fn global_llvm_features(
// -Ctarget-cpu=native
match sess.opts.cg.target_cpu {
Some(ref s) if s == "native" => {
+ // We have already figured out the actual CPU name with `LLVMRustGetHostCPUName` and set
+ // that for LLVM, so the features implied by that CPU name will be available everywhere.
+ // However, that is not sufficient: e.g. `skylake` alone is not sufficient to tell if
+ // some of the instructions are available or not. So we have to also explicitly ask for
+ // the exact set of features available on the host, and enable all of them.
let features_string = unsafe {
let ptr = llvm::LLVMGetHostCPUFeatures();
let features_string = if !ptr.is_null() {
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index e1fd8bea1f3..4c34ffc5d4e 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -396,11 +396,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
for i in 0..dest_len {
let place = self.project_index(&dest, i)?;
- let value = if i == index {
- elem.clone()
- } else {
- self.project_index(&input, i)?.into()
- };
+ let value =
+ if i == index { elem.clone() } else { self.project_index(&input, i)? };
self.copy_op(&value, &place)?;
}
}
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index a7b251ab252..0dc35618ff8 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -627,8 +627,7 @@ impl server::TokenStream for Rustc<'_, '_> {
base: Option<Self::TokenStream>,
trees: Vec<TokenTree<Self::TokenStream, Self::Span, Self::Symbol>>,
) -> Self::TokenStream {
- let mut stream =
- if let Some(base) = base { base } else { tokenstream::TokenStream::default() };
+ let mut stream = base.unwrap_or_default();
for tree in trees {
for tt in (tree, &mut *self).to_internal() {
stream.push_tree(tt);
@@ -642,8 +641,7 @@ impl server::TokenStream for Rustc<'_, '_> {
base: Option<Self::TokenStream>,
streams: Vec<Self::TokenStream>,
) -> Self::TokenStream {
- let mut stream =
- if let Some(base) = base { base } else { tokenstream::TokenStream::default() };
+ let mut stream = base.unwrap_or_default();
for s in streams {
stream.push_stream(s);
}
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index c5843b883a1..63cf483aa22 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -1369,13 +1369,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for (&var_hir_id, _) in upvars.iter() {
let mut diagnostics_info = Vec::new();
- let auto_trait_diagnostic = if let Some(diagnostics_info) =
- self.compute_2229_migrations_for_trait(min_captures, var_hir_id, closure_clause)
- {
- diagnostics_info
- } else {
- FxIndexMap::default()
- };
+ let auto_trait_diagnostic = self
+ .compute_2229_migrations_for_trait(min_captures, var_hir_id, closure_clause)
+ .unwrap_or_default();
let drop_reorder_diagnostic = if let Some(diagnostics_info) = self
.compute_2229_migrations_for_drop(
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index c2241773c8c..3b8077bb3fc 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -427,7 +427,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
Err(e) => early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")),
};
- let mut locale_resources = Vec::from(config.locale_resources);
+ let mut locale_resources = config.locale_resources;
locale_resources.push(codegen_backend.locale_resource());
let mut sess = rustc_session::build_session(
diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs
index 229d0c36421..c6218fe1e74 100644
--- a/compiler/rustc_lint/src/if_let_rescope.rs
+++ b/compiler/rustc_lint/src/if_let_rescope.rs
@@ -304,7 +304,7 @@ impl Subdiagnostic for IfLetRescopeRewrite {
.chain(repeat('}').take(closing_brackets.count))
.collect(),
));
- let msg = f(diag, crate::fluent_generated::lint_suggestion.into());
+ let msg = f(diag, crate::fluent_generated::lint_suggestion);
diag.multipart_suggestion_with_style(
msg,
suggestions,
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 4425c93211a..2157324d5cc 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1622,56 +1622,63 @@ impl<'a> CrateMetadataRef<'a> {
);
for virtual_dir in virtual_rust_source_base_dir.iter().flatten() {
- if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
- if let rustc_span::FileName::Real(old_name) = name {
- if let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
- old_name
- {
- if let Ok(rest) = virtual_name.strip_prefix(virtual_dir) {
- let virtual_name = virtual_name.clone();
-
- // The std library crates are in
- // `$sysroot/lib/rustlib/src/rust/library`, whereas other crates
- // may be in `$sysroot/lib/rustlib/src/rust/` directly. So we
- // detect crates from the std libs and handle them specially.
- const STD_LIBS: &[&str] = &[
- "core",
- "alloc",
- "std",
- "test",
- "term",
- "unwind",
- "proc_macro",
- "panic_abort",
- "panic_unwind",
- "profiler_builtins",
- "rtstartup",
- "rustc-std-workspace-core",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-std",
- "backtrace",
- ];
- let is_std_lib = STD_LIBS.iter().any(|l| rest.starts_with(l));
-
- let new_path = if is_std_lib {
- real_dir.join("library").join(rest)
- } else {
- real_dir.join(rest)
- };
-
- debug!(
- "try_to_translate_virtual_to_real: `{}` -> `{}`",
- virtual_name.display(),
- new_path.display(),
- );
- let new_name = rustc_span::RealFileName::Remapped {
- local_path: Some(new_path),
- virtual_name,
- };
- *old_name = new_name;
- }
+ if let Some(real_dir) = &sess.opts.real_rust_source_base_dir
+ && let rustc_span::FileName::Real(old_name) = name
+ && let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
+ old_name
+ && let Ok(rest) = virtual_name.strip_prefix(virtual_dir)
+ {
+ // The std library crates are in
+ // `$sysroot/lib/rustlib/src/rust/library`, whereas other crates
+ // may be in `$sysroot/lib/rustlib/src/rust/` directly. So we
+ // detect crates from the std libs and handle them specially.
+ const STD_LIBS: &[&str] = &[
+ "core",
+ "alloc",
+ "std",
+ "test",
+ "term",
+ "unwind",
+ "proc_macro",
+ "panic_abort",
+ "panic_unwind",
+ "profiler_builtins",
+ "rtstartup",
+ "rustc-std-workspace-core",
+ "rustc-std-workspace-alloc",
+ "rustc-std-workspace-std",
+ "backtrace",
+ ];
+ let is_std_lib = STD_LIBS.iter().any(|l| rest.starts_with(l));
+
+ let new_path = if is_std_lib {
+ real_dir.join("library").join(rest)
+ } else {
+ real_dir.join(rest)
+ };
+
+ debug!(
+ "try_to_translate_virtual_to_real: `{}` -> `{}`",
+ virtual_name.display(),
+ new_path.display(),
+ );
+
+ // Check if the translated real path is affected by any user-requested
+ // remaps via --remap-path-prefix. Apply them if so.
+ // Note that this is a special case for imported rust-src paths specified by
+ // https://rust-lang.github.io/rfcs/3127-trim-paths.html#handling-sysroot-paths.
+ // Other imported paths are not currently remapped (see #66251).
+ let (user_remapped, applied) =
+ sess.source_map().path_mapping().map_prefix(&new_path);
+ let new_name = if applied {
+ rustc_span::RealFileName::Remapped {
+ local_path: Some(new_path.clone()),
+ virtual_name: user_remapped.to_path_buf(),
}
- }
+ } else {
+ rustc_span::RealFileName::LocalPath(new_path)
+ };
+ *old_name = new_name;
}
}
};
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 54cfd995832..ee34ccd889f 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -217,7 +217,7 @@ pub fn early_report_macro_deprecation(
suggestion_span: span,
note: depr.note,
path,
- since_kind: deprecated_since_kind(is_in_effect, depr.since.clone()),
+ since_kind: deprecated_since_kind(is_in_effect, depr.since),
};
lint_buffer.buffer_lint(deprecation_lint(is_in_effect), node_id, span, diag);
}
diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
index 65442877d2d..cc4b7689d40 100644
--- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
@@ -223,14 +223,14 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
// Inherited from the by-ref coroutine.
body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone());
- body_def.constness(tcx.constness(coroutine_def_id).clone());
- body_def.coroutine_kind(tcx.coroutine_kind(coroutine_def_id).clone());
+ body_def.constness(tcx.constness(coroutine_def_id));
+ body_def.coroutine_kind(tcx.coroutine_kind(coroutine_def_id));
body_def.def_ident_span(tcx.def_ident_span(coroutine_def_id));
body_def.def_span(tcx.def_span(coroutine_def_id));
- body_def.explicit_predicates_of(tcx.explicit_predicates_of(coroutine_def_id).clone());
+ body_def.explicit_predicates_of(tcx.explicit_predicates_of(coroutine_def_id));
body_def.generics_of(tcx.generics_of(coroutine_def_id).clone());
- body_def.param_env(tcx.param_env(coroutine_def_id).clone());
- body_def.predicates_of(tcx.predicates_of(coroutine_def_id).clone());
+ body_def.param_env(tcx.param_env(coroutine_def_id));
+ body_def.predicates_of(tcx.predicates_of(coroutine_def_id));
// The type of the coroutine is the `by_move_coroutine_ty`.
body_def.type_of(ty::EarlyBinder::bind(by_move_coroutine_ty));
diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs
index 9884b6dd1c3..277a33c0311 100644
--- a/compiler/rustc_mir_transform/src/single_use_consts.rs
+++ b/compiler/rustc_mir_transform/src/single_use_consts.rs
@@ -185,15 +185,14 @@ impl<'tcx> MutVisitor<'tcx> for LocalReplacer<'tcx> {
&& let Some(local) = place.as_local()
&& local == self.local
{
- let const_op = self
+ let const_op = *self
.operand
.as_ref()
.unwrap_or_else(|| {
bug!("the operand was already stolen");
})
.constant()
- .unwrap()
- .clone();
+ .unwrap();
var_debug_info.value = VarDebugInfoContents::Const(const_op);
}
}
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs
index 3cb7576154f..8fce4266345 100644
--- a/compiler/rustc_pattern_analysis/src/constructor.rs
+++ b/compiler/rustc_pattern_analysis/src/constructor.rs
@@ -735,10 +735,10 @@ impl<Cx: PatCx> Clone for Constructor<Cx> {
Constructor::UnionField => Constructor::UnionField,
Constructor::Bool(b) => Constructor::Bool(*b),
Constructor::IntRange(range) => Constructor::IntRange(*range),
- Constructor::F16Range(lo, hi, end) => Constructor::F16Range(lo.clone(), *hi, *end),
- Constructor::F32Range(lo, hi, end) => Constructor::F32Range(lo.clone(), *hi, *end),
- Constructor::F64Range(lo, hi, end) => Constructor::F64Range(lo.clone(), *hi, *end),
- Constructor::F128Range(lo, hi, end) => Constructor::F128Range(lo.clone(), *hi, *end),
+ Constructor::F16Range(lo, hi, end) => Constructor::F16Range(*lo, *hi, *end),
+ Constructor::F32Range(lo, hi, end) => Constructor::F32Range(*lo, *hi, *end),
+ Constructor::F64Range(lo, hi, end) => Constructor::F64Range(*lo, *hi, *end),
+ Constructor::F128Range(lo, hi, end) => Constructor::F128Range(*lo, *hi, *end),
Constructor::Str(value) => Constructor::Str(value.clone()),
Constructor::Opaque(inner) => Constructor::Opaque(inner.clone()),
Constructor::Or => Constructor::Or,
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 46e30c614ab..582db97e1ce 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1469,11 +1469,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident))| {
- if unused_ident.name == ident.name {
- Some((def_id.clone(), unused_ident.clone()))
- } else {
- None
- }
+ if unused_ident.name == ident.name { Some((def_id, unused_ident)) } else { None }
});
if let Some((def_id, unused_ident)) = unused_macro {
diff --git a/library/Cargo.lock b/library/Cargo.lock
index e883749730c..877ae0cc1cc 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -61,9 +61,9 @@ dependencies = [
[[package]]
name = "compiler_builtins"
-version = "0.1.126"
+version = "0.1.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "758019257ad46e191b587d8f711022a6ac1d1fb6745d75e1d76c587fdcbca770"
+checksum = "e64c30475571756801eff60a811520c3d18e0ceb9c56c97bad2047ae601f6709"
dependencies = [
"cc",
"rustc-std-workspace-core",
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index 1b76b4c4a50..11db50a0fdf 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -10,7 +10,7 @@ edition = "2021"
[dependencies]
core = { path = "../core" }
-compiler_builtins = { version = "0.1.126", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "0.1.130", features = ['rustc-dep-of-std'] }
[dev-dependencies]
rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
diff --git a/library/alloc/benches/str.rs b/library/alloc/benches/str.rs
index f020638e992..98c7c5413ca 100644
--- a/library/alloc/benches/str.rs
+++ b/library/alloc/benches/str.rs
@@ -347,3 +347,5 @@ make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count());
make_test!(split_space_str, s, s.split(" ").count());
make_test!(split_ad_str, s, s.split("ad").count());
+
+make_test!(to_lowercase, s, s.to_lowercase());
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index f636f10d5c0..a92d22b1c30 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -180,10 +180,9 @@ impl<T> [T] {
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*))
/// worst-case.
///
- /// If the implementation of [`Ord`] for `T` does not implement a [total order] the resulting
- /// order of elements in the slice is unspecified. All original elements will remain in the
- /// slice and any possible modifications via interior mutability are observed in the input. Same
- /// is true if the implementation of [`Ord`] for `T` panics.
+ /// If the implementation of [`Ord`] for `T` does not implement a [total order], the function
+ /// may panic; even if the function exits normally, the resulting order of elements in the slice
+ /// is unspecified. See also the note on panicking below.
///
/// When applicable, unstable sorting is preferred because it is generally faster than stable
/// sorting and it doesn't allocate auxiliary memory. See
@@ -212,7 +211,15 @@ impl<T> [T] {
///
/// # Panics
///
- /// May panic if the implementation of [`Ord`] for `T` does not implement a [total order].
+ /// May panic if the implementation of [`Ord`] for `T` does not implement a [total order], or if
+ /// the [`Ord`] implementation itself panics.
+ ///
+ /// All safe functions on slices preserve the invariant that even if the function panics, all
+ /// original elements will remain in the slice and any possible modifications via interior
+ /// mutability are observed in the input. This ensures that recovery code (for instance inside
+ /// of a `Drop` or following a `catch_unwind`) will still have access to all the original
+ /// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able
+ /// to dispose of all contained elements.
///
/// # Examples
///
@@ -241,10 +248,9 @@ impl<T> [T] {
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*))
/// worst-case.
///
- /// If the comparison function `compare` does not implement a [total order] the resulting order
- /// of elements in the slice is unspecified. All original elements will remain in the slice and
- /// any possible modifications via interior mutability are observed in the input. Same is true
- /// if `compare` panics.
+ /// If the comparison function `compare` does not implement a [total order], the function may
+ /// panic; even if the function exits normally, the resulting order of elements in the slice is
+ /// unspecified. See also the note on panicking below.
///
/// For example `|a, b| (a - b).cmp(a)` is a comparison function that is neither transitive nor
/// reflexive nor total, `a < b < c < a` with `a = 1, b = 2, c = 3`. For more information and
@@ -263,7 +269,14 @@ impl<T> [T] {
///
/// # Panics
///
- /// May panic if `compare` does not implement a [total order].
+ /// May panic if `compare` does not implement a [total order], or if `compare` itself panics.
+ ///
+ /// All safe functions on slices preserve the invariant that even if the function panics, all
+ /// original elements will remain in the slice and any possible modifications via interior
+ /// mutability are observed in the input. This ensures that recovery code (for instance inside
+ /// of a `Drop` or following a `catch_unwind`) will still have access to all the original
+ /// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able
+ /// to dispose of all contained elements.
///
/// # Examples
///
@@ -295,10 +308,9 @@ impl<T> [T] {
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* \* log(*n*))
/// worst-case, where the key function is *O*(*m*).
///
- /// If the implementation of [`Ord`] for `K` does not implement a [total order] the resulting
- /// order of elements in the slice is unspecified. All original elements will remain in the
- /// slice and any possible modifications via interior mutability are observed in the input. Same
- /// is true if the implementation of [`Ord`] for `K` panics.
+ /// If the implementation of [`Ord`] for `K` does not implement a [total order], the function
+ /// may panic; even if the function exits normally, the resulting order of elements in the slice
+ /// is unspecified. See also the note on panicking below.
///
/// # Current implementation
///
@@ -313,7 +325,15 @@ impl<T> [T] {
///
/// # Panics
///
- /// May panic if the implementation of [`Ord`] for `K` does not implement a [total order].
+ /// May panic if the implementation of [`Ord`] for `K` does not implement a [total order], or if
+ /// the [`Ord`] implementation or the key-function `f` panics.
+ ///
+ /// All safe functions on slices preserve the invariant that even if the function panics, all
+ /// original elements will remain in the slice and any possible modifications via interior
+ /// mutability are observed in the input. This ensures that recovery code (for instance inside
+ /// of a `Drop` or following a `catch_unwind`) will still have access to all the original
+ /// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able
+ /// to dispose of all contained elements.
///
/// # Examples
///
@@ -347,10 +367,9 @@ impl<T> [T] {
/// storage to remember the results of key evaluation. The order of calls to the key function is
/// unspecified and may change in future versions of the standard library.
///
- /// If the implementation of [`Ord`] for `K` does not implement a [total order] the resulting
- /// order of elements in the slice is unspecified. All original elements will remain in the
- /// slice and any possible modifications via interior mutability are observed in the input. Same
- /// is true if the implementation of [`Ord`] for `K` panics.
+ /// If the implementation of [`Ord`] for `K` does not implement a [total order], the function
+ /// may panic; even if the function exits normally, the resulting order of elements in the slice
+ /// is unspecified. See also the note on panicking below.
///
/// For simple key functions (e.g., functions that are property accesses or basic operations),
/// [`sort_by_key`](slice::sort_by_key) is likely to be faster.
@@ -369,7 +388,15 @@ impl<T> [T] {
///
/// # Panics
///
- /// May panic if the implementation of [`Ord`] for `K` does not implement a [total order].
+ /// May panic if the implementation of [`Ord`] for `K` does not implement a [total order], or if
+ /// the [`Ord`] implementation panics.
+ ///
+ /// All safe functions on slices preserve the invariant that even if the function panics, all
+ /// original elements will remain in the slice and any possible modifications via interior
+ /// mutability are observed in the input. This ensures that recovery code (for instance inside
+ /// of a `Drop` or following a `catch_unwind`) will still have access to all the original
+ /// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able
+ /// to dispose of all contained elements.
///
/// # Examples
///
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 32212b61c6e..42501f9c315 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -9,6 +9,7 @@
use core::borrow::{Borrow, BorrowMut};
use core::iter::FusedIterator;
+use core::mem::MaybeUninit;
#[stable(feature = "encode_utf16", since = "1.8.0")]
pub use core::str::EncodeUtf16;
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
@@ -365,14 +366,9 @@ impl str {
without modifying the original"]
#[stable(feature = "unicode_case_mapping", since = "1.2.0")]
pub fn to_lowercase(&self) -> String {
- let out = convert_while_ascii(self.as_bytes(), u8::to_ascii_lowercase);
+ let (mut s, rest) = convert_while_ascii(self, u8::to_ascii_lowercase);
- // Safety: we know this is a valid char boundary since
- // out.len() is only progressed if ascii bytes are found
- let rest = unsafe { self.get_unchecked(out.len()..) };
-
- // Safety: We have written only valid ASCII to our vec
- let mut s = unsafe { String::from_utf8_unchecked(out) };
+ let prefix_len = s.len();
for (i, c) in rest.char_indices() {
if c == 'Σ' {
@@ -381,8 +377,7 @@ impl str {
// in `SpecialCasing.txt`,
// so hard-code it rather than have a generic "condition" mechanism.
// See https://github.com/rust-lang/rust/issues/26035
- let out_len = self.len() - rest.len();
- let sigma_lowercase = map_uppercase_sigma(&self, i + out_len);
+ let sigma_lowercase = map_uppercase_sigma(self, prefix_len + i);
s.push(sigma_lowercase);
} else {
match conversions::to_lower(c) {
@@ -458,14 +453,7 @@ impl str {
without modifying the original"]
#[stable(feature = "unicode_case_mapping", since = "1.2.0")]
pub fn to_uppercase(&self) -> String {
- let out = convert_while_ascii(self.as_bytes(), u8::to_ascii_uppercase);
-
- // Safety: we know this is a valid char boundary since
- // out.len() is only progressed if ascii bytes are found
- let rest = unsafe { self.get_unchecked(out.len()..) };
-
- // Safety: We have written only valid ASCII to our vec
- let mut s = unsafe { String::from_utf8_unchecked(out) };
+ let (mut s, rest) = convert_while_ascii(self, u8::to_ascii_uppercase);
for c in rest.chars() {
match conversions::to_upper(c) {
@@ -614,50 +602,87 @@ pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> {
unsafe { Box::from_raw(Box::into_raw(v) as *mut str) }
}
-/// Converts the bytes while the bytes are still ascii.
+/// Converts leading ascii bytes in `s` by calling the `convert` function.
+///
/// For better average performance, this happens in chunks of `2*size_of::<usize>()`.
-/// Returns a vec with the converted bytes.
+///
+/// Returns a tuple of the converted prefix and the remainder starting from
+/// the first non-ascii character.
+///
+/// This function is only public so that it can be verified in a codegen test,
+/// see `issue-123712-str-to-lower-autovectorization.rs`.
+#[unstable(feature = "str_internals", issue = "none")]
+#[doc(hidden)]
#[inline]
#[cfg(not(test))]
#[cfg(not(no_global_oom_handling))]
-fn convert_while_ascii(b: &[u8], convert: fn(&u8) -> u8) -> Vec<u8> {
- let mut out = Vec::with_capacity(b.len());
+pub fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, &str) {
+ // Process the input in chunks of 16 bytes to enable auto-vectorization.
+ // Previously the chunk size depended on the size of `usize`,
+ // but on 32-bit platforms with sse or neon is also the better choice.
+ // The only downside on other platforms would be a bit more loop-unrolling.
+ const N: usize = 16;
+
+ let mut slice = s.as_bytes();
+ let mut out = Vec::with_capacity(slice.len());
+ let mut out_slice = out.spare_capacity_mut();
+
+ let mut ascii_prefix_len = 0_usize;
+ let mut is_ascii = [false; N];
+
+ while slice.len() >= N {
+ // SAFETY: checked in loop condition
+ let chunk = unsafe { slice.get_unchecked(..N) };
+ // SAFETY: out_slice has at least same length as input slice and gets sliced with the same offsets
+ let out_chunk = unsafe { out_slice.get_unchecked_mut(..N) };
+
+ for j in 0..N {
+ is_ascii[j] = chunk[j] <= 127;
+ }
- const USIZE_SIZE: usize = mem::size_of::<usize>();
- const MAGIC_UNROLL: usize = 2;
- const N: usize = USIZE_SIZE * MAGIC_UNROLL;
- const NONASCII_MASK: usize = usize::from_ne_bytes([0x80; USIZE_SIZE]);
+ // Auto-vectorization for this check is a bit fragile, sum and comparing against the chunk
+ // size gives the best result, specifically a pmovmsk instruction on x86.
+ // See https://github.com/llvm/llvm-project/issues/96395 for why llvm currently does not
+ // currently recognize other similar idioms.
+ if is_ascii.iter().map(|x| *x as u8).sum::<u8>() as usize != N {
+ break;
+ }
- let mut i = 0;
- unsafe {
- while i + N <= b.len() {
- // Safety: we have checks the sizes `b` and `out` to know that our
- let in_chunk = b.get_unchecked(i..i + N);
- let out_chunk = out.spare_capacity_mut().get_unchecked_mut(i..i + N);
-
- let mut bits = 0;
- for j in 0..MAGIC_UNROLL {
- // read the bytes 1 usize at a time (unaligned since we haven't checked the alignment)
- // safety: in_chunk is valid bytes in the range
- bits |= in_chunk.as_ptr().cast::<usize>().add(j).read_unaligned();
- }
- // if our chunks aren't ascii, then return only the prior bytes as init
- if bits & NONASCII_MASK != 0 {
- break;
- }
+ for j in 0..N {
+ out_chunk[j] = MaybeUninit::new(convert(&chunk[j]));
+ }
- // perform the case conversions on N bytes (gets heavily autovec'd)
- for j in 0..N {
- // safety: in_chunk and out_chunk is valid bytes in the range
- let out = out_chunk.get_unchecked_mut(j);
- out.write(convert(in_chunk.get_unchecked(j)));
- }
+ ascii_prefix_len += N;
+ slice = unsafe { slice.get_unchecked(N..) };
+ out_slice = unsafe { out_slice.get_unchecked_mut(N..) };
+ }
- // mark these bytes as initialised
- i += N;
+ // handle the remainder as individual bytes
+ while slice.len() > 0 {
+ let byte = slice[0];
+ if byte > 127 {
+ break;
+ }
+ // SAFETY: out_slice has at least same length as input slice
+ unsafe {
+ *out_slice.get_unchecked_mut(0) = MaybeUninit::new(convert(&byte));
}
- out.set_len(i);
+ ascii_prefix_len += 1;
+ slice = unsafe { slice.get_unchecked(1..) };
+ out_slice = unsafe { out_slice.get_unchecked_mut(1..) };
}
- out
+ unsafe {
+ // SAFETY: ascii_prefix_len bytes have been initialized above
+ out.set_len(ascii_prefix_len);
+
+ // SAFETY: We have written only valid ascii to the output vec
+ let ascii_string = String::from_utf8_unchecked(out);
+
+ // SAFETY: we know this is a valid char boundary
+ // since we only skipped over leading ascii bytes
+ let rest = core::str::from_utf8_unchecked(slice);
+
+ (ascii_string, rest)
+ }
}
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index a80e5275dab..6f930ab0853 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -1854,7 +1854,10 @@ fn to_lowercase() {
assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
// https://github.com/rust-lang/rust/issues/124714
+ // input lengths around the boundary of the chunk size used by the ascii prefix optimization
+ assert_eq!("abcdefghijklmnoΣ".to_lowercase(), "abcdefghijklmnoς");
assert_eq!("abcdefghijklmnopΣ".to_lowercase(), "abcdefghijklmnopς");
+ assert_eq!("abcdefghijklmnopqΣ".to_lowercase(), "abcdefghijklmnopqς");
// a really long string that has it's lowercase form
// even longer. this tests that implementations don't assume
diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs
index a6f799c4a7d..68f00d07529 100644
--- a/library/core/src/alloc/global.rs
+++ b/library/core/src/alloc/global.rs
@@ -124,8 +124,8 @@ pub unsafe trait GlobalAlloc {
///
/// # Safety
///
- /// This function is unsafe because undefined behavior can result
- /// if the caller does not ensure that `layout` has non-zero size.
+ /// `layout` must have non-zero size. Attempting to allocate for a zero-sized `layout` may
+ /// result in undefined behavior.
///
/// (Extension subtraits might provide more specific bounds on
/// behavior, e.g., guarantee a sentinel address or a null pointer
@@ -156,14 +156,14 @@ pub unsafe trait GlobalAlloc {
///
/// # Safety
///
- /// This function is unsafe because undefined behavior can result
- /// if the caller does not ensure all of the following:
+ /// The caller must ensure:
///
- /// * `ptr` must denote a block of memory currently allocated via
- /// this allocator,
+ /// * `ptr` is a block of memory currently allocated via this allocator and,
///
- /// * `layout` must be the same layout that was used
- /// to allocate that block of memory.
+ /// * `layout` is the same layout that was used to allocate that block of
+ /// memory.
+ ///
+ /// Otherwise undefined behavior can result.
#[stable(feature = "global_alloc", since = "1.28.0")]
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout);
@@ -172,7 +172,8 @@ pub unsafe trait GlobalAlloc {
///
/// # Safety
///
- /// This function is unsafe for the same reasons that `alloc` is.
+ /// The caller has to ensure that `layout` has non-zero size. Like `alloc`
+ /// zero sized `layout` can result in undefined behaviour.
/// However the allocated block of memory is guaranteed to be initialized.
///
/// # Errors
@@ -220,20 +221,21 @@ pub unsafe trait GlobalAlloc {
///
/// # Safety
///
- /// This function is unsafe because undefined behavior can result
- /// if the caller does not ensure all of the following:
+ /// The caller must ensure that:
///
- /// * `ptr` must be currently allocated via this allocator,
+ /// * `ptr` is allocated via this allocator,
///
- /// * `layout` must be the same layout that was used
+ /// * `layout` is the same layout that was used
/// to allocate that block of memory,
///
- /// * `new_size` must be greater than zero.
+ /// * `new_size` is greater than zero.
///
/// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
- /// must not overflow `isize` (i.e., the rounded value must be less than or
+ /// does not overflow `isize` (i.e., the rounded value must be less than or
/// equal to `isize::MAX`).
///
+ /// If these are not followed, undefined behaviour can result.
+ ///
/// (Extension subtraits might provide more specific bounds on
/// behavior, e.g., guarantee a sentinel address or a null pointer
/// in response to a zero-size allocation request.)
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index c99f1aece4f..de212581e82 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -514,7 +514,8 @@ impl<T> Cell<T> {
/// assert_eq!(five, 5);
/// ```
#[stable(feature = "move_cell", since = "1.17.0")]
- #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")]
+ #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_allow_const_fn_unstable(const_precise_live_drops)]
pub const fn into_inner(self) -> T {
self.value.into_inner()
}
@@ -857,7 +858,8 @@ impl<T> RefCell<T> {
/// let five = c.into_inner();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")]
+ #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_allow_const_fn_unstable(const_precise_live_drops)]
#[inline]
pub const fn into_inner(self) -> T {
// Since this function takes `self` (the `RefCell`) by value, the
@@ -2100,8 +2102,8 @@ impl<T> UnsafeCell<T> {
/// ```
#[inline(always)]
#[stable(feature = "rust1", since = "1.0.0")]
- // When this is const stabilized, please remove `primitive_into_inner` below.
- #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")]
+ #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_allow_const_fn_unstable(const_precise_live_drops)]
pub const fn into_inner(self) -> T {
self.value
}
@@ -2247,47 +2249,6 @@ impl<T: CoerceUnsized<U>, U> CoerceUnsized<UnsafeCell<U>> for UnsafeCell<T> {}
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<UnsafeCell<U>> for UnsafeCell<T> {}
-// Special cases of UnsafeCell::into_inner where T is a primitive. These are
-// used by Atomic*::into_inner.
-//
-// The real UnsafeCell::into_inner cannot be used yet in a stable const function.
-// That is blocked on a "precise drop analysis" unstable const feature.
-// https://github.com/rust-lang/rust/issues/73255
-macro_rules! unsafe_cell_primitive_into_inner {
- ($($primitive:ident $atomic:literal)*) => {
- $(
- #[cfg(target_has_atomic_load_store = $atomic)]
- impl UnsafeCell<$primitive> {
- pub(crate) const fn primitive_into_inner(self) -> $primitive {
- self.value
- }
- }
- )*
- };
-}
-
-unsafe_cell_primitive_into_inner! {
- i8 "8"
- u8 "8"
- i16 "16"
- u16 "16"
- i32 "32"
- u32 "32"
- i64 "64"
- u64 "64"
- i128 "128"
- u128 "128"
- isize "ptr"
- usize "ptr"
-}
-
-#[cfg(target_has_atomic_load_store = "ptr")]
-impl<T> UnsafeCell<*mut T> {
- pub(crate) const fn primitive_into_inner(self) -> *mut T {
- self.value
- }
-}
-
/// [`UnsafeCell`], but [`Sync`].
///
/// This is just an `UnsafeCell`, except it implements `Sync`
diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs
index 87df8a4e272..14c587e0c48 100644
--- a/library/core/src/cell/once.rs
+++ b/library/core/src/cell/once.rs
@@ -309,7 +309,8 @@ impl<T> OnceCell<T> {
/// ```
#[inline]
#[stable(feature = "once_cell", since = "1.70.0")]
- #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")]
+ #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_allow_const_fn_unstable(const_precise_live_drops)]
pub const fn into_inner(self) -> Option<T> {
// Because `into_inner` takes `self` by value, the compiler statically verifies
// that it is not currently borrowed. So it is safe to move out `Option<T>`.
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 818a36002e7..4377b4993b8 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -275,49 +275,56 @@ pub macro PartialEq($item:item) {
/// Trait for comparisons corresponding to [equivalence relations](
/// https://en.wikipedia.org/wiki/Equivalence_relation).
///
-/// This means, that in addition to `a == b` and `a != b` being strict inverses,
-/// the relation must be (for all `a`, `b` and `c`):
+/// The primary difference to [`PartialEq`] is the additional requirement for reflexivity. A type
+/// that implements [`PartialEq`] guarantees that for all `a`, `b` and `c`:
///
-/// - reflexive: `a == a`;
-/// - symmetric: `a == b` implies `b == a` (required by `PartialEq` as well); and
-/// - transitive: `a == b` and `b == c` implies `a == c` (required by `PartialEq` as well).
+/// - symmetric: `a == b` implies `b == a` and `a != b` implies `!(a == b)`
+/// - transitive: `a == b` and `b == c` implies `a == c`
///
-/// This property cannot be checked by the compiler, and therefore `Eq` implies
-/// [`PartialEq`], and has no extra methods.
+/// `Eq`, which builds on top of [`PartialEq`] also implies:
+///
+/// - reflexive: `a == a`
+///
+/// This property cannot be checked by the compiler, and therefore `Eq` is a trait without methods.
///
/// Violating this property is a logic error. The behavior resulting from a logic error is not
/// specified, but users of the trait must ensure that such logic errors do *not* result in
/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these
/// methods.
///
-/// Implement `Eq` in addition to `PartialEq` if it's guaranteed that
-/// `PartialEq::eq(a, a)` always returns `true` (reflexivity), in addition to
-/// the symmetric and transitive properties already required by `PartialEq`.
+/// Floating point types such as [`f32`] and [`f64`] implement only [`PartialEq`] but *not* `Eq`
+/// because `NaN` != `NaN`.
///
/// ## Derivable
///
-/// This trait can be used with `#[derive]`. When `derive`d, because `Eq` has
-/// no extra methods, it is only informing the compiler that this is an
-/// equivalence relation rather than a partial equivalence relation. Note that
-/// the `derive` strategy requires all fields are `Eq`, which isn't
+/// This trait can be used with `#[derive]`. When `derive`d, because `Eq` has no extra methods, it
+/// is only informing the compiler that this is an equivalence relation rather than a partial
+/// equivalence relation. Note that the `derive` strategy requires all fields are `Eq`, which isn't
/// always desired.
///
/// ## How can I implement `Eq`?
///
-/// If you cannot use the `derive` strategy, specify that your type implements
-/// `Eq`, which has no methods:
+/// If you cannot use the `derive` strategy, specify that your type implements `Eq`, which has no
+/// extra methods:
///
/// ```
-/// enum BookFormat { Paperback, Hardback, Ebook }
+/// enum BookFormat {
+/// Paperback,
+/// Hardback,
+/// Ebook,
+/// }
+///
/// struct Book {
/// isbn: i32,
/// format: BookFormat,
/// }
+///
/// impl PartialEq for Book {
/// fn eq(&self, other: &Self) -> bool {
/// self.isbn == other.isbn
/// }
/// }
+///
/// impl Eq for Book {}
/// ```
#[doc(alias = "==")]
@@ -325,11 +332,9 @@ pub macro PartialEq($item:item) {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "Eq"]
pub trait Eq: PartialEq<Self> {
- // this method is used solely by #[derive(Eq)] to assert
- // that every component of a type implements `Eq`
- // itself. The current deriving infrastructure means doing this
- // assertion without using a method on this trait is nearly
- // impossible.
+ // this method is used solely by `impl Eq or #[derive(Eq)]` to assert that every component of a
+ // type implements `Eq` itself. The current deriving infrastructure means doing this assertion
+ // without using a method on this trait is nearly impossible.
//
// This should never be implemented by hand.
#[doc(hidden)]
@@ -693,17 +698,14 @@ impl<T: Clone> Clone for Reverse<T> {
/// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
///
-/// Implementations must be consistent with the [`PartialOrd`] implementation, and ensure
-/// `max`, `min`, and `clamp` are consistent with `cmp`:
+/// Implementations must be consistent with the [`PartialOrd`] implementation, and ensure `max`,
+/// `min`, and `clamp` are consistent with `cmp`:
///
/// - `partial_cmp(a, b) == Some(cmp(a, b))`.
/// - `max(a, b) == max_by(a, b, cmp)` (ensured by the default implementation).
/// - `min(a, b) == min_by(a, b, cmp)` (ensured by the default implementation).
-/// - For `a.clamp(min, max)`, see the [method docs](#method.clamp)
-/// (ensured by the default implementation).
-///
-/// It's easy to accidentally make `cmp` and `partial_cmp` disagree by
-/// deriving some of the traits and manually implementing others.
+/// - For `a.clamp(min, max)`, see the [method docs](#method.clamp) (ensured by the default
+/// implementation).
///
/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
/// specified, but users of the trait must ensure that such logic errors do *not* result in
@@ -712,15 +714,14 @@ impl<T: Clone> Clone for Reverse<T> {
///
/// ## Corollaries
///
-/// From the above and the requirements of `PartialOrd`, it follows that for
-/// all `a`, `b` and `c`:
+/// From the above and the requirements of `PartialOrd`, it follows that for all `a`, `b` and `c`:
///
/// - exactly one of `a < b`, `a == b` or `a > b` is true; and
-/// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
+/// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and
+/// `>`.
///
-/// Mathematically speaking, the `<` operator defines a strict [weak order]. In
-/// cases where `==` conforms to mathematical equality, it also defines a
-/// strict [total order].
+/// Mathematically speaking, the `<` operator defines a strict [weak order]. In cases where `==`
+/// conforms to mathematical equality, it also defines a strict [total order].
///
/// [weak order]: https://en.wikipedia.org/wiki/Weak_ordering
/// [total order]: https://en.wikipedia.org/wiki/Total_order
@@ -730,13 +731,12 @@ impl<T: Clone> Clone for Reverse<T> {
/// This trait can be used with `#[derive]`.
///
/// When `derive`d on structs, it will produce a
-/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering
-/// based on the top-to-bottom declaration order of the struct's members.
+/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering based on the
+/// top-to-bottom declaration order of the struct's members.
///
-/// When `derive`d on enums, variants are ordered primarily by their discriminants.
-/// Secondarily, they are ordered by their fields.
-/// By default, the discriminant is smallest for variants at the top, and
-/// largest for variants at the bottom. Here's an example:
+/// When `derive`d on enums, variants are ordered primarily by their discriminants. Secondarily,
+/// they are ordered by their fields. By default, the discriminant is smallest for variants at the
+/// top, and largest for variants at the bottom. Here's an example:
///
/// ```
/// #[derive(PartialEq, Eq, PartialOrd, Ord)]
@@ -748,8 +748,7 @@ impl<T: Clone> Clone for Reverse<T> {
/// assert!(E::Top < E::Bottom);
/// ```
///
-/// However, manually setting the discriminants can override this default
-/// behavior:
+/// However, manually setting the discriminants can override this default behavior:
///
/// ```
/// #[derive(PartialEq, Eq, PartialOrd, Ord)]
@@ -765,51 +764,178 @@ impl<T: Clone> Clone for Reverse<T> {
///
/// Lexicographical comparison is an operation with the following properties:
/// - Two sequences are compared element by element.
-/// - The first mismatching element defines which sequence is lexicographically less or greater than the other.
-/// - If one sequence is a prefix of another, the shorter sequence is lexicographically less than the other.
-/// - If two sequences have equivalent elements and are of the same length, then the sequences are lexicographically equal.
+/// - The first mismatching element defines which sequence is lexicographically less or greater
+/// than the other.
+/// - If one sequence is a prefix of another, the shorter sequence is lexicographically less than
+/// the other.
+/// - If two sequences have equivalent elements and are of the same length, then the sequences are
+/// lexicographically equal.
/// - An empty sequence is lexicographically less than any non-empty sequence.
/// - Two empty sequences are lexicographically equal.
///
/// ## How can I implement `Ord`?
///
-/// `Ord` requires that the type also be [`PartialOrd`] and [`Eq`] (which requires [`PartialEq`]).
+/// `Ord` requires that the type also be [`PartialOrd`], [`PartialEq`], and [`Eq`].
///
-/// Then you must define an implementation for [`cmp`]. You may find it useful to use
-/// [`cmp`] on your type's fields.
+/// Because `Ord` implies a stronger ordering relationship than [`PartialOrd`], and both `Ord` and
+/// [`PartialOrd`] must agree, you must choose how to implement `Ord` **first**. You can choose to
+/// derive it, or implement it manually. If you derive it, you should derive all four traits. If you
+/// implement it manually, you should manually implement all four traits, based on the
+/// implementation of `Ord`.
///
-/// Here's an example where you want to sort people by height only, disregarding `id`
-/// and `name`:
+/// Here's an example where you want to define the `Character` comparison by `health` and
+/// `experience` only, disregarding the field `mana`:
///
/// ```
/// use std::cmp::Ordering;
///
-/// #[derive(Eq)]
-/// struct Person {
-/// id: u32,
-/// name: String,
-/// height: u32,
+/// struct Character {
+/// health: u32,
+/// experience: u32,
+/// mana: f32,
/// }
///
-/// impl Ord for Person {
-/// fn cmp(&self, other: &Self) -> Ordering {
-/// self.height.cmp(&other.height)
+/// impl Ord for Character {
+/// fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+/// self.experience
+/// .cmp(&other.experience)
+/// .then(self.health.cmp(&other.health))
/// }
/// }
///
-/// impl PartialOrd for Person {
+/// impl PartialOrd for Character {
/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
/// Some(self.cmp(other))
/// }
/// }
///
-/// impl PartialEq for Person {
+/// impl PartialEq for Character {
/// fn eq(&self, other: &Self) -> bool {
-/// self.height == other.height
+/// self.health == other.health && self.experience == other.experience
+/// }
+/// }
+///
+/// impl Eq for Character {}
+/// ```
+///
+/// If all you need is to `slice::sort` a type by a field value, it can be simpler to use
+/// `slice::sort_by_key`.
+///
+/// ## Examples of incorrect `Ord` implementations
+///
+/// ```
+/// use std::cmp::Ordering;
+///
+/// #[derive(Debug)]
+/// struct Character {
+/// health: f32,
+/// }
+///
+/// impl Ord for Character {
+/// fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+/// if self.health < other.health {
+/// Ordering::Less
+/// } else if self.health > other.health {
+/// Ordering::Greater
+/// } else {
+/// Ordering::Equal
+/// }
+/// }
+/// }
+///
+/// impl PartialOrd for Character {
+/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+/// Some(self.cmp(other))
+/// }
+/// }
+///
+/// impl PartialEq for Character {
+/// fn eq(&self, other: &Self) -> bool {
+/// self.health == other.health
+/// }
+/// }
+///
+/// impl Eq for Character {}
+///
+/// let a = Character { health: 4.5 };
+/// let b = Character { health: f32::NAN };
+///
+/// // Mistake: floating-point values do not form a total order and using the built-in comparison
+/// // operands to implement `Ord` irregardless of that reality does not change it. Use
+/// // `f32::total_cmp` if you need a total order for floating-point values.
+///
+/// // Reflexivity requirement of `Ord` is not given.
+/// assert!(a == a);
+/// assert!(b != b);
+///
+/// // Antisymmetry requirement of `Ord` is not given. Only one of a < c and c < a is allowed to be
+/// // true, not both or neither.
+/// assert_eq!((a < b) as u8 + (b < a) as u8, 0);
+/// ```
+///
+/// ```
+/// use std::cmp::Ordering;
+///
+/// #[derive(Debug)]
+/// struct Character {
+/// health: u32,
+/// experience: u32,
+/// }
+///
+/// impl PartialOrd for Character {
+/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+/// Some(self.cmp(other))
+/// }
+/// }
+///
+/// impl Ord for Character {
+/// fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+/// if self.health < 50 {
+/// self.health.cmp(&other.health)
+/// } else {
+/// self.experience.cmp(&other.experience)
+/// }
+/// }
+/// }
+///
+/// // For performance reasons implementing `PartialEq` this way is not the idiomatic way, but it
+/// // ensures consistent behavior between `PartialEq`, `PartialOrd` and `Ord` in this example.
+/// impl PartialEq for Character {
+/// fn eq(&self, other: &Self) -> bool {
+/// self.cmp(other) == Ordering::Equal
/// }
/// }
+///
+/// impl Eq for Character {}
+///
+/// let a = Character {
+/// health: 3,
+/// experience: 5,
+/// };
+/// let b = Character {
+/// health: 10,
+/// experience: 77,
+/// };
+/// let c = Character {
+/// health: 143,
+/// experience: 2,
+/// };
+///
+/// // Mistake: The implementation of `Ord` compares different fields depending on the value of
+/// // `self.health`, the resulting order is not total.
+///
+/// // Transitivity requirement of `Ord` is not given. If a is smaller than b and b is smaller than
+/// // c, by transitive property a must also be smaller than c.
+/// assert!(a < b && b < c && c < a);
+///
+/// // Antisymmetry requirement of `Ord` is not given. Only one of a < c and c < a is allowed to be
+/// // true, not both or neither.
+/// assert_eq!((a < c) as u8 + (c < a) as u8, 2);
/// ```
///
+/// The documentation of [`PartialOrd`] contains further examples, for example it's wrong for
+/// [`PartialOrd`] and [`PartialEq`] to disagree.
+///
/// [`cmp`]: Ord::cmp
#[doc(alias = "<")]
#[doc(alias = ">")]
@@ -924,8 +1050,12 @@ pub macro Ord($item:item) {
/// Trait for types that form a [partial order](https://en.wikipedia.org/wiki/Partial_order).
///
-/// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using
-/// the `<`, `<=`, `>`, and `>=` operators, respectively.
+/// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using the `<`, `<=`, `>`, and
+/// `>=` operators, respectively.
+///
+/// This trait should **only** contain the comparison logic for a type **if one plans on only
+/// implementing `PartialOrd` but not [`Ord`]**. Otherwise the comparison logic should be in [`Ord`]
+/// and this trait implemented with `Some(self.cmp(other))`.
///
/// The methods of this trait must be consistent with each other and with those of [`PartialEq`].
/// The following conditions must hold:
@@ -937,26 +1067,25 @@ pub macro Ord($item:item) {
/// 5. `a >= b` if and only if `a > b || a == b`
/// 6. `a != b` if and only if `!(a == b)`.
///
-/// Conditions 2–5 above are ensured by the default implementation.
-/// Condition 6 is already ensured by [`PartialEq`].
+/// Conditions 2–5 above are ensured by the default implementation. Condition 6 is already ensured
+/// by [`PartialEq`].
///
/// If [`Ord`] is also implemented for `Self` and `Rhs`, it must also be consistent with
-/// `partial_cmp` (see the documentation of that trait for the exact requirements). It's
-/// easy to accidentally make them disagree by deriving some of the traits and manually
-/// implementing others.
+/// `partial_cmp` (see the documentation of that trait for the exact requirements). It's easy to
+/// accidentally make them disagree by deriving some of the traits and manually implementing others.
///
-/// The comparison relations must satisfy the following conditions
-/// (for all `a`, `b`, `c` of type `A`, `B`, `C`):
+/// The comparison relations must satisfy the following conditions (for all `a`, `b`, `c` of type
+/// `A`, `B`, `C`):
///
-/// - **Transitivity**: if `A: PartialOrd<B>` and `B: PartialOrd<C>` and `A:
-/// PartialOrd<C>`, then `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
-/// This must also work for longer chains, such as when `A: PartialOrd<B>`, `B: PartialOrd<C>`,
-/// `C: PartialOrd<D>`, and `A: PartialOrd<D>` all exist.
-/// - **Duality**: if `A: PartialOrd<B>` and `B: PartialOrd<A>`, then `a < b` if and only if `b > a`.
+/// - **Transitivity**: if `A: PartialOrd<B>` and `B: PartialOrd<C>` and `A: PartialOrd<C>`, then `a
+/// < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. This must also
+/// work for longer chains, such as when `A: PartialOrd<B>`, `B: PartialOrd<C>`, `C:
+/// PartialOrd<D>`, and `A: PartialOrd<D>` all exist.
+/// - **Duality**: if `A: PartialOrd<B>` and `B: PartialOrd<A>`, then `a < b` if and only if `b >
+/// a`.
///
-/// Note that the `B: PartialOrd<A>` (dual) and `A: PartialOrd<C>`
-/// (transitive) impls are not forced to exist, but these requirements apply
-/// whenever they do exist.
+/// Note that the `B: PartialOrd<A>` (dual) and `A: PartialOrd<C>` (transitive) impls are not forced
+/// to exist, but these requirements apply whenever they do exist.
///
/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
/// specified, but users of the trait must ensure that such logic errors do *not* result in
@@ -992,12 +1121,10 @@ pub macro Ord($item:item) {
///
/// ## Strict and non-strict partial orders
///
-/// The `<` and `>` operators behave according to a *strict* partial order.
-/// However, `<=` and `>=` do **not** behave according to a *non-strict*
-/// partial order.
-/// That is because mathematically, a non-strict partial order would require
-/// reflexivity, i.e. `a <= a` would need to be true for every `a`. This isn't
-/// always the case for types that implement `PartialOrd`, for example:
+/// The `<` and `>` operators behave according to a *strict* partial order. However, `<=` and `>=`
+/// do **not** behave according to a *non-strict* partial order. That is because mathematically, a
+/// non-strict partial order would require reflexivity, i.e. `a <= a` would need to be true for
+/// every `a`. This isn't always the case for types that implement `PartialOrd`, for example:
///
/// ```
/// let a = f64::sqrt(-1.0);
@@ -1009,13 +1136,12 @@ pub macro Ord($item:item) {
/// This trait can be used with `#[derive]`.
///
/// When `derive`d on structs, it will produce a
-/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering
-/// based on the top-to-bottom declaration order of the struct's members.
+/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering based on the
+/// top-to-bottom declaration order of the struct's members.
///
-/// When `derive`d on enums, variants are primarily ordered by their discriminants.
-/// Secondarily, they are ordered by their fields.
-/// By default, the discriminant is smallest for variants at the top, and
-/// largest for variants at the bottom. Here's an example:
+/// When `derive`d on enums, variants are primarily ordered by their discriminants. Secondarily,
+/// they are ordered by their fields. By default, the discriminant is smallest for variants at the
+/// top, and largest for variants at the bottom. Here's an example:
///
/// ```
/// #[derive(PartialEq, PartialOrd)]
@@ -1027,8 +1153,7 @@ pub macro Ord($item:item) {
/// assert!(E::Top < E::Bottom);
/// ```
///
-/// However, manually setting the discriminants can override this default
-/// behavior:
+/// However, manually setting the discriminants can override this default behavior:
///
/// ```
/// #[derive(PartialEq, PartialOrd)]
@@ -1046,8 +1171,8 @@ pub macro Ord($item:item) {
/// generated from default implementations.
///
/// However it remains possible to implement the others separately for types which do not have a
-/// total order. For example, for floating point numbers, `NaN < 0 == false` and `NaN >= 0 ==
-/// false` (cf. IEEE 754-2008 section 5.11).
+/// total order. For example, for floating point numbers, `NaN < 0 == false` and `NaN >= 0 == false`
+/// (cf. IEEE 754-2008 section 5.11).
///
/// `PartialOrd` requires your type to be [`PartialEq`].
///
@@ -1056,7 +1181,6 @@ pub macro Ord($item:item) {
/// ```
/// use std::cmp::Ordering;
///
-/// #[derive(Eq)]
/// struct Person {
/// id: u32,
/// name: String,
@@ -1080,11 +1204,13 @@ pub macro Ord($item:item) {
/// self.height == other.height
/// }
/// }
+///
+/// impl Eq for Person {}
/// ```
///
-/// You may also find it useful to use [`partial_cmp`] on your type's fields. Here
-/// is an example of `Person` types who have a floating-point `height` field that
-/// is the only field to be used for sorting:
+/// You may also find it useful to use [`partial_cmp`] on your type's fields. Here is an example of
+/// `Person` types who have a floating-point `height` field that is the only field to be used for
+/// sorting:
///
/// ```
/// use std::cmp::Ordering;
@@ -1108,6 +1234,38 @@ pub macro Ord($item:item) {
/// }
/// ```
///
+/// ## Examples of incorrect `PartialOrd` implementations
+///
+/// ```
+/// use std::cmp::Ordering;
+///
+/// #[derive(PartialEq, Debug)]
+/// struct Character {
+/// health: u32,
+/// experience: u32,
+/// }
+///
+/// impl PartialOrd for Character {
+/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+/// Some(self.health.cmp(&other.health))
+/// }
+/// }
+///
+/// let a = Character {
+/// health: 10,
+/// experience: 5,
+/// };
+/// let b = Character {
+/// health: 10,
+/// experience: 77,
+/// };
+///
+/// // Mistake: `PartialEq` and `PartialOrd` disagree with each other.
+///
+/// assert_eq!(a.partial_cmp(&b).unwrap(), Ordering::Equal); // a == b according to `PartialOrd`.
+/// assert_ne!(a, b); // a != b according to `PartialEq`.
+/// ```
+///
/// # Examples
///
/// ```
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 881a89f4d10..dec67f9fe51 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -2659,12 +2659,17 @@ extern "rust-intrinsic" {
///
/// `catch_fn` must not unwind.
///
- /// The third argument is a function called if an unwind occurs (both Rust unwinds and foreign
- /// unwinds). This function takes the data pointer and a pointer to the target-specific
- /// exception object that was caught. For more information, see the compiler's source as well as
- /// std's `catch_unwind` implementation.
+ /// The third argument is a function called if an unwind occurs (both Rust `panic` and foreign
+ /// unwinds). This function takes the data pointer and a pointer to the target- and
+ /// runtime-specific exception object that was caught.
///
- /// The stable version of this intrinsic is `std::panic::catch_unwind`.
+ /// Note that in the case of a foreign unwinding operation, the exception object data may not be
+ /// safely usable from Rust, and should not be directly exposed via the standard library. To
+ /// prevent unsafe access, the library implementation may either abort the process or present an
+ /// opaque error type to the user.
+ ///
+ /// For more information, see the compiler's source, as well as the documentation for the stable
+ /// version of this intrinsic, `std::panic::catch_unwind`.
#[rustc_nounwind]
pub fn catch_unwind(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32;
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 01cadd78cc0..817d9e3b962 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -118,7 +118,6 @@
#![feature(const_array_into_iter_constructors)]
#![feature(const_bigint_helper_methods)]
#![feature(const_black_box)]
-#![feature(const_cell_into_inner)]
#![feature(const_char_encode_utf16)]
#![feature(const_char_encode_utf8)]
#![feature(const_eval_select)]
diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs
index e2a842046a9..1ad5c07d15c 100644
--- a/library/core/src/panic/location.rs
+++ b/library/core/src/panic/location.rs
@@ -44,7 +44,7 @@ impl<'a> Location<'a> {
///
/// # Examples
///
- /// ```standalone
+ /// ```standalone_crate
/// use std::panic::Location;
///
/// /// Returns the [`Location`] at which it is called.
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index be85f507129..42b68e28273 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -596,7 +596,7 @@ impl AtomicBool {
#[stable(feature = "atomic_access", since = "1.15.0")]
#[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")]
pub const fn into_inner(self) -> bool {
- self.v.primitive_into_inner() != 0
+ self.v.into_inner() != 0
}
/// Loads a value from the bool.
@@ -1413,7 +1413,7 @@ impl<T> AtomicPtr<T> {
#[stable(feature = "atomic_access", since = "1.15.0")]
#[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")]
pub const fn into_inner(self) -> *mut T {
- self.p.primitive_into_inner()
+ self.p.into_inner()
}
/// Loads a value from the pointer.
@@ -2408,7 +2408,7 @@ macro_rules! atomic_int {
#[$stable_access]
#[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")]
pub const fn into_inner(self) -> $int_type {
- self.v.primitive_into_inner()
+ self.v.into_inner()
}
/// Loads a value from the atomic integer.
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 604c0d48743..4f2190f78bf 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -18,7 +18,6 @@
#![feature(const_align_offset)]
#![feature(const_array_from_ref)]
#![feature(const_black_box)]
-#![feature(const_cell_into_inner)]
#![feature(const_hash)]
#![feature(const_heap)]
#![feature(const_ip)]
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index d55114227af..7d860b49e87 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core", public = true }
-compiler_builtins = { version = "0.1.126" }
+compiler_builtins = { version = "0.1.130" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }
hashbrown = { version = "0.14", default-features = false, features = [
diff --git a/library/std/build.rs b/library/std/build.rs
index 359ae4f20ee..c5d0af469a8 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -96,9 +96,6 @@ fn main() {
let has_reliable_f16 = match (target_arch.as_str(), target_os.as_str()) {
// We can always enable these in Miri as that is not affected by codegen bugs.
_ if is_miri => true,
- // Selection failure until recent LLVM <https://github.com/llvm/llvm-project/issues/93894>
- // FIXME(llvm19): can probably be removed at the version bump
- ("loongarch64", _) => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
("s390x", _) => false,
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
@@ -108,18 +105,18 @@ fn main() {
// Apple has a special ABI for `f16` that we do not yet support
// FIXME(builtins): fixed by <https://github.com/rust-lang/compiler-builtins/pull/675>
("x86" | "x86_64", _) if target_vendor == "apple" => false,
- // Missing `__gnu_h2f_ieee` and `__gnu_f2h_ieee`
+ // Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
+ ("csky", _) => false,
+ ("hexagon", _) => false,
+ ("loongarch64", _) => false,
+ ("mips" | "mips64" | "mips32r6" | "mips64r6", _) => false,
("powerpc" | "powerpc64", _) => false,
- // Missing `__gnu_h2f_ieee` and `__gnu_f2h_ieee`
- ("mips" | "mips32r6" | "mips64" | "mips64r6", _) => false,
- // Missing `__extendhfsf` and `__truncsfhf`
- ("riscv32" | "riscv64", _) => false,
- // Most OSs are missing `__extendhfsf` and `__truncsfhf`
- (_, "linux" | "macos") => true,
- // Almost all OSs besides Linux and MacOS are missing symbols until compiler-builtins can
- // be updated. <https://github.com/rust-lang/rust/pull/125016> will get some of these, the
- // next CB update should get the rest.
- _ => false,
+ ("sparc" | "sparc64", _) => false,
+ ("wasm32" | "wasm64", _) => false,
+ // `f16` support only requires that symbols converting to and from `f32` are available. We
+ // provide these in `compiler-builtins`, so `f16` should be available on all platforms that
+ // do not have other ABI issues or LLVM crashes.
+ _ => true,
};
let has_reliable_f128 = match (target_arch.as_str(), target_os.as_str()) {
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 06ed4f6a03d..f81a13d4c44 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -561,7 +561,7 @@ impl TcpStream {
/// Moves this TCP stream into or out of nonblocking mode.
///
- /// This will result in `read`, `write`, `recv` and `send` operations
+ /// This will result in `read`, `write`, `recv` and `send` system operations
/// becoming nonblocking, i.e., immediately returning from their calls.
/// If the IO operation is successful, `Ok` is returned and no further
/// action is required. If the IO operation could not be completed and needs
diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs
index 8c9e31f9c15..b78e52023b3 100644
--- a/library/std/src/net/udp.rs
+++ b/library/std/src/net/udp.rs
@@ -764,7 +764,7 @@ impl UdpSocket {
/// Moves this UDP socket into or out of nonblocking mode.
///
- /// This will result in `recv`, `recv_from`, `send`, and `send_to`
+ /// This will result in `recv`, `recv_from`, `send`, and `send_to` system
/// operations becoming nonblocking, i.e., immediately returning from their
/// calls. If the IO operation is successful, `Ok` is returned and no
/// further action is required. If the IO operation could not be completed
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index 015cab89485..d649357a56d 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -288,45 +288,55 @@ pub use core::panic::abort_unwind;
/// Invokes a closure, capturing the cause of an unwinding panic if one occurs.
///
-/// This function will return `Ok` with the closure's result if the closure
-/// does not panic, and will return `Err(cause)` if the closure panics. The
-/// `cause` returned is the object with which panic was originally invoked.
+/// This function will return `Ok` with the closure's result if the closure does
+/// not panic, and will return `Err(cause)` if the closure panics. The `cause`
+/// returned is the object with which panic was originally invoked.
///
-/// It is currently undefined behavior to unwind from Rust code into foreign
-/// code, so this function is particularly useful when Rust is called from
-/// another language (normally C). This can run arbitrary Rust code, capturing a
-/// panic and allowing a graceful handling of the error.
+/// Rust functions that are expected to be called from foreign code that does
+/// not support unwinding (such as C compiled with `-fno-exceptions`) should be
+/// defined using `extern "C"`, which ensures that if the Rust code panics, it
+/// is automatically caught and the process is aborted. If this is the desired
+/// behavior, it is not necessary to use `catch_unwind` explicitly. This
+/// function should instead be used when more graceful error-handling is needed.
///
/// It is **not** recommended to use this function for a general try/catch
/// mechanism. The [`Result`] type is more appropriate to use for functions that
/// can fail on a regular basis. Additionally, this function is not guaranteed
/// to catch all panics, see the "Notes" section below.
///
-/// The closure provided is required to adhere to the [`UnwindSafe`] trait to ensure
-/// that all captured variables are safe to cross this boundary. The purpose of
-/// this bound is to encode the concept of [exception safety][rfc] in the type
-/// system. Most usage of this function should not need to worry about this
-/// bound as programs are naturally unwind safe without `unsafe` code. If it
-/// becomes a problem the [`AssertUnwindSafe`] wrapper struct can be used to quickly
-/// assert that the usage here is indeed unwind safe.
+/// The closure provided is required to adhere to the [`UnwindSafe`] trait to
+/// ensure that all captured variables are safe to cross this boundary. The
+/// purpose of this bound is to encode the concept of [exception safety][rfc] in
+/// the type system. Most usage of this function should not need to worry about
+/// this bound as programs are naturally unwind safe without `unsafe` code. If
+/// it becomes a problem the [`AssertUnwindSafe`] wrapper struct can be used to
+/// quickly assert that the usage here is indeed unwind safe.
///
/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
///
/// # Notes
///
-/// Note that this function **might not catch all panics** in Rust. A panic in
-/// Rust is not always implemented via unwinding, but can be implemented by
-/// aborting the process as well. This function *only* catches unwinding panics,
-/// not those that abort the process.
+/// This function **might not catch all Rust panics**. A Rust panic is not
+/// always implemented via unwinding, but can be implemented by aborting the
+/// process as well. This function *only* catches unwinding panics, not those
+/// that abort the process.
///
-/// Note that if a custom panic hook has been set, it will be invoked before
-/// the panic is caught, before unwinding.
+/// If a custom panic hook has been set, it will be invoked before the panic is
+/// caught, before unwinding.
///
-/// Also note that unwinding into Rust code with a foreign exception (e.g.
-/// an exception thrown from C++ code) is undefined behavior.
+/// Although unwinding into Rust code with a foreign exception (e.g. an
+/// exception thrown from C++ code, or a `panic!` in Rust code compiled or
+/// linked with a different runtime) via an appropriate ABI (e.g. `"C-unwind"`)
+/// is permitted, catching such an exception using this function will have one
+/// of two behaviors, and it is unspecified which will occur:
///
-/// Finally, be **careful in how you drop the result of this function**.
-/// If it is `Err`, it contains the panic payload, and dropping that may in turn panic!
+/// * The process aborts, after executing all destructors of `f` and the
+/// functions it called.
+/// * The function returns a `Result::Err` containing an opaque type.
+///
+/// Finally, be **careful in how you drop the result of this function**. If it
+/// is `Err`, it contains the panic payload, and dropping that may in turn
+/// panic!
///
/// # Examples
///
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 41f02af9366..686f5055ac1 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -664,6 +664,19 @@ impl Builder {
/// println!("{result}");
/// ```
///
+/// # Notes
+///
+/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g.
+/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a
+/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn`
+/// unwinds all the way to the root with such an exception, one of two behaviors are possible,
+/// and it is unspecified which will occur:
+///
+/// * The process aborts.
+/// * The process does not abort, and [`join`] will return a `Result::Err`
+/// containing an opaque type.
+///
+/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html
/// [`channels`]: crate::sync::mpsc
/// [`join`]: JoinHandle::join
/// [`Err`]: crate::result::Result::Err
@@ -1784,7 +1797,7 @@ impl<T> JoinHandle<T> {
/// operations that happen after `join` returns.
///
/// If the associated thread panics, [`Err`] is returned with the parameter given
- /// to [`panic!`].
+ /// to [`panic!`] (though see the Notes below).
///
/// [`Err`]: crate::result::Result::Err
/// [atomic memory orderings]: crate::sync::atomic
@@ -1806,6 +1819,18 @@ impl<T> JoinHandle<T> {
/// }).unwrap();
/// join_handle.join().expect("Couldn't join on the associated thread");
/// ```
+ ///
+ /// # Notes
+ ///
+ /// If a "foreign" unwinding operation (e.g. an exception thrown from C++
+ /// code, or a `panic!` in Rust code compiled or linked with a different
+ /// runtime) unwinds all the way to the thread root, the process may be
+ /// aborted; see the Notes on [`thread::spawn`]. If the process is not
+ /// aborted, this function will return a `Result::Err` containing an opaque
+ /// type.
+ ///
+ /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html
+ /// [`thread::spawn`]: spawn
#[stable(feature = "rust1", since = "1.0.0")]
pub fn join(self) -> Result<T> {
self.0.join()
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index bae7642cffd..e4011221286 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -242,7 +242,7 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool {
/// Returns true if we're running in CI with modified LLVM (and thus can't download it)
pub(crate) fn is_ci_llvm_modified(config: &Config) -> bool {
- CiEnv::is_ci() && config.rust_info.is_managed_git_subrepository() && {
+ CiEnv::is_rust_lang_managed_ci_job() && config.rust_info.is_managed_git_subrepository() && {
// We assume we have access to git, so it's okay to unconditionally pass
// `true` here.
let llvm_sha = detect_llvm_sha(config, true);
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 77e0ece3104..3c0afb858f8 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -343,6 +343,15 @@ pub struct Config {
pub out: PathBuf,
pub rust_info: channel::GitInfo,
+ pub cargo_info: channel::GitInfo,
+ pub rust_analyzer_info: channel::GitInfo,
+ pub clippy_info: channel::GitInfo,
+ pub miri_info: channel::GitInfo,
+ pub rustfmt_info: channel::GitInfo,
+ pub enzyme_info: channel::GitInfo,
+ pub in_tree_llvm_info: channel::GitInfo,
+ pub in_tree_gcc_info: channel::GitInfo,
+
// These are either the stage0 downloaded binaries or the locally installed ones.
pub initial_cargo: PathBuf,
pub initial_rustc: PathBuf,
@@ -1796,6 +1805,19 @@ impl Config {
config.omit_git_hash = omit_git_hash.unwrap_or(default);
config.rust_info = GitInfo::new(config.omit_git_hash, &config.src);
+ config.cargo_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/cargo"));
+ config.rust_analyzer_info =
+ GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rust-analyzer"));
+ config.clippy_info =
+ GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/clippy"));
+ config.miri_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/miri"));
+ config.rustfmt_info =
+ GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rustfmt"));
+ config.enzyme_info =
+ GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/enzyme"));
+ config.in_tree_llvm_info = GitInfo::new(false, &config.src.join("src/llvm-project"));
+ config.in_tree_gcc_info = GitInfo::new(false, &config.src.join("src/gcc"));
+
// We need to override `rust.channel` if it's manually specified when using the CI rustc.
// This is because if the compiler uses a different channel than the one specified in config.toml,
// tests may fail due to using a different channel than the one used by the compiler during tests.
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 7bf5b4e23d2..4805e598ce2 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -305,18 +305,15 @@ impl Build {
#[cfg(not(unix))]
let is_sudo = false;
- let omit_git_hash = config.omit_git_hash;
- let rust_info = GitInfo::new(omit_git_hash, &src);
- let cargo_info = GitInfo::new(omit_git_hash, &src.join("src/tools/cargo"));
- let rust_analyzer_info = GitInfo::new(omit_git_hash, &src.join("src/tools/rust-analyzer"));
- let clippy_info = GitInfo::new(omit_git_hash, &src.join("src/tools/clippy"));
- let miri_info = GitInfo::new(omit_git_hash, &src.join("src/tools/miri"));
- let rustfmt_info = GitInfo::new(omit_git_hash, &src.join("src/tools/rustfmt"));
- let enzyme_info = GitInfo::new(omit_git_hash, &src.join("src/tools/enzyme"));
-
- // we always try to use git for LLVM builds
- let in_tree_llvm_info = GitInfo::new(false, &src.join("src/llvm-project"));
- let in_tree_gcc_info = GitInfo::new(false, &src.join("src/gcc"));
+ let rust_info = config.rust_info.clone();
+ let cargo_info = config.cargo_info.clone();
+ let rust_analyzer_info = config.rust_analyzer_info.clone();
+ let clippy_info = config.clippy_info.clone();
+ let miri_info = config.miri_info.clone();
+ let rustfmt_info = config.rustfmt_info.clone();
+ let enzyme_info = config.enzyme_info.clone();
+ let in_tree_llvm_info = config.in_tree_llvm_info.clone();
+ let in_tree_gcc_info = config.in_tree_gcc_info.clone();
let initial_target_libdir_str = if config.dry_run() {
"/dummy/lib/path/to/lib/".to_string()
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index 47d04a52883..6b2d58c8ef3 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.18.0 \ No newline at end of file
+0.18.1 \ No newline at end of file
diff --git a/src/doc/rustdoc/src/write-documentation/documentation-tests.md b/src/doc/rustdoc/src/write-documentation/documentation-tests.md
index 7ed2e9720fe..c93893b5ada 100644
--- a/src/doc/rustdoc/src/write-documentation/documentation-tests.md
+++ b/src/doc/rustdoc/src/write-documentation/documentation-tests.md
@@ -414,11 +414,11 @@ In some cases, doctests cannot be merged. For example, if you have:
The problem with this code is that, if you change any other doctests, it'll likely break when
runing `rustdoc --test`, making it tricky to maintain.
-This is where the `standalone` attribute comes in: it tells `rustdoc` that a doctest
+This is where the `standalone_crate` attribute comes in: it tells `rustdoc` that a doctest
should not be merged with the others. So the previous code should use it:
```rust
-//! ```standalone
+//! ```standalone_crate
//! let location = std::panic::Location::caller();
//! assert_eq!(location.line(), 4);
//! ```
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 3ee6b24ac92..bdd6fbe8c0c 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -837,7 +837,7 @@ impl CreateRunnableDocTests {
let is_standalone = !doctest.can_be_merged
|| scraped_test.langstr.compile_fail
|| scraped_test.langstr.test_harness
- || scraped_test.langstr.standalone
+ || scraped_test.langstr.standalone_crate
|| self.rustdoc_options.nocapture
|| self.rustdoc_options.test_args.iter().any(|arg| arg == "--show-output");
if is_standalone {
diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs
index d560e3a476b..efbb332d12d 100644
--- a/src/librustdoc/doctest/make.rs
+++ b/src/librustdoc/doctest/make.rs
@@ -48,7 +48,7 @@ impl DocTestBuilder {
) -> Self {
let can_merge_doctests = can_merge_doctests
&& lang_str.is_some_and(|lang_str| {
- !lang_str.compile_fail && !lang_str.test_harness && !lang_str.standalone
+ !lang_str.compile_fail && !lang_str.test_harness && !lang_str.standalone_crate
});
let SourceInfo { crate_attrs, maybe_crate_attrs, crates, everything_else } =
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index b18d621478c..8ae5484feda 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -871,7 +871,7 @@ pub(crate) struct LangString {
pub(crate) rust: bool,
pub(crate) test_harness: bool,
pub(crate) compile_fail: bool,
- pub(crate) standalone: bool,
+ pub(crate) standalone_crate: bool,
pub(crate) error_codes: Vec<String>,
pub(crate) edition: Option<Edition>,
pub(crate) added_classes: Vec<String>,
@@ -1194,7 +1194,7 @@ impl Default for LangString {
rust: true,
test_harness: false,
compile_fail: false,
- standalone: false,
+ standalone_crate: false,
error_codes: Vec::new(),
edition: None,
added_classes: Vec::new(),
@@ -1264,8 +1264,8 @@ impl LangString {
seen_rust_tags = !seen_other_tags || seen_rust_tags;
data.no_run = true;
}
- LangStringToken::LangToken("standalone") => {
- data.standalone = true;
+ LangStringToken::LangToken("standalone_crate") => {
+ data.standalone_crate = true;
seen_rust_tags = !seen_other_tags || seen_rust_tags;
}
LangStringToken::LangToken(x) if x.starts_with("edition") => {
@@ -1298,44 +1298,47 @@ impl LangString {
}
LangStringToken::LangToken(x) if extra.is_some() => {
let s = x.to_lowercase();
- if let Some((flag, help)) = if s == "compile-fail"
- || s == "compile_fail"
- || s == "compilefail"
- {
- Some((
- "compile_fail",
- "the code block will either not be tested if not marked as a rust one \
- or won't fail if it compiles successfully",
- ))
- } else if s == "should-panic" || s == "should_panic" || s == "shouldpanic" {
- Some((
- "should_panic",
- "the code block will either not be tested if not marked as a rust one \
- or won't fail if it doesn't panic when running",
- ))
- } else if s == "no-run" || s == "no_run" || s == "norun" {
- Some((
- "no_run",
- "the code block will either not be tested if not marked as a rust one \
- or will be run (which you might not want)",
- ))
- } else if s == "test-harness" || s == "test_harness" || s == "testharness" {
- Some((
- "test_harness",
- "the code block will either not be tested if not marked as a rust one \
- or the code will be wrapped inside a main function",
- ))
- } else {
- None
+ if let Some(help) = match s.as_str() {
+ "compile-fail" | "compile_fail" | "compilefail" => Some(
+ "use `compile_fail` to invert the results of this test, so that it \
+ passes if it cannot be compiled and fails if it can",
+ ),
+ "should-panic" | "should_panic" | "shouldpanic" => Some(
+ "use `should_panic` to invert the results of this test, so that if \
+ passes if it panics and fails if it does not",
+ ),
+ "no-run" | "no_run" | "norun" => Some(
+ "use `no_run` to compile, but not run, the code sample during \
+ testing",
+ ),
+ "test-harness" | "test_harness" | "testharness" => Some(
+ "use `test_harness` to run functions marked `#[test]` instead of a \
+ potentially-implicit `main` function",
+ ),
+ "standalone" | "standalone_crate" | "standalone-crate" => {
+ if let Some(extra) = extra
+ && extra.sp.at_least_rust_2024()
+ {
+ Some(
+ "use `standalone_crate` to compile this code block \
+ separately",
+ )
+ } else {
+ None
+ }
+ }
+ _ => None,
} {
if let Some(extra) = extra {
extra.error_invalid_codeblock_attr_with_help(
format!("unknown attribute `{x}`"),
|lint| {
- lint.help(format!(
- "there is an attribute with a similar name: `{flag}`"
- ))
- .help(help);
+ lint.help(help).help(
+ "this code block may be skipped during testing, \
+ because unknown attributes are treated as markers for \
+ code samples written in other programming languages, \
+ unless it is also explicitly marked as `rust`",
+ );
},
);
}
diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs
index fbc18176ed8..bfa285c57fa 100644
--- a/src/librustdoc/visit.rs
+++ b/src/librustdoc/visit.rs
@@ -1,11 +1,17 @@
use crate::clean::*;
+/// Allows a type to traverse the cleaned ast of a crate.
+///
+/// Note that like [`rustc_ast::visit::Visitor`], but
+/// unlike [`rustc_lint::EarlyLintPass`], if you override a
+/// `visit_*` method, you will need to manually recurse into
+/// its contents.
pub(crate) trait DocVisitor<'a>: Sized {
fn visit_item(&mut self, item: &'a Item) {
self.visit_item_recur(item)
}
- /// don't override!
+ /// Don't override!
fn visit_inner_recur(&mut self, kind: &'a ItemKind) {
match kind {
StrippedItem(..) => unreachable!(),
@@ -46,7 +52,7 @@ pub(crate) trait DocVisitor<'a>: Sized {
}
}
- /// don't override!
+ /// Don't override!
fn visit_item_recur(&mut self, item: &'a Item) {
match &item.kind {
StrippedItem(i) => self.visit_inner_recur(&*i),
@@ -58,6 +64,7 @@ pub(crate) trait DocVisitor<'a>: Sized {
m.items.iter().for_each(|i| self.visit_item(i))
}
+ /// This is the main entrypoint of [`DocVisitor`].
fn visit_crate(&mut self, c: &'a Crate) {
self.visit_item(&c.module);
diff --git a/src/tools/build_helper/src/ci.rs b/src/tools/build_helper/src/ci.rs
index 6d79c7c83ad..60f319129a0 100644
--- a/src/tools/build_helper/src/ci.rs
+++ b/src/tools/build_helper/src/ci.rs
@@ -19,6 +19,15 @@ impl CiEnv {
pub fn is_ci() -> bool {
Self::current() != CiEnv::None
}
+
+ /// Checks if running in rust-lang/rust managed CI job.
+ pub fn is_rust_lang_managed_ci_job() -> bool {
+ Self::is_ci()
+ // If both are present, we can assume it's an upstream CI job
+ // as they are always set unconditionally.
+ && std::env::var_os("CI_JOB_NAME").is_some()
+ && std::env::var_os("TOOLSTATE_REPO").is_some()
+ }
}
pub mod gha {
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index a291ff37112..6a889d27793 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -1115,6 +1115,7 @@ fn expand_variables(mut value: String, config: &Config) -> String {
const CWD: &str = "{{cwd}}";
const SRC_BASE: &str = "{{src-base}}";
const BUILD_BASE: &str = "{{build-base}}";
+ const RUST_SRC_BASE: &str = "{{rust-src-base}}";
const SYSROOT_BASE: &str = "{{sysroot-base}}";
const TARGET_LINKER: &str = "{{target-linker}}";
const TARGET: &str = "{{target}}";
@@ -1144,6 +1145,13 @@ fn expand_variables(mut value: String, config: &Config) -> String {
value = value.replace(TARGET, &config.target);
}
+ if value.contains(RUST_SRC_BASE) {
+ let src_base = config.sysroot_base.join("lib/rustlib/src/rust");
+ src_base.try_exists().expect(&*format!("{} should exists", src_base.display()));
+ let src_base = src_base.read_link().unwrap_or(src_base);
+ value = value.replace(RUST_SRC_BASE, &src_base.to_string_lossy());
+ }
+
value
}
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index c2e74dffdca..74d86d2b521 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2294,13 +2294,19 @@ impl<'test> TestCx<'test> {
}
let base_dir = Path::new("/rustc/FAKE_PREFIX");
- // Paths into the libstd/libcore
+ // Fake paths into the libstd/libcore
normalize_path(&base_dir.join("library"), "$SRC_DIR");
// `ui-fulldeps` tests can show paths to the compiler source when testing macros from
// `rustc_macros`
// eg. /home/user/rust/compiler
normalize_path(&base_dir.join("compiler"), "$COMPILER_DIR");
+ // Real paths into the libstd/libcore
+ let rust_src_dir = &self.config.sysroot_base.join("lib/rustlib/src/rust");
+ rust_src_dir.try_exists().expect(&*format!("{} should exists", rust_src_dir.display()));
+ let rust_src_dir = rust_src_dir.read_link().unwrap_or(rust_src_dir.to_path_buf());
+ normalize_path(&rust_src_dir.join("library"), "$SRC_DIR_REAL");
+
// Paths into the build directory
let test_build_dir = &self.config.build_base;
let parent_build_dir = test_build_dir.parent().unwrap().parent().unwrap().parent().unwrap();
@@ -2310,9 +2316,6 @@ impl<'test> TestCx<'test> {
// eg. /home/user/rust/build
normalize_path(parent_build_dir, "$BUILD_DIR");
- // Paths into lib directory.
- normalize_path(&parent_build_dir.parent().unwrap().join("lib"), "$LIB_DIR");
-
if json {
// escaped newlines in json strings should be readable
// in the stderr files. There's no point int being correct,
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index e5f0aabbf7c..060deb18344 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -102,9 +102,9 @@ checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
[[package]]
name = "autocfg"
-version = "1.3.0"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "bincode"
@@ -161,9 +161,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
-version = "1.1.21"
+version = "1.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0"
+checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"
dependencies = [
"shlex",
]
@@ -376,9 +376,9 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
[[package]]
name = "flate2"
-version = "1.0.33"
+version = "1.0.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253"
+checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -572,9 +572,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
-version = "0.2.158"
+version = "0.2.159"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
+checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
[[package]]
name = "libdbus-sys"
@@ -949,9 +949,9 @@ dependencies = [
[[package]]
name = "pkg-config"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
+checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "polib"
@@ -1082,9 +1082,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
-version = "0.5.4"
+version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853"
+checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b"
dependencies = [
"bitflags 2.6.0",
]
@@ -1205,9 +1205,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
-version = "0.6.7"
+version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
+checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
dependencies = [
"serde",
]
@@ -1275,9 +1275,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
-version = "2.0.77"
+version = "2.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
+checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
dependencies = [
"proc-macro2",
"quote",
@@ -1306,9 +1306,9 @@ dependencies = [
[[package]]
name = "tempfile"
-version = "3.12.0"
+version = "3.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64"
+checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b"
dependencies = [
"cfg-if",
"fastrand",
@@ -1346,18 +1346,18 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
[[package]]
name = "thiserror"
-version = "1.0.63"
+version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
+checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.63"
+version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
+checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
dependencies = [
"proc-macro2",
"quote",
@@ -1411,9 +1411,9 @@ dependencies = [
[[package]]
name = "toml_edit"
-version = "0.22.21"
+version = "0.22.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf"
+checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
dependencies = [
"indexmap",
"serde",
@@ -1766,9 +1766,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
-version = "0.6.18"
+version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f"
+checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
dependencies = [
"memchr",
]
diff --git a/tests/codegen/issues/issue-123712-str-to-lower-autovectorization.rs b/tests/codegen/issues/issue-123712-str-to-lower-autovectorization.rs
new file mode 100644
index 00000000000..11ee10e8cc3
--- /dev/null
+++ b/tests/codegen/issues/issue-123712-str-to-lower-autovectorization.rs
@@ -0,0 +1,23 @@
+//@ only-x86_64
+//@ compile-flags: -C opt-level=3
+#![crate_type = "lib"]
+#![no_std]
+#![feature(str_internals)]
+
+extern crate alloc;
+
+/// Ensure that the ascii-prefix loop for `str::to_lowercase` and `str::to_uppercase` uses vector
+/// instructions.
+///
+/// The llvm ir should be the same for all targets that support some form of simd. Only targets
+/// without any simd instructions would see scalarized ir.
+/// Unfortunately, there is no `only-simd` directive to only run this test on only such platforms,
+/// and using test revisions would still require the core libraries for all platforms.
+// CHECK-LABEL: @lower_while_ascii
+// CHECK: [[A:%[0-9]]] = load <16 x i8>
+// CHECK-NEXT: [[B:%[0-9]]] = icmp slt <16 x i8> [[A]], zeroinitializer
+// CHECK-NEXT: [[C:%[0-9]]] = bitcast <16 x i1> [[B]] to i16
+#[no_mangle]
+pub fn lower_while_ascii(s: &str) -> (alloc::string::String, &str) {
+ alloc::str::convert_while_ascii(s, u8::to_ascii_lowercase)
+}
diff --git a/tests/crashes/130521.rs b/tests/crashes/130521.rs
new file mode 100644
index 00000000000..2d30b658024
--- /dev/null
+++ b/tests/crashes/130521.rs
@@ -0,0 +1,13 @@
+//@ known-bug: #130521
+
+#![feature(object_safe_for_dispatch)]
+struct Vtable(dyn Cap);
+
+trait Cap<'a> {}
+
+union Transmute {
+ t: u64,
+ u: &'static Vtable,
+}
+
+const G: &Copy = unsafe { Transmute { t: 1 }.u };
diff --git a/tests/crashes/130524.rs b/tests/crashes/130524.rs
new file mode 100644
index 00000000000..14d2269de59
--- /dev/null
+++ b/tests/crashes/130524.rs
@@ -0,0 +1,22 @@
+//@ known-bug: #130524
+
+trait Transform {
+ type Output<'a>;
+}
+
+trait Propagate<Input> {}
+
+fn new_node<T: Transform>(_c: Vec<Box<dyn for<'a> Propagate<<T as Transform>::Output<'a>>>>) -> T {
+ todo!()
+}
+
+impl<Input, T> Propagate<Input> for T {}
+struct Noop;
+
+impl Transform for Noop {
+ type Output<'a> = ();
+}
+
+fn main() {
+ let _node: Noop = new_node(vec![Box::new(Noop)]);
+}
diff --git a/tests/crashes/130627.rs b/tests/crashes/130627.rs
new file mode 100644
index 00000000000..59d3606592b
--- /dev/null
+++ b/tests/crashes/130627.rs
@@ -0,0 +1,20 @@
+//@ known-bug: #130627
+
+#![feature(trait_alias)]
+
+trait Test {}
+
+#[diagnostic::on_unimplemented(
+ message="message",
+ label="label",
+ note="note"
+)]
+trait Alias = Test;
+
+// Use trait alias as bound on type parameter.
+fn foo<T: Alias>(v: &T) {
+}
+
+pub fn main() {
+ foo(&1);
+}
diff --git a/tests/crashes/130687.rs b/tests/crashes/130687.rs
new file mode 100644
index 00000000000..361be0905df
--- /dev/null
+++ b/tests/crashes/130687.rs
@@ -0,0 +1,4 @@
+//@ known-bug: #130687
+//@ only-x86_64
+pub struct Data([u8; usize::MAX >> 16]);
+const _: &'static Data = &Data([0; usize::MAX >> 16]);
diff --git a/tests/crashes/130779.rs b/tests/crashes/130779.rs
new file mode 100644
index 00000000000..f0fd81fff44
--- /dev/null
+++ b/tests/crashes/130779.rs
@@ -0,0 +1,11 @@
+//@ known-bug: #130779
+#![feature(never_patterns)]
+
+enum E { A }
+
+fn main() {
+ match E::A {
+ ! |
+ if true => {}
+ }
+}
diff --git a/tests/crashes/130921.rs b/tests/crashes/130921.rs
new file mode 100644
index 00000000000..b7cb1303937
--- /dev/null
+++ b/tests/crashes/130921.rs
@@ -0,0 +1,10 @@
+//@ known-bug: #130921
+//@ compile-flags: -Zvalidate-mir -Copt-level=0 --crate-type lib
+
+pub fn hello() -> [impl Sized; 2] {
+ if false {
+ let x = hello();
+ let _: &[i32] = &x;
+ }
+ todo!()
+}
diff --git a/tests/crashes/130970.rs b/tests/crashes/130970.rs
new file mode 100644
index 00000000000..e1f59c155a5
--- /dev/null
+++ b/tests/crashes/130970.rs
@@ -0,0 +1,9 @@
+//@ known-bug: #130970
+//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir
+
+fn main() {
+ extern "C" {
+ static symbol: [usize];
+ }
+ println!("{}", symbol[0]);
+}
diff --git a/tests/run-make/doctests-merge/doctest-standalone.rs b/tests/run-make/doctests-merge/doctest-standalone.rs
index 134ffb58285..ac9f8f9272a 100644
--- a/tests/run-make/doctests-merge/doctest-standalone.rs
+++ b/tests/run-make/doctests-merge/doctest-standalone.rs
@@ -1,11 +1,11 @@
#![crate_name = "foo"]
#![crate_type = "lib"]
-//! ```standalone
+//! ```standalone_crate
//! foo::init();
//! ```
-/// ```standalone
+/// ```standalone_crate
/// foo::init();
/// ```
pub fn init() {
diff --git a/tests/rustdoc-gui/docblock-code-block-line-number.goml b/tests/rustdoc-gui/docblock-code-block-line-number.goml
index 53f756dfcd6..3c16626336e 100644
--- a/tests/rustdoc-gui/docblock-code-block-line-number.goml
+++ b/tests/rustdoc-gui/docblock-code-block-line-number.goml
@@ -87,8 +87,7 @@ assert-css: ("#settings", {"display": "block"})
// Then, click the toggle button.
click: "input#line-numbers"
-wait-for: 100 // FIXME: `wait-for-false` does not exist
-assert-false: "pre.example-line-numbers"
+wait-for-false: "pre.example-line-numbers"
assert-local-storage: {"rustdoc-line-numbers": "false" }
// Check that the rounded corners are back.
@@ -107,8 +106,7 @@ assert-css: (
click: "input#line-numbers"
wait-for: "pre.example-line-numbers"
assert-local-storage: {"rustdoc-line-numbers": "true" }
-wait-for: 100 // FIXME: `wait-for-false` does not exist
-assert: "pre.example-line-numbers"
+wait-for: "pre.example-line-numbers"
// Same check with scraped examples line numbers.
go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
@@ -195,15 +193,13 @@ define-function: ("check-line-numbers-existence", [], block {
// Then, click the toggle button.
click: "input#line-numbers"
- wait-for: 100 // FIXME: `wait-for-false` does not exist
- assert-local-storage-false: {"rustdoc-line-numbers": "true" }
+ wait-for-local-storage-false: {"rustdoc-line-numbers": "true" }
assert-false: ".example-line-numbers"
// Line numbers should still be there.
assert: ".src-line-numbers"
// Now disabling the setting.
click: "input#line-numbers"
- wait-for: 100 // FIXME: `wait-for-false` does not exist
- assert-local-storage: {"rustdoc-line-numbers": "true" }
+ wait-for-local-storage: {"rustdoc-line-numbers": "true" }
assert-false: ".example-line-numbers"
// Line numbers should still be there.
assert: ".src-line-numbers"
@@ -246,12 +242,10 @@ wait-for: "#settings"
// Then, click the toggle button.
click: "input#line-numbers"
-wait-for: 100 // FIXME: `wait-for-false` does not exist
+wait-for-count: (".example-wrap > pre.example-line-numbers", 0)
assert-local-storage-false: {"rustdoc-line-numbers": "true" }
-assert-count: (".example-wrap > pre.example-line-numbers", 0)
// Now turning off the setting.
click: "input#line-numbers"
-wait-for: 100 // FIXME: `wait-for-false` does not exist
+wait-for-count: (".example-wrap > pre.example-line-numbers", 2)
assert-local-storage: {"rustdoc-line-numbers": "true" }
-assert-count: (".example-wrap > pre.example-line-numbers", 2)
diff --git a/tests/rustdoc-ui/doctest/check-attr-test.stderr b/tests/rustdoc-ui/doctest/check-attr-test.stderr
index 10f763a6f9d..257136d1633 100644
--- a/tests/rustdoc-ui/doctest/check-attr-test.stderr
+++ b/tests/rustdoc-ui/doctest/check-attr-test.stderr
@@ -8,8 +8,8 @@ error: unknown attribute `compile-fail`
9 | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `compile_fail`
- = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
+ = help: use `compile_fail` to invert the results of this test, so that it passes if it cannot be compiled and fails if it can
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
note: the lint level is defined here
--> $DIR/check-attr-test.rs:3:9
|
@@ -26,8 +26,8 @@ error: unknown attribute `compilefail`
9 | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `compile_fail`
- = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
+ = help: use `compile_fail` to invert the results of this test, so that it passes if it cannot be compiled and fails if it can
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `comPile_fail`
--> $DIR/check-attr-test.rs:5:1
@@ -39,8 +39,8 @@ error: unknown attribute `comPile_fail`
9 | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `compile_fail`
- = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
+ = help: use `compile_fail` to invert the results of this test, so that it passes if it cannot be compiled and fails if it can
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `should-panic`
--> $DIR/check-attr-test.rs:12:1
@@ -52,8 +52,8 @@ error: unknown attribute `should-panic`
16 | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `should_panic`
- = help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running
+ = help: use `should_panic` to invert the results of this test, so that if passes if it panics and fails if it does not
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `shouldpanic`
--> $DIR/check-attr-test.rs:12:1
@@ -65,8 +65,8 @@ error: unknown attribute `shouldpanic`
16 | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `should_panic`
- = help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running
+ = help: use `should_panic` to invert the results of this test, so that if passes if it panics and fails if it does not
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `shOuld_panic`
--> $DIR/check-attr-test.rs:12:1
@@ -78,8 +78,8 @@ error: unknown attribute `shOuld_panic`
16 | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `should_panic`
- = help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running
+ = help: use `should_panic` to invert the results of this test, so that if passes if it panics and fails if it does not
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `no-run`
--> $DIR/check-attr-test.rs:19:1
@@ -91,8 +91,8 @@ error: unknown attribute `no-run`
23 | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `no_run`
- = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
+ = help: use `no_run` to compile, but not run, the code sample during testing
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `norun`
--> $DIR/check-attr-test.rs:19:1
@@ -104,8 +104,8 @@ error: unknown attribute `norun`
23 | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `no_run`
- = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
+ = help: use `no_run` to compile, but not run, the code sample during testing
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `nO_run`
--> $DIR/check-attr-test.rs:19:1
@@ -117,8 +117,8 @@ error: unknown attribute `nO_run`
23 | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `no_run`
- = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
+ = help: use `no_run` to compile, but not run, the code sample during testing
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `test-harness`
--> $DIR/check-attr-test.rs:26:1
@@ -130,8 +130,8 @@ error: unknown attribute `test-harness`
30 | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `test_harness`
- = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+ = help: use `test_harness` to run functions marked `#[test]` instead of a potentially-implicit `main` function
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `testharness`
--> $DIR/check-attr-test.rs:26:1
@@ -143,8 +143,8 @@ error: unknown attribute `testharness`
30 | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `test_harness`
- = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+ = help: use `test_harness` to run functions marked `#[test]` instead of a potentially-implicit `main` function
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `tesT_harness`
--> $DIR/check-attr-test.rs:26:1
@@ -156,8 +156,8 @@ error: unknown attribute `tesT_harness`
30 | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `test_harness`
- = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+ = help: use `test_harness` to run functions marked `#[test]` instead of a potentially-implicit `main` function
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: aborting due to 12 previous errors
diff --git a/tests/rustdoc-ui/doctest/standalone-warning-2024.rs b/tests/rustdoc-ui/doctest/standalone-warning-2024.rs
new file mode 100644
index 00000000000..aac43031546
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/standalone-warning-2024.rs
@@ -0,0 +1,16 @@
+// This test checks that it will output warnings for usage of `standalone` or `standalone_crate`.
+
+//@ compile-flags:--test -Zunstable-options --edition 2024
+//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME"
+//@ normalize-stdout-test: ".rs:\d+:\d+" -> ".rs:$$LINE:$$COL"
+
+#![deny(warnings)]
+
+//! ```standalone
+//! bla
+//! ```
+//!
+//! ```standalone-crate
+//! bla
+//! ```
diff --git a/tests/rustdoc-ui/doctest/standalone-warning-2024.stderr b/tests/rustdoc-ui/doctest/standalone-warning-2024.stderr
new file mode 100644
index 00000000000..d69d03d8657
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/standalone-warning-2024.stderr
@@ -0,0 +1,38 @@
+error: unknown attribute `standalone`
+ --> $DIR/standalone-warning-2024.rs:10:1
+ |
+10 | / //! ```standalone
+11 | | //! bla
+12 | | //! ```
+13 | | //!
+14 | | //! ```standalone-crate
+15 | | //! bla
+16 | | //! ```
+ | |_______^
+ |
+ = help: use `standalone_crate` to compile this code block separately
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
+note: the lint level is defined here
+ --> $DIR/standalone-warning-2024.rs:8:9
+ |
+8 | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(warnings)]`
+
+error: unknown attribute `standalone-crate`
+ --> $DIR/standalone-warning-2024.rs:10:1
+ |
+10 | / //! ```standalone
+11 | | //! bla
+12 | | //! ```
+13 | | //!
+14 | | //! ```standalone-crate
+15 | | //! bla
+16 | | //! ```
+ | |_______^
+ |
+ = help: use `standalone_crate` to compile this code block separately
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/rustdoc-ui/doctest/standalone-warning.rs b/tests/rustdoc-ui/doctest/standalone-warning.rs
new file mode 100644
index 00000000000..ce081c7641c
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/standalone-warning.rs
@@ -0,0 +1,10 @@
+// This test checks that it will not output warning for usage of `standalone` or `standalone_crate`.
+//@ check-pass
+
+//! ```standalone
+//! bla
+//! ```
+//!
+//! ```standalone-crate
+//! bla
+//! ```
diff --git a/tests/rustdoc-ui/lints/check-attr.stderr b/tests/rustdoc-ui/lints/check-attr.stderr
index d640125ab51..e23806e0bab 100644
--- a/tests/rustdoc-ui/lints/check-attr.stderr
+++ b/tests/rustdoc-ui/lints/check-attr.stderr
@@ -10,8 +10,8 @@ LL | | /// boo
LL | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `compile_fail`
- = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
+ = help: use `compile_fail` to invert the results of this test, so that it passes if it cannot be compiled and fails if it can
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
note: the lint level is defined here
--> $DIR/check-attr.rs:1:9
|
@@ -30,8 +30,8 @@ LL | | /// boo
LL | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `compile_fail`
- = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
+ = help: use `compile_fail` to invert the results of this test, so that it passes if it cannot be compiled and fails if it can
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `comPile_fail`
--> $DIR/check-attr.rs:3:1
@@ -45,8 +45,8 @@ LL | | /// boo
LL | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `compile_fail`
- = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
+ = help: use `compile_fail` to invert the results of this test, so that it passes if it cannot be compiled and fails if it can
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `should-panic`
--> $DIR/check-attr.rs:13:1
@@ -60,8 +60,8 @@ LL | | /// boo
LL | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `should_panic`
- = help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running
+ = help: use `should_panic` to invert the results of this test, so that if passes if it panics and fails if it does not
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `shouldpanic`
--> $DIR/check-attr.rs:13:1
@@ -75,8 +75,8 @@ LL | | /// boo
LL | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `should_panic`
- = help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running
+ = help: use `should_panic` to invert the results of this test, so that if passes if it panics and fails if it does not
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `sHould_panic`
--> $DIR/check-attr.rs:13:1
@@ -90,8 +90,8 @@ LL | | /// boo
LL | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `should_panic`
- = help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running
+ = help: use `should_panic` to invert the results of this test, so that if passes if it panics and fails if it does not
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `no-run`
--> $DIR/check-attr.rs:23:1
@@ -105,8 +105,8 @@ LL | | /// boo
LL | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `no_run`
- = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
+ = help: use `no_run` to compile, but not run, the code sample during testing
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `norun`
--> $DIR/check-attr.rs:23:1
@@ -120,8 +120,8 @@ LL | | /// boo
LL | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `no_run`
- = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
+ = help: use `no_run` to compile, but not run, the code sample during testing
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `no_Run`
--> $DIR/check-attr.rs:23:1
@@ -135,8 +135,8 @@ LL | | /// boo
LL | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `no_run`
- = help: the code block will either not be tested if not marked as a rust one or will be run (which you might not want)
+ = help: use `no_run` to compile, but not run, the code sample during testing
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `test-harness`
--> $DIR/check-attr.rs:33:1
@@ -150,8 +150,8 @@ LL | | /// boo
LL | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `test_harness`
- = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+ = help: use `test_harness` to run functions marked `#[test]` instead of a potentially-implicit `main` function
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `testharness`
--> $DIR/check-attr.rs:33:1
@@ -165,8 +165,8 @@ LL | | /// boo
LL | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `test_harness`
- = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+ = help: use `test_harness` to run functions marked `#[test]` instead of a potentially-implicit `main` function
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `teSt_harness`
--> $DIR/check-attr.rs:33:1
@@ -180,8 +180,8 @@ LL | | /// boo
LL | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `test_harness`
- = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+ = help: use `test_harness` to run functions marked `#[test]` instead of a potentially-implicit `main` function
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: unknown attribute `rust2018`
--> $DIR/check-attr.rs:43:1
@@ -222,8 +222,8 @@ LL | | /// boo
LL | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `should_panic`
- = help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running
+ = help: use `should_panic` to invert the results of this test, so that if passes if it panics and fails if it does not
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: aborting due to 15 previous errors
diff --git a/tests/rustdoc-ui/lints/check-fail.stderr b/tests/rustdoc-ui/lints/check-fail.stderr
index 99b01bac598..2eb9496e5dc 100644
--- a/tests/rustdoc-ui/lints/check-fail.stderr
+++ b/tests/rustdoc-ui/lints/check-fail.stderr
@@ -31,8 +31,8 @@ LL | | //! let x = 12;
LL | | //! ```
| |_______^
|
- = help: there is an attribute with a similar name: `test_harness`
- = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+ = help: use `test_harness` to run functions marked `#[test]` instead of a potentially-implicit `main` function
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
note: the lint level is defined here
--> $DIR/check-fail.rs:6:9
|
@@ -51,8 +51,8 @@ LL | | /// let x = 12;
LL | | /// ```
| |_______^
|
- = help: there is an attribute with a similar name: `test_harness`
- = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+ = help: use `test_harness` to run functions marked `#[test]` instead of a potentially-implicit `main` function
+ = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust`
error: aborting due to 4 previous errors
diff --git a/tests/ui/errors/remap-path-prefix-sysroot.rs b/tests/ui/errors/remap-path-prefix-sysroot.rs
new file mode 100644
index 00000000000..4cbb38709be
--- /dev/null
+++ b/tests/ui/errors/remap-path-prefix-sysroot.rs
@@ -0,0 +1,24 @@
+//@ revisions: with-remap without-remap
+//@ compile-flags: -g -Ztranslate-remapped-path-to-local-path=yes
+//@ [with-remap]compile-flags: --remap-path-prefix={{rust-src-base}}=remapped
+//@ [with-remap]compile-flags: --remap-path-prefix={{src-base}}=remapped-tests-ui
+//@ [without-remap]compile-flags:
+//@ error-pattern: E0507
+
+// The $SRC_DIR*.rs:LL:COL normalisation doesn't kick in automatically
+// as the remapped revision will not begin with $SRC_DIR_REAL,
+// so we have to do it ourselves.
+//@ normalize-stderr-test: ".rs:\d+:\d+" -> ".rs:LL:COL"
+
+use std::thread;
+struct Worker {
+ thread: thread::JoinHandle<()>,
+}
+
+impl Drop for Worker {
+ fn drop(&mut self) {
+ self.thread.join().unwrap();
+ }
+}
+
+pub fn main(){}
diff --git a/tests/ui/errors/remap-path-prefix-sysroot.with-remap.stderr b/tests/ui/errors/remap-path-prefix-sysroot.with-remap.stderr
new file mode 100644
index 00000000000..88d713d2b04
--- /dev/null
+++ b/tests/ui/errors/remap-path-prefix-sysroot.with-remap.stderr
@@ -0,0 +1,17 @@
+error[E0507]: cannot move out of `self.thread` which is behind a mutable reference
+ --> remapped-tests-ui/errors/remap-path-prefix-sysroot.rs:LL:COL
+ |
+LL | self.thread.join().unwrap();
+ | ^^^^^^^^^^^ ------ `self.thread` moved due to this method call
+ | |
+ | move occurs because `self.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait
+ |
+note: `JoinHandle::<T>::join` takes ownership of the receiver `self`, which moves `self.thread`
+ --> remapped/library/std/src/thread/mod.rs:LL:COL
+ |
+LL | pub fn join(self) -> Result<T> {
+ | ^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/errors/remap-path-prefix-sysroot.without-remap.stderr b/tests/ui/errors/remap-path-prefix-sysroot.without-remap.stderr
new file mode 100644
index 00000000000..9b337699c32
--- /dev/null
+++ b/tests/ui/errors/remap-path-prefix-sysroot.without-remap.stderr
@@ -0,0 +1,17 @@
+error[E0507]: cannot move out of `self.thread` which is behind a mutable reference
+ --> $DIR/remap-path-prefix-sysroot.rs:LL:COL
+ |
+LL | self.thread.join().unwrap();
+ | ^^^^^^^^^^^ ------ `self.thread` moved due to this method call
+ | |
+ | move occurs because `self.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait
+ |
+note: `JoinHandle::<T>::join` takes ownership of the receiver `self`, which moves `self.thread`
+ --> $SRC_DIR_REAL/std/src/thread/mod.rs:LL:COL
+ |
+LL | pub fn join(self) -> Result<T> {
+ | ^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0507`.