From 8976a6ee07fd983cda1463fd299a4e2adc16ec4d Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 30 May 2025 09:50:06 +0800 Subject: [PATCH 1/7] bootstrap: remap compiler vs non-compiler sources differently - Map compiler sources (corresponding to `rustc-dev` dist component) with `/rustc-dev/{hash}`. - Map non-compiler sources (corresponding to `rust-src` dist component or other non-compiler sources) with `/rustc/{hash}`. This allows the compiler to have the possibility of opportunistically reverse the mapping. This is because - `rust-src` unpacks sources to a path like `$sysroot/lib/rustlib/src/rust`, whereas - `rustc-dev` unpacks sources to a path like `$sysroot/lib/rustlib/rustc-src/rust` (Notice the `src` vs `rustc-src` difference.) --- src/bootstrap/src/core/builder/cargo.rs | 47 +++++++++++++++++++++---- src/bootstrap/src/lib.rs | 33 +++++++++++++++-- 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index e41f6f16b0232..27b3a5b97c3d8 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -11,7 +11,7 @@ use crate::utils::build_stamp; use crate::utils::helpers::{self, LldThreads, check_cfg_arg, linker_args, linker_flags}; use crate::{ BootstrapCommand, CLang, Compiler, Config, DocTests, DryRun, EXTRA_CHECK_CFGS, GitRepo, Mode, - TargetSelection, command, prepare_behaviour_dump_dir, t, + RemapScheme, TargetSelection, command, prepare_behaviour_dump_dir, t, }; /// Represents flag values in `String` form with whitespace delimiter to pass it to the compiler @@ -920,13 +920,46 @@ impl Builder<'_> { hostflags.arg(format!("-Ctarget-feature={sign}crt-static")); } - if let Some(map_to) = self.build.debuginfo_map_to(GitRepo::Rustc) { - let map = format!("{}={}", self.build.src.display(), map_to); - cargo.env("RUSTC_DEBUGINFO_MAP", map); + // `rustc` needs to know the remapping scheme, in order to know how to reverse it (unremap) + // later. Two env vars are set and made available to the compiler + // + // - `CFG_VIRTUAL_RUST_SOURCE_BASE_DIR`: `rust-src` remap scheme (`NonCompiler`) + // - `CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR`: `rustc-dev` remap scheme (`Compiler`) + // + // Keep this scheme in sync with `rustc_metadata::rmeta::decoder`'s + // `try_to_translate_virtual_to_real`. + // + // `RUSTC_DEBUGINFO_MAP` is used to pass through to the underlying rustc + // `--remap-path-prefix`. + match mode { + Mode::Rustc | Mode::Codegen => { + if let Some(ref map_to) = + self.build.debuginfo_map_to(GitRepo::Rustc, RemapScheme::NonCompiler) + { + cargo.env("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR", map_to); + } - // `rustc` needs to know the virtual `/rustc/$hash` we're mapping to, - // in order to opportunistically reverse it later. - cargo.env("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR", map_to); + if let Some(ref map_to) = + self.build.debuginfo_map_to(GitRepo::Rustc, RemapScheme::Compiler) + { + // When building compiler sources, we want to apply the compiler remap scheme. + cargo.env( + "RUSTC_DEBUGINFO_MAP", + format!("{}={}", self.build.src.display(), map_to), + ); + cargo.env("CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR", map_to); + } + } + Mode::Std | Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd => { + if let Some(ref map_to) = + self.build.debuginfo_map_to(GitRepo::Rustc, RemapScheme::NonCompiler) + { + cargo.env( + "RUSTC_DEBUGINFO_MAP", + format!("{}={}", self.build.src.display(), map_to), + ); + } + } } if self.config.rust_remap_debuginfo { diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 7cce14841eb34..2fbe72fa86205 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -272,6 +272,16 @@ impl Mode { } } +/// When `rust.rust_remap_debuginfo` is requested, the compiler needs to know how to +/// opportunistically unremap compiler vs non-compiler sources. We use two schemes, +/// [`RemapScheme::Compiler`] and [`RemapScheme::NonCompiler`]. +pub enum RemapScheme { + /// The [`RemapScheme::Compiler`] scheme will remap to `/rustc-dev/{hash}`. + Compiler, + /// The [`RemapScheme::NonCompiler`] scheme will remap to `/rustc/{hash}`. + NonCompiler, +} + #[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum CLang { C, @@ -1210,7 +1220,7 @@ Executed at: {executed_at}"#, }) } - fn debuginfo_map_to(&self, which: GitRepo) -> Option { + fn debuginfo_map_to(&self, which: GitRepo, remap_scheme: RemapScheme) -> Option { if !self.config.rust_remap_debuginfo { return None; } @@ -1218,7 +1228,24 @@ Executed at: {executed_at}"#, match which { GitRepo::Rustc => { let sha = self.rust_sha().unwrap_or(&self.version); - Some(format!("/rustc/{sha}")) + + match remap_scheme { + RemapScheme::Compiler => { + // For compiler sources, remap via `/rustc-dev/{sha}` to allow + // distinguishing between compiler sources vs library sources, since + // `rustc-dev` dist component places them under + // `$sysroot/lib/rustlib/rustc-src/rust` as opposed to `rust-src`'s + // `$sysroot/lib/rustlib/src/rust`. + // + // Keep this scheme in sync with `rustc_metadata::rmeta::decoder`'s + // `try_to_translate_virtual_to_real`. + Some(format!("/rustc-dev/{sha}")) + } + RemapScheme::NonCompiler => { + // For non-compiler sources, use `/rustc/{sha}` remapping scheme. + Some(format!("/rustc/{sha}")) + } + } } GitRepo::Llvm => Some(String::from("/rustc/llvm")), } @@ -1285,7 +1312,7 @@ Executed at: {executed_at}"#, base.push("-fno-omit-frame-pointer".into()); } - if let Some(map_to) = self.debuginfo_map_to(which) { + if let Some(map_to) = self.debuginfo_map_to(which, RemapScheme::NonCompiler) { let map = format!("{}={}", self.src.display(), map_to); let cc = self.cc(target); if cc.ends_with("clang") || cc.ends_with("gcc") { From b283394db14a47d44a4b5ace33705cfa3873b0b5 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sat, 7 Jun 2025 14:45:10 +0200 Subject: [PATCH 2/7] Only allow `bootstrap` cfg in rustc, related and tool-std --- src/bootstrap/src/core/builder/cargo.rs | 16 +++++++++------- src/bootstrap/src/lib.rs | 5 ++++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 1e9af68a92df6..a21bee7c6110e 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -636,6 +636,15 @@ impl Builder<'_> { for (restricted_mode, name, values) in EXTRA_CHECK_CFGS { if restricted_mode.is_none() || *restricted_mode == Some(mode) { rustflags.arg(&check_cfg_arg(name, *values)); + + if *name == "bootstrap" { + // Cargo doesn't pass RUSTFLAGS to proc_macros: + // https://github.com/rust-lang/cargo/issues/4423 + // Thus, if we are on stage 0, we explicitly set `--cfg=bootstrap`. + // We also declare that the flag is expected, which we need to do to not + // get warnings about it being unexpected. + hostflags.arg(check_cfg_arg(name, *values)); + } } } @@ -645,13 +654,6 @@ impl Builder<'_> { if stage == 0 { hostflags.arg("--cfg=bootstrap"); } - // Cargo doesn't pass RUSTFLAGS to proc_macros: - // https://github.com/rust-lang/cargo/issues/4423 - // Thus, if we are on stage 0, we explicitly set `--cfg=bootstrap`. - // We also declare that the flag is expected, which we need to do to not - // get warnings about it being unexpected. - hostflags.arg("-Zunstable-options"); - hostflags.arg("--check-cfg=cfg(bootstrap)"); // FIXME: It might be better to use the same value for both `RUSTFLAGS` and `RUSTDOCFLAGS`, // but this breaks CI. At the very least, stage0 `rustdoc` needs `--cfg bootstrap`. See diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 07772b8932d9d..8e657b99f17e9 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -81,7 +81,10 @@ const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"]; /// (Mode restriction, config name, config values (if any)) #[expect(clippy::type_complexity)] // It's fine for hard-coded list and type is explained above. const EXTRA_CHECK_CFGS: &[(Option, &str, Option<&[&'static str]>)] = &[ - (None, "bootstrap", None), + (Some(Mode::Rustc), "bootstrap", None), + (Some(Mode::Codegen), "bootstrap", None), + (Some(Mode::ToolRustc), "bootstrap", None), + (Some(Mode::ToolStd), "bootstrap", None), (Some(Mode::Rustc), "llvm_enzyme", None), (Some(Mode::Codegen), "llvm_enzyme", None), (Some(Mode::ToolRustc), "llvm_enzyme", None), From 9b1cd722ca7490ae28db77b44eefb4700ef6bb19 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sat, 7 Jun 2025 14:45:25 +0200 Subject: [PATCH 3/7] Fix usage of `bootstrap` in core --- library/core/src/iter/sources/generator.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/library/core/src/iter/sources/generator.rs b/library/core/src/iter/sources/generator.rs index c94232e09eb86..0846974d526a9 100644 --- a/library/core/src/iter/sources/generator.rs +++ b/library/core/src/iter/sources/generator.rs @@ -9,8 +9,6 @@ /// /// ``` /// #![feature(iter_macro, coroutines)] -/// # #[cfg(not(bootstrap))] -/// # { /// /// let it = std::iter::iter!{|| { /// yield 1; @@ -19,11 +17,10 @@ /// } }(); /// let v: Vec<_> = it.collect(); /// assert_eq!(v, [1, 2, 3]); -/// # } /// ``` #[unstable(feature = "iter_macro", issue = "none", reason = "generators are unstable")] #[allow_internal_unstable(coroutines, iter_from_coroutine)] -#[cfg_attr(not(bootstrap), rustc_builtin_macro)] +#[rustc_builtin_macro] pub macro iter($($t:tt)*) { /* compiler-builtin */ } From 7c1c56646b62762b3b88b2b34930b11d1921443a Mon Sep 17 00:00:00 2001 From: bohan Date: Sun, 8 Jun 2025 20:28:35 +0800 Subject: [PATCH 4/7] early return in trait detection for non-trait item --- .../rustc_hir_typeck/src/method/suggest.rs | 20 +++++++++++-------- tests/crashes/135863.rs | 10 ---------- .../double-reference-ty-in-self-ty.rs | 12 +++++++++++ .../double-reference-ty-in-self-ty.stderr | 19 ++++++++++++++++++ 4 files changed, 43 insertions(+), 18 deletions(-) delete mode 100644 tests/crashes/135863.rs create mode 100644 tests/ui/suggestions/double-reference-ty-in-self-ty.rs create mode 100644 tests/ui/suggestions/double-reference-ty-in-self-ty.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 3eae95d5b738d..2fac13b72019c 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3494,7 +3494,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; } trait_in_other_version_found = self - .detect_and_explain_multiple_crate_versions( + .detect_and_explain_multiple_crate_versions_of_trait_item( err, pick.item.def_id, rcvr.hir_id, @@ -3701,12 +3701,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // same crate. let rcvr_ty = self.node_ty_opt(ty.hir_id); - trait_in_other_version_found = self.detect_and_explain_multiple_crate_versions( - err, - assoc.def_id, - ty.hir_id, - rcvr_ty, - ); + trait_in_other_version_found = self + .detect_and_explain_multiple_crate_versions_of_trait_item( + err, + assoc.def_id, + ty.hir_id, + rcvr_ty, + ); } if !trait_in_other_version_found && self.suggest_valid_traits(err, item_name, valid_out_of_scope_traits, true) @@ -4098,7 +4099,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn detect_and_explain_multiple_crate_versions( + fn detect_and_explain_multiple_crate_versions_of_trait_item( &self, err: &mut Diag<'_>, item_def_id: DefId, @@ -4111,6 +4112,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } let trait_def_id = self.tcx.parent(item_def_id); + if !self.tcx.is_trait(trait_def_id) { + return false; + } let krate = self.tcx.crate_name(trait_def_id.krate); let name = self.tcx.item_name(trait_def_id); let candidates: Vec<_> = traits diff --git a/tests/crashes/135863.rs b/tests/crashes/135863.rs deleted file mode 100644 index a0ff5988a0db2..0000000000000 --- a/tests/crashes/135863.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #135863 -struct A; - -impl A { - fn len(self: &&B) {} -} - -fn main() { - A.len() -} diff --git a/tests/ui/suggestions/double-reference-ty-in-self-ty.rs b/tests/ui/suggestions/double-reference-ty-in-self-ty.rs new file mode 100644 index 0000000000000..4ac13f0f635d9 --- /dev/null +++ b/tests/ui/suggestions/double-reference-ty-in-self-ty.rs @@ -0,0 +1,12 @@ +// issue#135863 + +struct A; + +impl A { + fn len(self: &&A) {} +} + +fn main() { + A.len(); + //~^ ERROR: no method named `len` found for struct `A` in the current scope +} diff --git a/tests/ui/suggestions/double-reference-ty-in-self-ty.stderr b/tests/ui/suggestions/double-reference-ty-in-self-ty.stderr new file mode 100644 index 0000000000000..a718234241093 --- /dev/null +++ b/tests/ui/suggestions/double-reference-ty-in-self-ty.stderr @@ -0,0 +1,19 @@ +error[E0599]: no method named `len` found for struct `A` in the current scope + --> $DIR/double-reference-ty-in-self-ty.rs:10:7 + | +LL | struct A; + | -------- method `len` not found for this struct +... +LL | fn len(self: &&A) {} + | --- the method is available for `&A` here +... +LL | A.len(); + | ^^^ method not found in `A` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `len`, perhaps you need to implement it: + candidate #1: `ExactSizeIterator` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. From f4ba1746cc1b13eb73f3739a5ff5e64cde56f078 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Sun, 8 Jun 2025 21:37:25 +0200 Subject: [PATCH 5/7] CI: rfl: move job forward to Linux v6.16-rc1 Remove the comment on top as well, since that issue is now fixed in this new tag. Signed-off-by: Miguel Ojeda --- src/ci/docker/scripts/rfl-build.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index fa18f67583ff6..c59928913989c 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -2,8 +2,7 @@ set -euo pipefail -# https://github.com/Rust-for-Linux/linux/issues/1163 -LINUX_VERSION=3ca02fc80cc4fdac63aaa6796642f1e07be591d6 +LINUX_VERSION=v6.16-rc1 # Build rustc, rustdoc, cargo, clippy-driver and rustfmt ../x.py build --stage 2 library rustdoc clippy rustfmt From 889f7cbffa5b7e89fe006c1d35dad42ef6ecc525 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 8 Jun 2025 20:11:19 -0700 Subject: [PATCH 6/7] Avoid a gratuitous 10s wait in a stress test `stress_recv_timeout_two_threads`, in the mpmc and mpsc testsuites, is a stress test of the `recv_timeout` function. This test processes and ignores timeouts, and just ensures that every sent value gets received. As such, the exact length of the timeouts is not critical, only that the timeout and sleep durations ensure that at least one timeout occurred. The current tests have 100 iterations, half of which sleep for 200ms, causing the test to take 10s. This represents around 2/3rds of the *total* runtime of the `library/std` testsuite. Reduce this to 50 iterations where half of them sleep for 10ms, causing the test to take 0.25s. Add a check that at least one timeout occurred. --- library/std/tests/sync/mpmc.rs | 11 ++++++++--- library/std/tests/sync/mpsc.rs | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/library/std/tests/sync/mpmc.rs b/library/std/tests/sync/mpmc.rs index 78abcb3bcbe1d..594fc2180d83f 100644 --- a/library/std/tests/sync/mpmc.rs +++ b/library/std/tests/sync/mpmc.rs @@ -462,8 +462,8 @@ fn oneshot_single_thread_recv_timeout() { #[test] fn stress_recv_timeout_two_threads() { let (tx, rx) = channel(); - let stress = stress_factor() + 100; - let timeout = Duration::from_millis(100); + let stress = stress_factor() + 50; + let timeout = Duration::from_millis(5); thread::spawn(move || { for i in 0..stress { @@ -475,18 +475,23 @@ fn stress_recv_timeout_two_threads() { }); let mut recv_count = 0; + let mut got_timeout = false; loop { match rx.recv_timeout(timeout) { Ok(n) => { assert_eq!(n, 1usize); recv_count += 1; } - Err(RecvTimeoutError::Timeout) => continue, + Err(RecvTimeoutError::Timeout) => { + got_timeout = true; + continue; + } Err(RecvTimeoutError::Disconnected) => break, } } assert_eq!(recv_count, stress); + assert!(got_timeout); } #[test] diff --git a/library/std/tests/sync/mpsc.rs b/library/std/tests/sync/mpsc.rs index 1d8edfde44bed..9de4a71987b8e 100644 --- a/library/std/tests/sync/mpsc.rs +++ b/library/std/tests/sync/mpsc.rs @@ -425,8 +425,8 @@ fn oneshot_single_thread_recv_timeout() { #[test] fn stress_recv_timeout_two_threads() { let (tx, rx) = channel(); - let stress = stress_factor() + 100; - let timeout = Duration::from_millis(100); + let stress = stress_factor() + 50; + let timeout = Duration::from_millis(5); thread::spawn(move || { for i in 0..stress { @@ -438,18 +438,23 @@ fn stress_recv_timeout_two_threads() { }); let mut recv_count = 0; + let mut got_timeout = false; loop { match rx.recv_timeout(timeout) { Ok(n) => { assert_eq!(n, 1usize); recv_count += 1; } - Err(RecvTimeoutError::Timeout) => continue, + Err(RecvTimeoutError::Timeout) => { + got_timeout = true; + continue; + } Err(RecvTimeoutError::Disconnected) => break, } } assert_eq!(recv_count, stress); + assert!(got_timeout); } #[test] From cb9980133cbb670387a597c349397cd38f52edee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 8 Jun 2025 21:19:24 +0200 Subject: [PATCH 7/7] Do not checkout GCC submodule for the tidy job --- src/ci/github-actions/jobs.yml | 4 ++++ src/ci/scripts/checkout-submodules.sh | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 3f8ea696ee2ed..43c77d1ddf7f5 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -129,6 +129,10 @@ pr: - name: mingw-check-tidy continue_on_error: true free_disk: false + env: + # This submodule is expensive to checkout, and it should not be needed for + # tidy. This speeds up the PR CI job by ~1 minute. + SKIP_SUBMODULES: src/gcc <<: *job-linux-4c - name: x86_64-gnu-llvm-19 env: diff --git a/src/ci/scripts/checkout-submodules.sh b/src/ci/scripts/checkout-submodules.sh index 5bb343241aea6..3b646587dc28d 100755 --- a/src/ci/scripts/checkout-submodules.sh +++ b/src/ci/scripts/checkout-submodules.sh @@ -55,7 +55,11 @@ for i in ${!modules[@]}; do bg_pids[${i}]=$! continue else + # Submodule paths contained in SKIP_SUBMODULES (comma-separated list) will not be + # checked out. + if [ -z "${SKIP_SUBMODULES:-}" ] || [[ ! ",$SKIP_SUBMODULES," = *",$module,"* ]]; then use_git="$use_git $module" + fi fi done retry sh -c "git submodule deinit -f $use_git && \