From 92b10819efecc0a2a638050d8fc8c9b2d2ad14d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:19:10 +0800 Subject: [PATCH 01/23] tidy: skip revision llvm-components check for run-make tests Since run-make tests do not support revisions. --- src/tools/tidy/src/target_specific_tests.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs index 8be27d1e117ce..c1032b19f9709 100644 --- a/src/tools/tidy/src/target_specific_tests.rs +++ b/src/tools/tidy/src/target_specific_tests.rs @@ -36,8 +36,8 @@ struct RevisionInfo<'a> { llvm_components: Option>, } -pub fn check(path: &Path, bad: &mut bool) { - crate::walk::walk(path, |path, _is_dir| filter_not_rust(path), &mut |entry, content| { +pub fn check(tests_path: &Path, bad: &mut bool) { + crate::walk::walk(tests_path, |path, _is_dir| filter_not_rust(path), &mut |entry, content| { let file = entry.path().display(); let mut header_map = BTreeMap::new(); iter_header(content, &mut |HeaderLine { revision, directive, .. }| { @@ -65,6 +65,12 @@ pub fn check(path: &Path, bad: &mut bool) { } } }); + + // Skip run-make tests as revisions are not supported. + if entry.path().strip_prefix(tests_path).is_ok_and(|rest| rest.starts_with("run-make")) { + return; + } + for (rev, RevisionInfo { target_arch, llvm_components }) in &header_map { let rev = rev.unwrap_or("[unspecified]"); match (target_arch, llvm_components) { From beaf9d1c14122a55d71717560162c8123f5f23ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:20:32 +0800 Subject: [PATCH 02/23] tests/run-make: add missing needs-llvm-components Without suitable `needs-llvm-components` directives, these tests that rely on target-specific codegen can fail if used with a LLVM that is built without the required components. --- tests/run-make/print-cfg/rmake.rs | 5 +++++ tests/run-make/print-target-list/rmake.rs | 13 +++++++++---- tests/run-make/print-to-output/rmake.rs | 10 ++++++++-- tests/run-make/target-without-atomic-cas/rmake.rs | 15 ++++++++++----- 4 files changed, 32 insertions(+), 11 deletions(-) diff --git a/tests/run-make/print-cfg/rmake.rs b/tests/run-make/print-cfg/rmake.rs index 471a99b90d982..7b8b760ea333b 100644 --- a/tests/run-make/print-cfg/rmake.rs +++ b/tests/run-make/print-cfg/rmake.rs @@ -5,6 +5,11 @@ //! //! It also checks that some targets have the correct set cfgs. +// ignore-tidy-linelength +//@ needs-llvm-components: arm x86 +// Note: without the needs-llvm-components it will fail on LLVM built without the required +// components listed above. + use std::collections::HashSet; use std::iter::FromIterator; use std::path::PathBuf; diff --git a/tests/run-make/print-target-list/rmake.rs b/tests/run-make/print-target-list/rmake.rs index 743ed52069dea..04ef8440104f6 100644 --- a/tests/run-make/print-target-list/rmake.rs +++ b/tests/run-make/print-target-list/rmake.rs @@ -1,10 +1,15 @@ -// Checks that all the targets returned by `rustc --print target-list` are valid -// target specifications +// Checks that all the targets returned by `rustc --print target-list` are valid target +// specifications. + +// ignore-tidy-linelength +//@ needs-llvm-components: aarch64 arm avr bpf csky hexagon loongarch m68k mips msp430 nvptx powerpc riscv sparc systemz webassembly x86 +// FIXME(jieyouxu): there has to be a better way to do this, without the needs-llvm-components it +// will fail on LLVM built without all of the components listed above. use run_make_support::bare_rustc; -// FIXME(127877): certain experimental targets fail with creating a 'LLVM TargetMachine' -// in CI, so we skip them +// FIXME(#127877): certain experimental targets fail with creating a 'LLVM TargetMachine' in CI, so +// we skip them. const EXPERIMENTAL_TARGETS: &[&str] = &["avr", "m68k", "csky", "xtensa"]; fn main() { diff --git a/tests/run-make/print-to-output/rmake.rs b/tests/run-make/print-to-output/rmake.rs index db2a291f8e737..a85ab5e23b080 100644 --- a/tests/run-make/print-to-output/rmake.rs +++ b/tests/run-make/print-to-output/rmake.rs @@ -1,5 +1,11 @@ -//! This checks the output of some `--print` options when -//! output to a file (instead of stdout) +//! This checks the output of some `--print` options when output to a file (instead of stdout) + +// ignore-tidy-linelength +//@ needs-llvm-components: aarch64 arm avr bpf csky hexagon loongarch m68k mips msp430 nvptx powerpc riscv sparc systemz webassembly x86 +// FIXME(jieyouxu): there has to be a better way to do this, without the needs-llvm-components it +// will fail on LLVM built without all of the components listed above. If adding a new target that +// relies on a llvm component not listed above, it will need to be added to the required llvm +// components above. use std::path::PathBuf; diff --git a/tests/run-make/target-without-atomic-cas/rmake.rs b/tests/run-make/target-without-atomic-cas/rmake.rs index c8782b6d1a566..e6c86c0c21d96 100644 --- a/tests/run-make/target-without-atomic-cas/rmake.rs +++ b/tests/run-make/target-without-atomic-cas/rmake.rs @@ -1,8 +1,13 @@ -// ARM Cortex-M are a class of processors supported by the rust compiler. However, -// they cannot support any atomic features, such as Arc. This test simply prints -// the configuration details of one Cortex target, and checks that the compiler -// does not falsely list atomic support. -// See https://github.com/rust-lang/rust/pull/36874 +// ARM Cortex-M are a class of processors supported by the rust compiler. However, they cannot +// support any atomic features, such as Arc. This test simply prints the configuration details of +// one Cortex target, and checks that the compiler does not falsely list atomic support. +// See . + +// ignore-tidy-linelength +//@ needs-llvm-components: arm +// Note: without the needs-llvm-components it will fail on LLVM built without all of the components +// listed above. If any new targets are added, please double-check their respective llvm components +// are specified above. use run_make_support::rustc; From 2c141a454249ea0edbab2f4697eb634063e8b032 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 27 Aug 2024 15:22:15 +1000 Subject: [PATCH 03/23] Update old comment referring to `libcompiler_builtins` --- library/profiler_builtins/build.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs index c1e0e5c1c8975..b57f1187f8356 100644 --- a/library/profiler_builtins/build.rs +++ b/library/profiler_builtins/build.rs @@ -1,6 +1,8 @@ //! Compiles the profiler part of the `compiler-rt` library. //! -//! See the build.rs for libcompiler_builtins crate for details. +//! Loosely based on: +//! - LLVM's `compiler-rt/lib/profile/CMakeLists.txt` +//! - . use std::env; use std::path::PathBuf; From fcce75e9a666c60d106a04cbffc365c01364f1fd Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 27 Aug 2024 14:46:24 +1000 Subject: [PATCH 04/23] Use helper functions to read environment variables This also migrates from legacy `cargo:` directives to the newer `cargo::` prefix. --- library/profiler_builtins/build.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs index b57f1187f8356..b9aaf512d5a17 100644 --- a/library/profiler_builtins/build.rs +++ b/library/profiler_builtins/build.rs @@ -8,9 +8,8 @@ use std::env; use std::path::PathBuf; fn main() { - println!("cargo:rerun-if-env-changed=LLVM_PROFILER_RT_LIB"); - if let Ok(rt) = env::var("LLVM_PROFILER_RT_LIB") { - println!("cargo:rustc-link-lib=static:+verbatim={rt}"); + if let Ok(rt) = tracked_env_var("LLVM_PROFILER_RT_LIB") { + println!("cargo::rustc-link-lib=static:+verbatim={rt}"); return; } @@ -82,12 +81,10 @@ fn main() { } // Get the LLVM `compiler-rt` directory from bootstrap. - println!("cargo:rerun-if-env-changed=RUST_COMPILER_RT_FOR_PROFILER"); - let root = PathBuf::from(env::var("RUST_COMPILER_RT_FOR_PROFILER").unwrap_or_else(|_| { - let path = "../../src/llvm-project/compiler-rt"; - println!("RUST_COMPILER_RT_FOR_PROFILER was not set; falling back to {path:?}"); - path.to_owned() - })); + let root = PathBuf::from(tracked_env_var_or_fallback( + "RUST_COMPILER_RT_FOR_PROFILER", + "../../src/llvm-project/compiler-rt", + )); let src_root = root.join("lib").join("profile"); assert!(src_root.exists(), "profiler runtime source directory not found: {src_root:?}"); @@ -105,3 +102,14 @@ fn main() { cfg.warnings(false); cfg.compile("profiler-rt"); } + +fn tracked_env_var(key: &str) -> Result { + println!("cargo::rerun-if-env-changed={key}"); + env::var(key) +} +fn tracked_env_var_or_fallback(key: &str, fallback: &str) -> String { + tracked_env_var(key).unwrap_or_else(|_| { + println!("cargo::warning={key} was not set; falling back to {fallback:?}"); + fallback.to_owned() + }) +} From b6dba995b4efddfae2b567f7bce8d5217a0e7477 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 27 Aug 2024 15:04:10 +1000 Subject: [PATCH 05/23] Remove `InstrProfilingBiasVar.c` from the list of source files This file was introduced in LLVM 11, but was then removed in LLVM 13. --- library/profiler_builtins/build.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs index b9aaf512d5a17..7dcbcc444ba4d 100644 --- a/library/profiler_builtins/build.rs +++ b/library/profiler_builtins/build.rs @@ -40,7 +40,6 @@ fn main() { "InstrProfilingWriter.c", // These files were added in LLVM 11. "InstrProfilingInternal.c", - "InstrProfilingBiasVar.c", ]; if target_env == "msvc" { From 25ca8a283f757b95929da385c4493b45e3012e78 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 27 Aug 2024 15:12:51 +1000 Subject: [PATCH 06/23] Sort the list of source files --- library/profiler_builtins/build.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs index 7dcbcc444ba4d..6089937e0b7a2 100644 --- a/library/profiler_builtins/build.rs +++ b/library/profiler_builtins/build.rs @@ -20,10 +20,12 @@ fn main() { // FIXME: `rerun-if-changed` directives are not currently emitted and the build script // will not rerun on changes in these source files or headers included into them. let mut profile_sources = vec![ + // tidy-alphabetical-start "GCDAProfiling.c", "InstrProfiling.c", "InstrProfilingBuffer.c", "InstrProfilingFile.c", + "InstrProfilingInternal.c", "InstrProfilingMerge.c", "InstrProfilingMergeFile.c", "InstrProfilingNameVar.c", @@ -38,8 +40,7 @@ fn main() { "InstrProfilingValue.c", "InstrProfilingVersionVar.c", "InstrProfilingWriter.c", - // These files were added in LLVM 11. - "InstrProfilingInternal.c", + // tidy-alphabetical-end ]; if target_env == "msvc" { From 842cda6865ca297135f53083bd013aa91abb5587 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 27 Aug 2024 15:15:08 +1000 Subject: [PATCH 07/23] Always include `WindowsMMap.c` in the list of source files The whole file is surrounded by `#if defined(_WIN32)`, so there's no need to have separate logic to exclue it from non-Windows builds. --- library/profiler_builtins/build.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs index 6089937e0b7a2..93048a6dec75c 100644 --- a/library/profiler_builtins/build.rs +++ b/library/profiler_builtins/build.rs @@ -19,7 +19,7 @@ fn main() { // FIXME: `rerun-if-changed` directives are not currently emitted and the build script // will not rerun on changes in these source files or headers included into them. - let mut profile_sources = vec![ + let profile_sources = vec![ // tidy-alphabetical-start "GCDAProfiling.c", "InstrProfiling.c", @@ -40,13 +40,13 @@ fn main() { "InstrProfilingValue.c", "InstrProfilingVersionVar.c", "InstrProfilingWriter.c", + "WindowsMMap.c", // tidy-alphabetical-end ]; if target_env == "msvc" { // Don't pull in extra libraries on MSVC cfg.flag("/Zl"); - profile_sources.push("WindowsMMap.c"); cfg.define("strdup", Some("_strdup")); cfg.define("open", Some("_open")); cfg.define("fdopen", Some("_fdopen")); @@ -61,8 +61,6 @@ fn main() { if target_os != "windows" { cfg.flag("-fvisibility=hidden"); cfg.define("COMPILER_RT_HAS_UNAME", Some("1")); - } else { - profile_sources.push("WindowsMMap.c"); } } From 7f90aa5538454c226b664ed882729e5f24251bd4 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 27 Aug 2024 15:38:26 +1000 Subject: [PATCH 08/23] Add `cargo::rerun-if-changed` directives for source directories --- library/profiler_builtins/build.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs index 93048a6dec75c..bf4a1749322de 100644 --- a/library/profiler_builtins/build.rs +++ b/library/profiler_builtins/build.rs @@ -17,8 +17,6 @@ fn main() { let target_env = env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV was not set"); let cfg = &mut cc::Build::new(); - // FIXME: `rerun-if-changed` directives are not currently emitted and the build script - // will not rerun on changes in these source files or headers included into them. let profile_sources = vec![ // tidy-alphabetical-start "GCDAProfiling.c", @@ -86,6 +84,7 @@ fn main() { let src_root = root.join("lib").join("profile"); assert!(src_root.exists(), "profiler runtime source directory not found: {src_root:?}"); + println!("cargo::rerun-if-changed={}", src_root.display()); let mut n_sources_found = 0u32; for src in profile_sources { let path = src_root.join(src); @@ -96,7 +95,10 @@ fn main() { } assert!(n_sources_found > 0, "couldn't find any profiler runtime source files in {src_root:?}"); - cfg.include(root.join("include")); + let include = root.join("include"); + println!("cargo::rerun-if-changed={}", include.display()); + cfg.include(include); + cfg.warnings(false); cfg.compile("profiler-rt"); } From 5b6ff4fe18e4294ac2180325cdb46494a051706c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 27 Aug 2024 15:41:46 +1000 Subject: [PATCH 09/23] Don't skip nonexistent source files This behaviour was introduced during the upgrade to LLVM 11. Now that the list of source files has been cleaned up, we can reasonably expect _all_ of the listed source files to be present. --- library/profiler_builtins/build.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs index bf4a1749322de..dd85239fa8cfd 100644 --- a/library/profiler_builtins/build.rs +++ b/library/profiler_builtins/build.rs @@ -85,15 +85,9 @@ fn main() { let src_root = root.join("lib").join("profile"); assert!(src_root.exists(), "profiler runtime source directory not found: {src_root:?}"); println!("cargo::rerun-if-changed={}", src_root.display()); - let mut n_sources_found = 0u32; - for src in profile_sources { - let path = src_root.join(src); - if path.exists() { - cfg.file(path); - n_sources_found += 1; - } + for file in profile_sources { + cfg.file(src_root.join(file)); } - assert!(n_sources_found > 0, "couldn't find any profiler runtime source files in {src_root:?}"); let include = root.join("include"); println!("cargo::rerun-if-changed={}", include.display()); From 6ba72c0c7e392c4ee847abee407a858346b81498 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 27 Aug 2024 10:47:58 +0300 Subject: [PATCH 10/23] skip stage 0 target check if `BOOTSTRAP_SKIP_TARGET_SANITY` is set Signed-off-by: onur-ozkan --- src/bootstrap/src/core/sanity.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index c42d4c56c3816..60ec57d0d443a 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -8,9 +8,7 @@ //! In theory if we get past this phase it's a bug if a build fails, but in //! practice that's likely not true! -use std::collections::HashMap; -#[cfg(not(feature = "bootstrap-self-test"))] -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::ffi::{OsStr, OsString}; use std::path::PathBuf; use std::{env, fs}; @@ -34,7 +32,6 @@ pub struct Finder { // it might not yet be included in stage0. In such cases, we handle the targets missing from stage0 in this list. // // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap). -#[cfg(not(feature = "bootstrap-self-test"))] const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined ]; @@ -205,7 +202,6 @@ than building it. .map(|p| cmd_finder.must_have(p)) .or_else(|| cmd_finder.maybe_have("reuse")); - #[cfg(not(feature = "bootstrap-self-test"))] let stage0_supported_target_list: HashSet = crate::utils::helpers::output( command(&build.config.initial_rustc).args(["--print", "target-list"]).as_command_mut(), ) @@ -234,8 +230,7 @@ than building it. } // Ignore fake targets that are only used for unit tests in bootstrap. - #[cfg(not(feature = "bootstrap-self-test"))] - { + if cfg!(not(feature = "bootstrap-self-test")) && !skip_target_sanity { let mut has_target = false; let target_str = target.to_string(); From 1a743710aa80b73af7023e3975097c59a47d9d01 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 27 Aug 2024 12:19:05 +0300 Subject: [PATCH 11/23] set `BOOTSTRAP_SKIP_TARGET_SANITY` in opt-dist before running tests opt-dist overrides the stage 0 compiler with previously compiled compilers, which can cause confusion in bootstrap's target sanity checks. It is best to skip that check. Signed-off-by: onur-ozkan --- src/tools/opt-dist/src/tests.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs index 30c9648bc08e9..9dbba7a05001d 100644 --- a/src/tools/opt-dist/src/tests.rs +++ b/src/tools/opt-dist/src/tests.rs @@ -102,7 +102,13 @@ llvm-config = "{llvm_config}" for test_path in env.skipped_tests() { args.extend(["--skip", test_path]); } - cmd(&args).env("COMPILETEST_FORCE_STAGE0", "1").run().context("Cannot execute tests") + cmd(&args) + .env("COMPILETEST_FORCE_STAGE0", "1") + // Above we override the stage 0 compiler with previously compiled compiler, + // which can cause confusion in bootstrap's target sanity checks. + .env("BOOTSTRAP_SKIP_TARGET_SANITY", "1") + .run() + .context("Cannot execute tests") } /// Tries to find the version of the dist artifacts (either nightly, beta, or 1.XY.Z). From 99558dc7f4ac4ed6a534136b57caf7a10a62c0bb Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 29 Aug 2024 14:38:45 -0700 Subject: [PATCH 12/23] Update the `wasm-component-ld` binary dependency This keeps it up-to-date by moving from 0.5.6 to 0.5.7. While here I've additionally updated some other wasm-related dependencies in the workspace to keep them up-to-date and try to avoid duplicate versions as well. --- Cargo.lock | 55 ++++++++++++++++----------- compiler/rustc_codegen_ssa/Cargo.toml | 2 +- src/tools/run-make-support/Cargo.toml | 2 +- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ea4cd8f5aca4..23c7a5bc60f19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2463,7 +2463,7 @@ dependencies = [ "indexmap", "memchr", "ruzstd 0.7.0", - "wasmparser", + "wasmparser 0.215.0", ] [[package]] @@ -3133,7 +3133,7 @@ dependencies = [ "regex", "serde_json", "similar", - "wasmparser", + "wasmparser 0.216.0", ] [[package]] @@ -5779,9 +5779,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi-preview1-component-adapter-provider" -version = "23.0.2" +version = "24.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91d3d13afef569b9fc80cfbb807c87c16ef49bd3ac1a93285ea6a264b600d2d" +checksum = "36e6cadfa74538edd5409b6f8c79628436529138e9618b7373bec7aae7805835" [[package]] name = "wasm-bindgen" @@ -5840,16 +5840,16 @@ checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasm-component-ld" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51449c63d1ce69f92b8465a084ed5b91f1a7eb583fa95796650a6bfcffc4f9cb" +checksum = "13261270d3ac58ffae0219ae34f297a7e24f9ee3b13b29be579132c588a83519" dependencies = [ "anyhow", "clap", "lexopt", "tempfile", "wasi-preview1-component-adapter-provider", - "wasmparser", + "wasmparser 0.216.0", "wat", "wit-component", "wit-parser", @@ -5864,19 +5864,19 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.215.0" +version = "0.216.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb56df3e06b8e6b77e37d2969a50ba51281029a9aeb3855e76b7f49b6418847" +checksum = "04c23aebea22c8a75833ae08ed31ccc020835b12a41999e58c31464271b94a88" dependencies = [ "leb128", - "wasmparser", + "wasmparser 0.216.0", ] [[package]] name = "wasm-metadata" -version = "0.215.0" +version = "0.216.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6bb07c5576b608f7a2a9baa2294c1a3584a249965d695a9814a496cb6d232f" +checksum = "47c8154d703a6b0e45acf6bd172fa002fc3c7058a9f7615e517220aeca27c638" dependencies = [ "anyhow", "indexmap", @@ -5885,7 +5885,7 @@ dependencies = [ "serde_json", "spdx", "wasm-encoder", - "wasmparser", + "wasmparser 0.216.0", ] [[package]] @@ -5893,6 +5893,15 @@ name = "wasmparser" version = "0.215.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53fbde0881f24199b81cf49b6ff8f9c145ac8eb1b7fc439adb5c099734f7d90e" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "wasmparser" +version = "0.216.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcdee6bea3619d311fb4b299721e89a986c3470f804b6d534340e412589028e3" dependencies = [ "ahash", "bitflags 2.6.0", @@ -5904,9 +5913,9 @@ dependencies = [ [[package]] name = "wast" -version = "215.0.0" +version = "216.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff1d00d893593249e60720be04a7c1f42f1c4dc3806a2869f4e66ab61eb54cb" +checksum = "f7eb1f2eecd913fdde0dc6c3439d0f24530a98ac6db6cb3d14d92a5328554a08" dependencies = [ "bumpalo", "leb128", @@ -5917,9 +5926,9 @@ dependencies = [ [[package]] name = "wat" -version = "1.215.0" +version = "1.216.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670bf4d9c8cf76ae242d70ded47c546525b6dafaa6871f9bcb065344bf2b4e3d" +checksum = "ac0409090fb5154f95fb5ba3235675fd9e579e731524d63b6a2f653e1280c82a" dependencies = [ "wast", ] @@ -6206,9 +6215,9 @@ dependencies = [ [[package]] name = "wit-component" -version = "0.215.0" +version = "0.216.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f725e3885fc5890648be5c5cbc1353b755dc932aa5f1aa7de968b912a3280743" +checksum = "7e2ca3ece38ea2447a9069b43074ba73d96dde1944cba276c54e41371745f9dc" dependencies = [ "anyhow", "bitflags 2.6.0", @@ -6219,15 +6228,15 @@ dependencies = [ "serde_json", "wasm-encoder", "wasm-metadata", - "wasmparser", + "wasmparser 0.216.0", "wit-parser", ] [[package]] name = "wit-parser" -version = "0.215.0" +version = "0.216.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "935a97eaffd57c3b413aa510f8f0b550a4a9fe7d59e79cd8b89a83dcb860321f" +checksum = "a4d108165c1167a4ccc8a803dcf5c28e0a51d6739fd228cc7adce768632c764c" dependencies = [ "anyhow", "id-arena", @@ -6238,7 +6247,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser", + "wasmparser 0.216.0", ] [[package]] diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index e78039bafd8dd..3ab4cd0a0f53c 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -41,7 +41,7 @@ tempfile = "3.2" thin-vec = "0.2.12" thorin-dwp = "0.7" tracing = "0.1" -wasm-encoder = "0.215.0" +wasm-encoder = "0.216.0" # tidy-alphabetical-end [target.'cfg(unix)'.dependencies] diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml index 77df6e7beb591..d3605cd3dce05 100644 --- a/src/tools/run-make-support/Cargo.toml +++ b/src/tools/run-make-support/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" bstr = "1.6.0" object = "0.36.2" similar = "2.5.0" -wasmparser = { version = "0.215", default-features = false, features = ["std"] } +wasmparser = { version = "0.216", default-features = false, features = ["std"] } regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace gimli = "0.31.0" build_helper = { path = "../build_helper" } From 355d7c9ecda6dbb63812aafb744873f6bc9c5e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 30 Aug 2024 12:38:22 +0200 Subject: [PATCH 13/23] couple more crash tests --- tests/crashes/129425.rs | 6 ++++++ tests/crashes/129444.rs | 15 +++++++++++++++ tests/crashes/129503.rs | 7 +++++++ tests/crashes/129556.rs | 26 ++++++++++++++++++++++++++ 4 files changed, 54 insertions(+) create mode 100644 tests/crashes/129425.rs create mode 100644 tests/crashes/129444.rs create mode 100644 tests/crashes/129503.rs create mode 100644 tests/crashes/129556.rs diff --git a/tests/crashes/129425.rs b/tests/crashes/129425.rs new file mode 100644 index 0000000000000..ac7dc0078474d --- /dev/null +++ b/tests/crashes/129425.rs @@ -0,0 +1,6 @@ +//@ known-bug: rust-lang/rust#129425 + +//@compile-flags: --crate-type=lib + +#![feature(generic_const_exprs)] +fn foo<'a, T: 'a>(_: [(); std::mem::offset_of!((T,), 0)]) {} diff --git a/tests/crashes/129444.rs b/tests/crashes/129444.rs new file mode 100644 index 0000000000000..b1b547b5191bd --- /dev/null +++ b/tests/crashes/129444.rs @@ -0,0 +1,15 @@ +//@ known-bug: rust-lang/rust#129444 + +//@ compile-flags: -Znext-solver=coherence + +trait Trait { + type Assoc; +} + +struct W(*mut T); +impl Trait for W>> {} + +trait NoOverlap {} +impl>> NoOverlap for T {} + +impl> NoOverlap for W {} diff --git a/tests/crashes/129503.rs b/tests/crashes/129503.rs new file mode 100644 index 0000000000000..c1ed46e595570 --- /dev/null +++ b/tests/crashes/129503.rs @@ -0,0 +1,7 @@ +//@ known-bug: rust-lang/rust#129503 + +use std::arch::asm; + +unsafe fn f6() { + asm!(concat!(r#"lJ𐏿Æ�.𐏿�"#, "r} {}")); +} diff --git a/tests/crashes/129556.rs b/tests/crashes/129556.rs new file mode 100644 index 0000000000000..364827e9444f6 --- /dev/null +++ b/tests/crashes/129556.rs @@ -0,0 +1,26 @@ +//@ known-bug: rust-lang/rust#129556 + +#![feature(adt_const_params)] +#![feature(generic_const_exprs)] + +use core::marker::ConstParamTy; + +// #[derive(ConstParamTy, PartialEq, Eq)] +// struct StructOrEnum; + +#[derive(ConstParamTy, PartialEq, Eq)] +enum StructOrEnum { + A, +} + +trait TraitParent {} + +trait TraitChild: TraitParent {} + +impl TraitParent for StructOrEnum {} + +// ICE occurs +impl TraitChild for StructOrEnum {} + +// ICE does not occur +// impl TraitChild<{ StructOrEnum::A }> for StructOrEnum {} From 7fde02ea53f423ca25740e9339d8ff1db8f73052 Mon Sep 17 00:00:00 2001 From: Strophox Date: Wed, 31 Jul 2024 09:41:14 +0200 Subject: [PATCH 14/23] enable Miri to pass const pointers through FFI Co-authored-by: Ralf Jung --- .../rustc_const_eval/src/interpret/machine.rs | 12 +-- .../src/mir/interpret/allocation.rs | 3 +- src/tools/miri/src/alloc_addresses/mod.rs | 68 ++++++++++++++- src/tools/miri/src/concurrency/thread.rs | 2 +- src/tools/miri/src/lib.rs | 3 + src/tools/miri/src/machine.rs | 25 ++++++ src/tools/miri/src/shims/native_lib.rs | 13 +++ .../{libtest.map => native-lib.map} | 8 ++ .../tests/native-lib/pass/ptr_read_access.rs | 82 +++++++++++++++++++ .../native-lib/pass/ptr_read_access.stdout | 1 + ...all_extern_c_fn.rs => scalar_arguments.rs} | 0 ...rn_c_fn.stdout => scalar_arguments.stdout} | 0 .../miri/tests/native-lib/ptr_read_access.c | 47 +++++++++++ .../native-lib/{test.c => scalar_arguments.c} | 0 src/tools/miri/tests/ui.rs | 13 ++- 15 files changed, 260 insertions(+), 17 deletions(-) rename src/tools/miri/tests/native-lib/{libtest.map => native-lib.map} (62%) create mode 100644 src/tools/miri/tests/native-lib/pass/ptr_read_access.rs create mode 100644 src/tools/miri/tests/native-lib/pass/ptr_read_access.stdout rename src/tools/miri/tests/native-lib/pass/{call_extern_c_fn.rs => scalar_arguments.rs} (100%) rename src/tools/miri/tests/native-lib/pass/{call_extern_c_fn.stdout => scalar_arguments.stdout} (100%) create mode 100644 src/tools/miri/tests/native-lib/ptr_read_access.c rename src/tools/miri/tests/native-lib/{test.c => scalar_arguments.c} (100%) diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 761ab81e22842..cff0612d58edb 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -357,17 +357,7 @@ pub trait Machine<'tcx>: Sized { ecx: &InterpCx<'tcx, Self>, id: AllocId, alloc: &'b Allocation, - ) -> InterpResult<'tcx, Cow<'b, Allocation>> - { - // The default implementation does a copy; CTFE machines have a more efficient implementation - // based on their particular choice for `Provenance`, `AllocExtra`, and `Bytes`. - let kind = Self::GLOBAL_KIND - .expect("if GLOBAL_KIND is None, adjust_global_allocation must be overwritten"); - let alloc = alloc.adjust_from_tcx(&ecx.tcx, |ptr| ecx.global_root_pointer(ptr))?; - let extra = - Self::init_alloc_extra(ecx, id, MemoryKind::Machine(kind), alloc.size(), alloc.align)?; - Ok(Cow::Owned(alloc.with_extra(extra))) - } + ) -> InterpResult<'tcx, Cow<'b, Allocation>>; /// Initialize the extra state of an allocation. /// diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 3e101c0c6354d..5fb8af576ae93 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -358,10 +358,11 @@ impl Allocation { pub fn adjust_from_tcx( &self, cx: &impl HasDataLayout, + mut alloc_bytes: impl FnMut(&[u8], Align) -> Result, mut adjust_ptr: impl FnMut(Pointer) -> Result, Err>, ) -> Result, Err> { // Copy the data. - let mut bytes = Bytes::from_bytes(Cow::Borrowed(&*self.bytes), self.align); + let mut bytes = alloc_bytes(&*self.bytes, self.align)?; // Adjust provenance of pointers stored in this allocation. let mut new_provenance = Vec::with_capacity(self.provenance.ptrs().len()); let ptr_size = cx.data_layout().pointer_size.bytes_usize(); diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index ed955e78c3e9a..76c68add8cdc9 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -42,6 +42,11 @@ pub struct GlobalStateInner { /// they do not have an `AllocExtra`. /// This is the inverse of `int_to_ptr_map`. base_addr: FxHashMap, + /// Temporarily store prepared memory space for global allocations the first time their memory + /// address is required. This is used to ensure that the memory is allocated before Miri assigns + /// it an internal address, which is important for matching the internal address to the machine + /// address so FFI can read from pointers. + prepared_alloc_bytes: FxHashMap, /// A pool of addresses we can reuse for future allocations. reuse: ReusePool, /// Whether an allocation has been exposed or not. This cannot be put @@ -59,6 +64,7 @@ impl VisitProvenance for GlobalStateInner { let GlobalStateInner { int_to_ptr_map: _, base_addr: _, + prepared_alloc_bytes: _, reuse: _, exposed: _, next_base_addr: _, @@ -78,6 +84,7 @@ impl GlobalStateInner { GlobalStateInner { int_to_ptr_map: Vec::default(), base_addr: FxHashMap::default(), + prepared_alloc_bytes: FxHashMap::default(), reuse: ReusePool::new(config), exposed: FxHashSet::default(), next_base_addr: stack_addr, @@ -166,7 +173,39 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { assert!(!matches!(kind, AllocKind::Dead)); // This allocation does not have a base address yet, pick or reuse one. - let base_addr = if let Some((reuse_addr, clock)) = global_state.reuse.take_addr( + let base_addr = if ecx.machine.native_lib.is_some() { + // In native lib mode, we use the "real" address of the bytes for this allocation. + // This ensures the interpreted program and native code have the same view of memory. + match kind { + AllocKind::LiveData => { + let ptr = if ecx.tcx.try_get_global_alloc(alloc_id).is_some() { + // For new global allocations, we always pre-allocate the memory to be able use the machine address directly. + let prepared_bytes = MiriAllocBytes::zeroed(size, align) + .unwrap_or_else(|| { + panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes") + }); + let ptr = prepared_bytes.as_ptr(); + // Store prepared allocation space to be picked up for use later. + global_state.prepared_alloc_bytes.try_insert(alloc_id, prepared_bytes).unwrap(); + ptr + } else { + ecx.get_alloc_bytes_unchecked_raw(alloc_id)? + }; + // Ensure this pointer's provenance is exposed, so that it can be used by FFI code. + ptr.expose_provenance().try_into().unwrap() + } + AllocKind::Function | AllocKind::VTable => { + // Allocate some dummy memory to get a unique address for this function/vtable. + let alloc_bytes = MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap()); + // We don't need to expose these bytes as nobody is allowed to access them. + let addr = alloc_bytes.as_ptr().addr().try_into().unwrap(); + // Leak the underlying memory to ensure it remains unique. + std::mem::forget(alloc_bytes); + addr + } + AllocKind::Dead => unreachable!() + } + } else if let Some((reuse_addr, clock)) = global_state.reuse.take_addr( &mut *rng, size, align, @@ -318,6 +357,33 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(base_ptr.wrapping_offset(offset, ecx)) } + // This returns some prepared `MiriAllocBytes`, either because `addr_from_alloc_id` reserved + // memory space in the past, or by doing the pre-allocation right upon being called. + fn get_global_alloc_bytes(&self, id: AllocId, kind: MemoryKind, bytes: &[u8], align: Align) -> InterpResult<'tcx, MiriAllocBytes> { + let ecx = self.eval_context_ref(); + Ok(if ecx.machine.native_lib.is_some() { + // In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`. + // This additional call ensures that some `MiriAllocBytes` are always prepared. + ecx.addr_from_alloc_id(id, kind)?; + let mut global_state = ecx.machine.alloc_addresses.borrow_mut(); + // The memory we need here will have already been allocated during an earlier call to + // `addr_from_alloc_id` for this allocation. So don't create a new `MiriAllocBytes` here, instead + // fetch the previously prepared bytes from `prepared_alloc_bytes`. + let mut prepared_alloc_bytes = global_state + .prepared_alloc_bytes + .remove(&id) + .unwrap_or_else(|| panic!("alloc bytes for {id:?} have not been prepared")); + // Sanity-check that the prepared allocation has the right size and alignment. + assert!(prepared_alloc_bytes.as_ptr().is_aligned_to(align.bytes_usize())); + assert_eq!(prepared_alloc_bytes.len(), bytes.len()); + // Copy allocation contents into prepared memory. + prepared_alloc_bytes.copy_from_slice(bytes); + prepared_alloc_bytes + } else { + MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(&*bytes), align) + }) + } + /// When a pointer is used for a memory access, this computes where in which allocation the /// access is going. fn ptr_get_alloc( diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index a4d3e3f7af3ce..37d4a2663e012 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -887,7 +887,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let alloc = this.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?; // We make a full copy of this allocation. let mut alloc = - alloc.inner().adjust_from_tcx(&this.tcx, |ptr| this.global_root_pointer(ptr))?; + alloc.inner().adjust_from_tcx(&this.tcx, |bytes, align| Ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align)), |ptr| this.global_root_pointer(ptr))?; // This allocation will be deallocated when the thread dies, so it is not in read-only memory. alloc.mutability = Mutability::Mut; // Create a fresh allocation with this content. diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index f796e845a2399..f70ca098fb95b 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -12,6 +12,9 @@ #![feature(let_chains)] #![feature(trait_upcasting)] #![feature(strict_overflow_ops)] +#![feature(strict_provenance)] +#![feature(exposed_provenance)] +#![feature(pointer_is_aligned_to)] // Configure clippy and other lints #![allow( clippy::collapsible_else_if, diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index a7493d48d6a2d..35bef5e6ed513 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1,6 +1,7 @@ //! Global machine state as well as implementation of the interpreter engine //! `Machine` trait. +use std::borrow::Cow; use std::cell::RefCell; use std::collections::hash_map::Entry; use std::fmt; @@ -1225,6 +1226,30 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { }) } + /// Called to adjust global allocations to the Provenance and AllocExtra of this machine. + /// + /// If `alloc` contains pointers, then they are all pointing to globals. + /// + /// This should avoid copying if no work has to be done! If this returns an owned + /// allocation (because a copy had to be done to adjust things), machine memory will + /// cache the result. (This relies on `AllocMap::get_or` being able to add the + /// owned allocation to the map even when the map is shared.) + fn adjust_global_allocation<'b>( + ecx: &InterpCx<'tcx, Self>, + id: AllocId, + alloc: &'b Allocation, + ) -> InterpResult<'tcx, Cow<'b, Allocation>> + { + let kind = Self::GLOBAL_KIND.unwrap().into(); + let alloc = alloc.adjust_from_tcx(&ecx.tcx, + |bytes, align| ecx.get_global_alloc_bytes(id, kind, bytes, align), + |ptr| ecx.global_root_pointer(ptr), + )?; + let extra = + Self::init_alloc_extra(ecx, id, kind, alloc.size(), alloc.align)?; + Ok(Cow::Owned(alloc.with_extra(extra))) + } + #[inline(always)] fn before_memory_read( _tcx: TyCtxtAt<'tcx>, diff --git a/src/tools/miri/src/shims/native_lib.rs b/src/tools/miri/src/shims/native_lib.rs index 40697e17ba193..25d96fbd7331f 100644 --- a/src/tools/miri/src/shims/native_lib.rs +++ b/src/tools/miri/src/shims/native_lib.rs @@ -194,6 +194,8 @@ enum CArg { UInt64(u64), /// usize. USize(usize), + /// Raw pointer, stored as C's `void*`. + RawPtr(*mut std::ffi::c_void), } impl<'a> CArg { @@ -210,6 +212,7 @@ impl<'a> CArg { CArg::UInt32(i) => ffi::arg(i), CArg::UInt64(i) => ffi::arg(i), CArg::USize(i) => ffi::arg(i), + CArg::RawPtr(i) => ffi::arg(i), } } } @@ -234,6 +237,16 @@ fn imm_to_carg<'tcx>(v: ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'t ty::Uint(UintTy::U64) => CArg::UInt64(v.to_scalar().to_u64()?), ty::Uint(UintTy::Usize) => CArg::USize(v.to_scalar().to_target_usize(cx)?.try_into().unwrap()), + ty::RawPtr(_, mutability) => { + // Arbitrary mutable pointer accesses are not currently supported in Miri. + if mutability.is_mut() { + throw_unsup_format!("unsupported mutable pointer type for native call: {}", v.layout.ty); + } else { + let s = v.to_scalar().to_pointer(cx)?.addr(); + // This relies on the `expose_provenance` in `addr_from_alloc_id`. + CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize())) + } + }, _ => throw_unsup_format!("unsupported argument type for native call: {}", v.layout.ty), }) } diff --git a/src/tools/miri/tests/native-lib/libtest.map b/src/tools/miri/tests/native-lib/native-lib.map similarity index 62% rename from src/tools/miri/tests/native-lib/libtest.map rename to src/tools/miri/tests/native-lib/native-lib.map index a57a4dc149feb..7e3bd19622af3 100644 --- a/src/tools/miri/tests/native-lib/libtest.map +++ b/src/tools/miri/tests/native-lib/native-lib.map @@ -1,12 +1,20 @@ CODEABI_1.0 { # Define which symbols to export. global: + # scalar_arguments.c add_one_int; printer; test_stack_spill; get_unsigned_int; add_int16; add_short_to_long; + + # ptr_read_access.c + print_pointer; + access_simple; + access_nested; + access_static; + # The rest remains private. local: *; }; diff --git a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs new file mode 100644 index 0000000000000..d8e6209839e2a --- /dev/null +++ b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs @@ -0,0 +1,82 @@ +//@only-target-linux +//@only-on-host + +fn main() { + test_pointer(); + + test_simple(); + + test_nested(); + + test_static(); +} + +// Test void function that dereferences a pointer and prints its contents from C. +fn test_pointer() { + extern "C" { + fn print_pointer(ptr: *const i32); + } + + let x = 42; + + unsafe { print_pointer(&x) }; +} + +// Test function that dereferences a simple struct pointer and accesses a field. +fn test_simple() { + #[repr(C)] + struct Simple { + field: i32 + } + + extern "C" { + fn access_simple(s_ptr: *const Simple) -> i32; + } + + let simple = Simple { field: -42 }; + + assert_eq!(unsafe { access_simple(&simple) }, -42); +} + +// Test function that dereferences nested struct pointers and accesses fields. +fn test_nested() { + use std::ptr::NonNull; + + #[derive(Debug, PartialEq, Eq)] + #[repr(C)] + struct Nested { + value: i32, + next: Option>, + } + + extern "C" { + fn access_nested(n_ptr: *const Nested) -> i32; + } + + let mut nested_0 = Nested { value: 97, next: None }; + let mut nested_1 = Nested { value: 98, next: NonNull::new(&mut nested_0) }; + let nested_2 = Nested { value: 99, next: NonNull::new(&mut nested_1) }; + + assert_eq!(unsafe { access_nested(&nested_2) }, 97); +} + +// Test function that dereferences static struct pointers and accesses fields. +fn test_static() { + + #[repr(C)] + struct Static { + value: i32, + recurse: &'static Static, + } + + extern "C" { + fn access_static(n_ptr: *const Static) -> i32; + } + + static STATIC: Static = Static { + value: 9001, + recurse: &STATIC, + }; + + assert_eq!(unsafe { access_static(&STATIC) }, 9001); +} diff --git a/src/tools/miri/tests/native-lib/pass/ptr_read_access.stdout b/src/tools/miri/tests/native-lib/pass/ptr_read_access.stdout new file mode 100644 index 0000000000000..1a8799abfc93e --- /dev/null +++ b/src/tools/miri/tests/native-lib/pass/ptr_read_access.stdout @@ -0,0 +1 @@ +printing pointer dereference from C: 42 diff --git a/src/tools/miri/tests/native-lib/pass/call_extern_c_fn.rs b/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs similarity index 100% rename from src/tools/miri/tests/native-lib/pass/call_extern_c_fn.rs rename to src/tools/miri/tests/native-lib/pass/scalar_arguments.rs diff --git a/src/tools/miri/tests/native-lib/pass/call_extern_c_fn.stdout b/src/tools/miri/tests/native-lib/pass/scalar_arguments.stdout similarity index 100% rename from src/tools/miri/tests/native-lib/pass/call_extern_c_fn.stdout rename to src/tools/miri/tests/native-lib/pass/scalar_arguments.stdout diff --git a/src/tools/miri/tests/native-lib/ptr_read_access.c b/src/tools/miri/tests/native-lib/ptr_read_access.c new file mode 100644 index 0000000000000..03b9189e2e86d --- /dev/null +++ b/src/tools/miri/tests/native-lib/ptr_read_access.c @@ -0,0 +1,47 @@ +#include + +/* Test: test_pointer */ + +void print_pointer(const int *ptr) { + printf("printing pointer dereference from C: %d\n", *ptr); +} + +/* Test: test_simple */ + +typedef struct Simple { + int field; +} Simple; + +int access_simple(const Simple *s_ptr) { + return s_ptr->field; +} + +/* Test: test_nested */ + +typedef struct Nested { + int value; + struct Nested *next; +} Nested; + +// Returns the innermost/last value of a Nested pointer chain. +int access_nested(const Nested *n_ptr) { + // Edge case: `n_ptr == NULL` (i.e. first Nested is None). + if (!n_ptr) { return 0; } + + while (n_ptr->next) { + n_ptr = n_ptr->next; + } + + return n_ptr->value; +} + +/* Test: test_static */ + +typedef struct Static { + int value; + struct Static *recurse; +} Static; + +int access_static(const Static *s_ptr) { + return s_ptr->recurse->recurse->value; +} diff --git a/src/tools/miri/tests/native-lib/test.c b/src/tools/miri/tests/native-lib/scalar_arguments.c similarity index 100% rename from src/tools/miri/tests/native-lib/test.c rename to src/tools/miri/tests/native-lib/scalar_arguments.c diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs index 9cbcf6e42a795..c510ef95c30e8 100644 --- a/src/tools/miri/tests/ui.rs +++ b/src/tools/miri/tests/ui.rs @@ -36,18 +36,25 @@ fn build_native_lib() -> PathBuf { // Create the directory if it does not already exist. std::fs::create_dir_all(&so_target_dir) .expect("Failed to create directory for shared object file"); - let so_file_path = so_target_dir.join("libtestlib.so"); + let so_file_path = so_target_dir.join("native-lib.so"); let cc_output = Command::new(cc) .args([ "-shared", "-o", so_file_path.to_str().unwrap(), - "tests/native-lib/test.c", + // FIXME: Automate gathering of all relevant C source files in the directory. + "tests/native-lib/scalar_arguments.c", + "tests/native-lib/ptr_read_access.c", // Only add the functions specified in libcode.version to the shared object file. // This is to avoid automatically adding `malloc`, etc. // Source: https://anadoxin.org/blog/control-over-symbol-exports-in-gcc.html/ "-fPIC", - "-Wl,--version-script=tests/native-lib/libtest.map", + "-Wl,--version-script=tests/native-lib/native-lib.map", + // Ensure we notice serious problems in the C code. + "-Wall", + "-Wextra", + "-Wpedantic", + "-Werror", ]) .output() .expect("failed to generate shared object file for testing native function calls"); From 8c19c14c3f0ad2828fa6fcaf9c5402b2d87fa08f Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 1 Aug 2024 17:32:13 -0700 Subject: [PATCH 15/23] Add release notes for 1.81.0 --- RELEASES.md | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 5e4827be4ecfd..79771ef1d8cc8 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,123 @@ +Version 1.81.0 (2024-09-05) +========================== + + + +Language +-------- + +- [Abort on uncaught panics in `extern "C"` functions.](https://github.com/rust-lang/rust/pull/116088/) +- [Fix ambiguous cases of multiple `&` in elided self lifetimes.](https://github.com/rust-lang/rust/pull/117967/) +- [Stabilize `#[expect]` for lints (RFC 2383),](https://github.com/rust-lang/rust/pull/120924/) like `#[allow]` with a warning if the lint is _not_ fulfilled. +- [Edition 2024: Make `!` fall back to `!` instead of `()`.](https://github.com/rust-lang/rust/pull/123508/) +- [Change method resolution to constrain hidden types instead of rejecting method candidates.](https://github.com/rust-lang/rust/pull/123962/) +- [Bump `elided_lifetimes_in_associated_constant` to deny.](https://github.com/rust-lang/rust/pull/124211/) +- [`offset_from`: always allow pointers to point to the same address.](https://github.com/rust-lang/rust/pull/124921/) +- [Allow constraining opaque types during subtyping in the trait system.](https://github.com/rust-lang/rust/pull/125447/) +- [Allow constraining opaque types during various unsizing casts.](https://github.com/rust-lang/rust/pull/125610/) +- [Deny keyword lifetimes pre-expansion.](https://github.com/rust-lang/rust/pull/126762/) + + + +Compiler +-------- + +- [Make casts of pointers to trait objects stricter.](https://github.com/rust-lang/rust/pull/120248/) +- [Check alias args for well-formedness even if they have escaping bound vars.](https://github.com/rust-lang/rust/pull/123737/) +- [Deprecate no-op codegen option `-Cinline-threshold=...`.](https://github.com/rust-lang/rust/pull/124712/) +- [Re-implement a type-size based limit.](https://github.com/rust-lang/rust/pull/125507/) +- [Properly account for alignment in `transmute` size checks.](https://github.com/rust-lang/rust/pull/125740/) +- [Remove the `box_pointers` lint.](https://github.com/rust-lang/rust/pull/126018/) +- [Ensure the interpreter checks bool/char for validity when they are used in a cast.](https://github.com/rust-lang/rust/pull/126265/) +- [Improve coverage instrumentation for functions containing nested items.](https://github.com/rust-lang/rust/pull/127199/) +- Target changes: + - [Add Tier 3 `no_std` Xtensa targets:](https://github.com/rust-lang/rust/pull/125141/) `xtensa-esp32-none-elf`, `xtensa-esp32s2-none-elf`, `xtensa-esp32s3-none-elf` + - [Add Tier 3 `std` Xtensa targets:](https://github.com/rust-lang/rust/pull/126380/) `xtensa-esp32-espidf`, `xtensa-esp32s2-espidf`, `xtensa-esp32s3-espidf` + - [Add Tier 3 i686 Redox OS target:](https://github.com/rust-lang/rust/pull/126192/) `i686-unknown-redox` + - [Promote `arm64ec-pc-windows-msvc` to Tier 2.](https://github.com/rust-lang/rust/pull/126039/) + - [Promote `wasm32-wasip2` to Tier 2.](https://github.com/rust-lang/rust/pull/126967/) + - [Promote `loongarch64-unknown-linux-musl` to Tier 2 with host tools.](https://github.com/rust-lang/rust/pull/126298/) + - [Enable full tools and profiler for LoongArch Linux targets.](https://github.com/rust-lang/rust/pull/127078/) + - [Unconditionally warn on usage of `wasm32-wasi`.](https://github.com/rust-lang/rust/pull/126662/) (see compatibility note below) + - Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. + + + +Libraries +--------- + +- [Split core's `PanicInfo` and std's `PanicInfo`.](https://github.com/rust-lang/rust/pull/115974/) (see compatibility note below) +- [Generalize `{Rc,Arc}::make_mut()` to unsized types.](https://github.com/rust-lang/rust/pull/116113/) +- [Replace sort implementations with stable `driftsort` and unstable `ipnsort`.](https://github.com/rust-lang/rust/pull/124032/) See the [research project](https://github.com/Voultapher/sort-research-rs) for more details. +- [Document behavior of `create_dir_all` with respect to empty paths.](https://github.com/rust-lang/rust/pull/125112/) +- [Fix interleaved output in the default panic hook when multiple threads panic simultaneously.](https://github.com/rust-lang/rust/pull/127397/) + + + +Stabilized APIs +--------------- + +- [`core::error`](https://doc.rust-lang.org/stable/core/error/index.html) +- [`hint::assert_unchecked`](https://doc.rust-lang.org/stable/core/hint/fn.assert_unchecked.html) +- [`fs::exists`](https://doc.rust-lang.org/stable/std/fs/fn.exists.html) +- [`AtomicBool::fetch_not`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicBool.html#method.fetch_not) +- [`Duration::abs_diff`](https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.abs_diff) +- [`IoSlice::advance`](https://doc.rust-lang.org/stable/std/io/struct.IoSlice.html#method.advance) +- [`IoSlice::advance_slices`](https://doc.rust-lang.org/stable/std/io/struct.IoSlice.html#method.advance_slices) +- [`IoSliceMut::advance`](https://doc.rust-lang.org/stable/std/io/struct.IoSliceMut.html#method.advance) +- [`IoSliceMut::advance_slices`](https://doc.rust-lang.org/stable/std/io/struct.IoSliceMut.html#method.advance_slices) +- [`PanicHookInfo`](https://doc.rust-lang.org/stable/std/panic/struct.PanicHookInfo.html) +- [`PanicInfo::message`](https://doc.rust-lang.org/stable/core/panic/struct.PanicInfo.html#method.message) +- [`PanicMessage`](https://doc.rust-lang.org/stable/core/panic/struct.PanicMessage.html) + +These APIs are now stable in const contexts: + +- [`char::from_u32_unchecked`](https://doc.rust-lang.org/stable/core/char/fn.from_u32_unchecked.html) (function) +- [`char::from_u32_unchecked`](https://doc.rust-lang.org/stable/core/primitive.char.html#method.from_u32_unchecked) (method) +- [`CStr::count_bytes`](https://doc.rust-lang.org/stable/core/ffi/c_str/struct.CStr.html#method.count_bytes) +- [`CStr::from_ptr`](https://doc.rust-lang.org/stable/core/ffi/c_str/struct.CStr.html#method.from_ptr) + + + +Cargo +----- + +- [Generated `.cargo_vcs_info.json` is always included, even when `--allow-dirty` is passed.](https://github.com/rust-lang/cargo/pull/13960/) +- [Disallow `package.license-file` and `package.readme` pointing to non-existent files during packaging.](https://github.com/rust-lang/cargo/pull/13921/) +- [Disallow passing `--release`/`--debug` flag along with the `--profile` flag.](https://github.com/rust-lang/cargo/pull/13971/) +- [Remove `lib.plugin` key support in `Cargo.toml`. Rust plugin support has been deprecated for four years and was removed in 1.75.0.](https://github.com/rust-lang/cargo/pull/13902/) + + + +Rustdoc +---- + +- [Add support for `--remap-path-prefix`.](https://github.com/rust-lang/rust/pull/107099/) + + + +Compatibility Notes +------------------- + +* Usage of the `wasm32-wasi` target will now issue a compiler warning and request users switch to the `wasm32-wasip1` target instead. Both targets are the same, `wasm32-wasi` is only being renamed, and this [change to the WASI target](https://blog.rust-lang.org/2024/04/09/updates-to-rusts-wasi-targets.html) is being done to enable removing `wasm32-wasi` in January 2025. + +* We have renamed `std::panic::PanicInfo` to `std::panic::PanicHookInfo`. The old name will continue to work as an alias, but will result in a deprecation warning starting in Rust 1.82.0. + + `core::panic::PanicInfo` will remain unchanged, however, as this is now a *different type*. + + The reason is that these types have different roles: `std::panic::PanicHookInfo` is the argument to the [panic hook](https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html) in std context (where panics can have an arbitrary payload), while `core::panic::PanicInfo` is the argument to the [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) in no_std context (where panics always carry a formatted *message*). Separating these types allows us to add more useful methods to these types, such as `std::panic::PanicHookInfo::payload_as_str()` and `core::panic::PanicInfo::message()`. + + + +Internal Changes +---------------- + +These changes do not affect any public interfaces of Rust, but they represent +significant improvements to the performance or internals of rustc and related +tools. + +- [Add a Rust-for Linux `auto` CI job to check kernel builds.](https://github.com/rust-lang/rust/pull/125209/) + Version 1.80.0 (2024-07-25) ========================== From dd9fcffb20982b053d8b628663d7ceb690878eed Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 20 Aug 2024 09:42:17 -0700 Subject: [PATCH 16/23] Drop the edition relnote about `!` fallback --- RELEASES.md | 1 - 1 file changed, 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 79771ef1d8cc8..fb1af44e52ca1 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -9,7 +9,6 @@ Language - [Abort on uncaught panics in `extern "C"` functions.](https://github.com/rust-lang/rust/pull/116088/) - [Fix ambiguous cases of multiple `&` in elided self lifetimes.](https://github.com/rust-lang/rust/pull/117967/) - [Stabilize `#[expect]` for lints (RFC 2383),](https://github.com/rust-lang/rust/pull/120924/) like `#[allow]` with a warning if the lint is _not_ fulfilled. -- [Edition 2024: Make `!` fall back to `!` instead of `()`.](https://github.com/rust-lang/rust/pull/123508/) - [Change method resolution to constrain hidden types instead of rejecting method candidates.](https://github.com/rust-lang/rust/pull/123962/) - [Bump `elided_lifetimes_in_associated_constant` to deny.](https://github.com/rust-lang/rust/pull/124211/) - [`offset_from`: always allow pointers to point to the same address.](https://github.com/rust-lang/rust/pull/124921/) From 27873f8052625069c20263862eb7aa92293c3eea Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 30 Aug 2024 17:54:36 -0700 Subject: [PATCH 17/23] Mention sort perf, and add its panics in compat notes --- RELEASES.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index fb1af44e52ca1..c98af314ccdcf 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -47,7 +47,7 @@ Libraries - [Split core's `PanicInfo` and std's `PanicInfo`.](https://github.com/rust-lang/rust/pull/115974/) (see compatibility note below) - [Generalize `{Rc,Arc}::make_mut()` to unsized types.](https://github.com/rust-lang/rust/pull/116113/) -- [Replace sort implementations with stable `driftsort` and unstable `ipnsort`.](https://github.com/rust-lang/rust/pull/124032/) See the [research project](https://github.com/Voultapher/sort-research-rs) for more details. +- [Replace sort implementations with stable `driftsort` and unstable `ipnsort`.](https://github.com/rust-lang/rust/pull/124032/) All `slice::sort*` and `slice::select_nth*` methods are expected to see significant performance improvements. See the [research project](https://github.com/Voultapher/sort-research-rs) for more details. - [Document behavior of `create_dir_all` with respect to empty paths.](https://github.com/rust-lang/rust/pull/125112/) - [Fix interleaved output in the default panic hook when multiple threads panic simultaneously.](https://github.com/rust-lang/rust/pull/127397/) @@ -106,6 +106,8 @@ Compatibility Notes The reason is that these types have different roles: `std::panic::PanicHookInfo` is the argument to the [panic hook](https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html) in std context (where panics can have an arbitrary payload), while `core::panic::PanicInfo` is the argument to the [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) in no_std context (where panics always carry a formatted *message*). Separating these types allows us to add more useful methods to these types, such as `std::panic::PanicHookInfo::payload_as_str()` and `core::panic::PanicInfo::message()`. +* The new sort implementations may panic if a type's implementation of [`Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) (or the given comparison function) does not implement a [total order](https://en.wikipedia.org/wiki/Total_order) as the trait requires. `Ord`'s supertraits (`PartialOrd`, `Eq`, and `PartialEq`) must also be consistent. The previous implementations would not "notice" any problem, but the new implementations have a good chance of detecting inconsistencies, throwing a panic rather than returning knowingly unsorted data. + Internal Changes From 99e14e3c809e933f68ad5b1363dc46e78a1d6570 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 30 Aug 2024 17:56:17 -0700 Subject: [PATCH 18/23] Remove the relnote for rustdoc's *unstable* `--remap-path-prefix` --- RELEASES.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index c98af314ccdcf..6aba476103e7f 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -86,13 +86,6 @@ Cargo - [Disallow passing `--release`/`--debug` flag along with the `--profile` flag.](https://github.com/rust-lang/cargo/pull/13971/) - [Remove `lib.plugin` key support in `Cargo.toml`. Rust plugin support has been deprecated for four years and was removed in 1.75.0.](https://github.com/rust-lang/cargo/pull/13902/) - - -Rustdoc ----- - -- [Add support for `--remap-path-prefix`.](https://github.com/rust-lang/rust/pull/107099/) - Compatibility Notes From bce176d9a7b1f7e1fbc485ab0d0a9c8af03ae32a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 31 Aug 2024 12:59:19 +0200 Subject: [PATCH 19/23] tidy: say which feature gate has a stability issue mismatch --- src/tools/tidy/src/features.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index a4d27d29d3269..4f24eb2124207 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -455,9 +455,10 @@ fn get_and_check_lib_features( if f.tracking_issue != s.tracking_issue && f.level != Status::Accepted { tidy_error!( bad, - "{}:{}: `issue` \"{}\" mismatches the {} `issue` of \"{}\"", + "{}:{}: feature gate {} has inconsistent `issue`: \"{}\" mismatches the {} `issue` of \"{}\"", file.display(), line, + name, f.tracking_issue_display(), display, s.tracking_issue_display(), From e3b1966137264ab6be7e42ce55b6bb6f5cea6413 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 31 Aug 2024 15:06:21 +0200 Subject: [PATCH 20/23] make the const-unstable-in-stable error more clear --- compiler/rustc_const_eval/messages.ftl | 4 ++-- .../consts/min_const_fn/min_const_fn_libstd_stability.stderr | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index db788b6b15199..8a6dfb892490a 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -415,8 +415,8 @@ const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn const_eval_unstable_in_stable = const-stable function cannot use `#[feature({$gate})]` - .unstable_sugg = if it is not part of the public API, make this function unstably const - .bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval) + .unstable_sugg = if the function is not (yet) meant to be stable, make this function unstably const + .bypass_sugg = otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval) const_eval_unterminated_c_string = reading a null-terminated string starting at {$pointer} with no null found before end of allocation diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr index 019deda063c78..cb447719f9c58 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr @@ -20,12 +20,12 @@ error: const-stable function cannot use `#[feature(const_refs_to_cell)]` LL | x.get(); | ^ | -help: if it is not part of the public API, make this function unstably const +help: if the function is not (yet) meant to be stable, make this function unstably const | LL + #[rustc_const_unstable(feature = "...", issue = "...")] LL | const fn bar3() -> u32 { | -help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval) +help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval) | LL + #[rustc_allow_const_fn_unstable(const_refs_to_cell)] LL | const fn bar3() -> u32 { From 3cec2d693520b8a409a8ba6d2b6d1a40e14ade62 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 31 Aug 2024 15:06:39 +0200 Subject: [PATCH 21/23] don't take reachability into account when warning about missing-const-stability --- compiler/rustc_passes/src/stability.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 4d58590ca3b0e..ba4c300ea61af 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -544,9 +544,8 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { let is_stable = self.tcx.lookup_stability(def_id).is_some_and(|stability| stability.level.is_stable()); let missing_const_stability_attribute = self.tcx.lookup_const_stability(def_id).is_none(); - let is_reachable = self.effective_visibilities.is_reachable(def_id); - if is_const && is_stable && missing_const_stability_attribute && is_reachable { + if is_const && is_stable && missing_const_stability_attribute { let descr = self.tcx.def_descr(def_id.to_def_id()); self.tcx.dcx().emit_err(errors::MissingConstStabAttr { span, descr }); } From 670a78b3a78ef341da7cdcafde58923a66b82ff9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 31 Aug 2024 17:26:54 +0200 Subject: [PATCH 22/23] Fix code examples buttons not appearing on click on mobile --- src/librustdoc/html/static/js/main.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 75f2a1418cd8f..c3e219f2c87b3 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1878,9 +1878,15 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm if (elem === null) { return; } - const buttons = elem.querySelector(".button-holder"); + let buttons = elem.querySelector(".button-holder"); if (buttons === null) { - return; + // On mobile, you can't hover an element so buttons need to be created on click + // if they're not already there. + addCopyButton(event); + buttons = elem.querySelector(".button-holder"); + if (buttons === null) { + return; + } } buttons.classList.toggle("keep-visible"); } From 7d728e54d97c6062c3ad2ccbc6ac48faa99bce31 Mon Sep 17 00:00:00 2001 From: Alcaro Date: Sat, 31 Aug 2024 19:09:41 +0200 Subject: [PATCH 23/23] Update mod.rs This typo looks unnecessary --- library/core/src/mem/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index e602b497d171a..fed484ae3cd12 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -612,7 +612,7 @@ pub const fn needs_drop() -> bool { /// /// There is no guarantee that an all-zero byte-pattern represents a valid value /// of some type `T`. For example, the all-zero byte-pattern is not a valid value -/// for reference types (`&T`, `&mut T`) and functions pointers. Using `zeroed` +/// for reference types (`&T`, `&mut T`) and function pointers. Using `zeroed` /// on such types causes immediate [undefined behavior][ub] because [the Rust /// compiler assumes][inv] that there always is a valid value in a variable it /// considers initialized.