From d7923d4b3828b1ce4330266172dc6a9515b163a3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 10 Mar 2026 22:55:52 +0100 Subject: [PATCH 01/15] simd_add/sub/mul/neg: document overflow behavior --- library/core/src/intrinsics/simd.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 5fb2102c319e2..50d8871973792 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -62,6 +62,7 @@ pub const unsafe fn simd_splat(value: U) -> T; /// Adds two simd vectors elementwise. /// /// `T` must be a vector of integers or floats. +/// For integers, wrapping arithmetic is used. #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn simd_add(x: T, y: T) -> T; @@ -69,6 +70,7 @@ pub const unsafe fn simd_add(x: T, y: T) -> T; /// Subtracts `rhs` from `lhs` elementwise. /// /// `T` must be a vector of integers or floats. +/// For integers, wrapping arithmetic is used. #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn simd_sub(lhs: T, rhs: T) -> T; @@ -76,6 +78,7 @@ pub const unsafe fn simd_sub(lhs: T, rhs: T) -> T; /// Multiplies two simd vectors elementwise. /// /// `T` must be a vector of integers or floats. +/// For integers, wrapping arithmetic is used. #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn simd_mul(x: T, y: T) -> T; @@ -233,8 +236,7 @@ pub const unsafe fn simd_as(x: T) -> U; /// Negates a vector elementwise. /// /// `T` must be a vector of integers or floats. -/// -/// Rust panics for `-::Min` due to overflow, but it is not UB with this intrinsic. +/// For integers, wrapping arithmetic is used. #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn simd_neg(x: T) -> T; From 84a2d2a92c1f3c9f79cf632eaf2d6498e031dec5 Mon Sep 17 00:00:00 2001 From: Paul Murphy Date: Tue, 10 Feb 2026 15:27:00 -0600 Subject: [PATCH 02/15] Pass -pg to linker when using -Zinstrument-mcount Clang and gcc use this option to control linking behavior too. Some targets need to be linked against a special crt which enables profiling at runtime. This makes using gprof a little easier with Rust binaries. Otherwise, rustc must be passed `-Clink-args=-pg` to ensure the correct startup code is linked. --- compiler/rustc_codegen_ssa/src/back/link.rs | 4 ++++ compiler/rustc_codegen_ssa/src/back/linker.rs | 7 +++++++ .../instrument-mcount-link-pg/main.rs | 3 +++ .../instrument-mcount-link-pg/rmake.rs | 19 +++++++++++++++++++ 4 files changed, 33 insertions(+) create mode 100644 tests/run-make/instrument-mcount-link-pg/main.rs create mode 100644 tests/run-make/instrument-mcount-link-pg/rmake.rs diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 56dca6c8b9021..29ae1548b7439 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2767,6 +2767,10 @@ fn add_order_independent_options( cmd.pgo_gen(); } + if sess.opts.unstable_opts.instrument_mcount { + cmd.enable_profiling(); + } + if sess.opts.cg.control_flow_guard != CFGuard::Disabled { cmd.control_flow_guard(); } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 3ace1a8c266cf..55ee9b1b974a0 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -352,6 +352,7 @@ pub(crate) trait Linker { fn add_no_exec(&mut self) {} fn add_as_needed(&mut self) {} fn reset_per_library_state(&mut self) {} + fn enable_profiling(&mut self) {} } impl dyn Linker + '_ { @@ -732,6 +733,12 @@ impl<'a> Linker for GccLinker<'a> { self.link_or_cc_args(&["-u", "__llvm_profile_runtime"]); } + fn enable_profiling(&mut self) { + // This flag is also used when linking to choose target specific + // libraries needed to enable profiling. + self.cc_arg("-pg"); + } + fn control_flow_guard(&mut self) {} fn ehcont_guard(&mut self) {} diff --git a/tests/run-make/instrument-mcount-link-pg/main.rs b/tests/run-make/instrument-mcount-link-pg/main.rs new file mode 100644 index 0000000000000..47ad8c634112b --- /dev/null +++ b/tests/run-make/instrument-mcount-link-pg/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello World!"); +} diff --git a/tests/run-make/instrument-mcount-link-pg/rmake.rs b/tests/run-make/instrument-mcount-link-pg/rmake.rs new file mode 100644 index 0000000000000..184bd9429bfd8 --- /dev/null +++ b/tests/run-make/instrument-mcount-link-pg/rmake.rs @@ -0,0 +1,19 @@ +// When building a binary instrumented with mcount, verify the +// binary is linked with the correct crt to enable profiling. +// +//@ only-gnu +//@ ignore-cross-compile + +use run_make_support::{path, run, rustc}; + +fn main() { + // Compile instrumentation enabled binary, and verify -pg is passed + let link_args = + rustc().input("main.rs").arg("-Zinstrument-mcount").print("link-args").run().stdout_utf8(); + assert!(link_args.contains("\"-pg\"")); + + // Run it, and verify gmon.out is created + assert!(!path("gmon.out").exists()); + run("main"); + assert!(path("gmon.out").exists()); +} From cc2c5f9b8d19bae79ed8f1671c9ea4feea9f76a2 Mon Sep 17 00:00:00 2001 From: Paul Murphy Date: Thu, 12 Mar 2026 09:14:06 -0500 Subject: [PATCH 03/15] Fix mcount name for *-windows-gnu targets mingw exposes the `_mcount` symbol for profiling. --- compiler/rustc_target/src/spec/base/windows_gnu.rs | 1 + compiler/rustc_target/src/spec/base/windows_gnullvm.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler/rustc_target/src/spec/base/windows_gnu.rs b/compiler/rustc_target/src/spec/base/windows_gnu.rs index d2fe42b903062..cee3f91226998 100644 --- a/compiler/rustc_target/src/spec/base/windows_gnu.rs +++ b/compiler/rustc_target/src/spec/base/windows_gnu.rs @@ -106,6 +106,7 @@ pub(crate) fn opts() -> TargetOptions { // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to // output DWO, despite using DWARF, doesn't use ELF.. supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), + mcount: "_mcount".into(), ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs index 3bd8ebd0ed3d5..8e26852d03711 100644 --- a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs @@ -53,6 +53,7 @@ pub(crate) fn opts() -> TargetOptions { // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to // output DWO, despite using DWARF, doesn't use ELF.. supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), + mcount: "_mcount".into(), ..Default::default() } } From 87c25522c6cace676266e64cbbe7774d5eae89fe Mon Sep 17 00:00:00 2001 From: Paul Murphy Date: Thu, 12 Mar 2026 11:54:56 -0500 Subject: [PATCH 04/15] Link extra libraries when using mcount on *-windows-gnu targets libgmon needs to be linked. This also requires readding a few other system libraries to satisfy its dependencies. --- compiler/rustc_codegen_ssa/src/back/linker.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 55ee9b1b974a0..89cd1528ced9f 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -737,6 +737,13 @@ impl<'a> Linker for GccLinker<'a> { // This flag is also used when linking to choose target specific // libraries needed to enable profiling. self.cc_arg("-pg"); + // On windows-gnu targets, libgmon also needs to be linked, and this + // requires readding libraries to satisfy its dependencies. + if self.sess.target.is_like_windows { + self.cc_arg("-lgmon"); + self.cc_arg("-lkernel32"); + self.cc_arg("-lmsvcrt"); + } } fn control_flow_guard(&mut self) {} From 384f363b7023244df33bef7eb8070a334eae9b48 Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Fri, 13 Mar 2026 14:32:54 -0400 Subject: [PATCH 05/15] change "error finalizing incremental compilation" from warning to note The warning has no error code, so in a `-D warnings` environment, it's impossible to ignore if it consistently breaks your build. Change it to a note so it is still visible, but doesn't break the build --- compiler/rustc_incremental/src/persist/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index f73cc4d43e8c5..cf80a7ac2c469 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -366,7 +366,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Option) { } Err(e) => { // Warn about the error. However, no need to abort compilation now. - sess.dcx().emit_warn(errors::Finalize { path: &incr_comp_session_dir, err: e }); + sess.dcx().emit_note(errors::Finalize { path: &incr_comp_session_dir, err: e }); debug!("finalize_session_directory() - error, marking as invalid"); // Drop the file lock, so we can garage collect From 4845f7842228c03910b3bf5d1a4221eea4e14f5d Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Tue, 17 Mar 2026 15:59:08 -0400 Subject: [PATCH 06/15] Reword the incremental finalize diagnostic Remove the confusing word "error". The diagnostic is already prefixed with a level when it is displayed, so this is redundant and possibly confusing ("warning: error ..."). Add some help text summarizing the impact of what happened: the next build won't be able to reuse work from the current run. --- compiler/rustc_incremental/src/errors.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs index 3354689d0ca33..a1f4464c76592 100644 --- a/compiler/rustc_incremental/src/errors.rs +++ b/compiler/rustc_incremental/src/errors.rs @@ -192,7 +192,8 @@ pub(crate) struct DeleteFull<'a> { } #[derive(Diagnostic)] -#[diag("error finalizing incremental compilation session directory `{$path}`: {$err}")] +#[diag("did not finalize incremental compilation session directory `{$path}`: {$err}")] +#[help("the next build will not be able to reuse work from this compilation")] pub(crate) struct Finalize<'a> { pub path: &'a Path, pub err: std::io::Error, From fac53a0cf82ed94246b8159a1d40e297e385bef4 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 18 Mar 2026 12:41:18 +0900 Subject: [PATCH 07/15] add regression test for issue 153695 --- .../reachable/never-pattern-closure-param-array.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/ui/reachable/never-pattern-closure-param-array.rs diff --git a/tests/ui/reachable/never-pattern-closure-param-array.rs b/tests/ui/reachable/never-pattern-closure-param-array.rs new file mode 100644 index 0000000000000..83bbc4b39b772 --- /dev/null +++ b/tests/ui/reachable/never-pattern-closure-param-array.rs @@ -0,0 +1,13 @@ +//@ check-pass +//@ edition: 2024 + +#![feature(never_patterns)] +#![allow(incomplete_features)] +#![allow(unreachable_code)] + +fn main() { + let _ = Some({ + return; + }) + .map(|!| [1]); +} From 74909ec285fb12f2a14234009354ad883b7cdabd Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 18 Mar 2026 12:41:27 +0900 Subject: [PATCH 08/15] fix ICE for arrays in diverging never-pattern closure bodies --- compiler/rustc_hir_typeck/src/expr.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 17c7c4b76b2d6..184c0d5a53d16 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1660,14 +1660,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let element_ty = if !args.is_empty() { - // This shouldn't happen unless there's another error - // (e.g., never patterns in inappropriate contexts). - if self.diverges.get() != Diverges::Maybe { - self.dcx() - .struct_span_err(expr.span, "unexpected divergence state in checking array") - .delay_as_bug(); - } - let coerce_to = expected .to_option(self) .and_then(|uty| { From 0cc494621967992bd1f72415ab244832ef55a1f5 Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Thu, 19 Mar 2026 21:18:31 -0400 Subject: [PATCH 09/15] add a test to make rustc_incremental finalize_session_directory rename fail Use a proc macro to observe the incremental session directory and do something platform specific so that renaming the '-working' session directory during finalize_session_directory will fail. On Unix, change the permissions on the parent directory to be read-only. On Windows, open and leak a file inside the `-working` directory. --- .../run-make/incremental-finalize-fail/foo.rs | 5 + .../incremental-finalize-fail/poison/lib.rs | 87 +++++++++++++++ .../incremental-finalize-fail/rmake.rs | 103 ++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 tests/run-make/incremental-finalize-fail/foo.rs create mode 100644 tests/run-make/incremental-finalize-fail/poison/lib.rs create mode 100644 tests/run-make/incremental-finalize-fail/rmake.rs diff --git a/tests/run-make/incremental-finalize-fail/foo.rs b/tests/run-make/incremental-finalize-fail/foo.rs new file mode 100644 index 0000000000000..1f1e2842b4658 --- /dev/null +++ b/tests/run-make/incremental-finalize-fail/foo.rs @@ -0,0 +1,5 @@ +poison::poison_finalize!(); + +pub fn hello() -> i32 { + 42 +} diff --git a/tests/run-make/incremental-finalize-fail/poison/lib.rs b/tests/run-make/incremental-finalize-fail/poison/lib.rs new file mode 100644 index 0000000000000..e191cf7ade4cd --- /dev/null +++ b/tests/run-make/incremental-finalize-fail/poison/lib.rs @@ -0,0 +1,87 @@ +//! A proc macro that sabotages the incremental compilation finalize step. +//! +//! When invoked, it locates the `-working` session directory inside the +//! incremental compilation directory (passed via POISON_INCR_DIR) and +//! makes it impossible to rename: +//! +//! - On Unix: removes write permission from the parent (crate) directory. +//! - On Windows: creates a file inside the -working directory and leaks +//! the file handle, preventing the directory from being renamed. + +extern crate proc_macro; + +use std::fs; +use std::path::PathBuf; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn poison_finalize(_input: TokenStream) -> TokenStream { + let incr_dir = std::env::var("POISON_INCR_DIR").expect("POISON_INCR_DIR must be set"); + + let crate_dir = find_crate_dir(&incr_dir); + let working_dir = find_working_dir(&crate_dir); + + #[cfg(unix)] + poison_unix(&crate_dir); + + #[cfg(windows)] + poison_windows(&working_dir); + + TokenStream::new() +} + +/// Remove write permission from the crate directory. +/// This causes rename() to fail with EACCES +#[cfg(unix)] +fn poison_unix(crate_dir: &PathBuf) { + use std::os::unix::fs::PermissionsExt; + let mut perms = fs::metadata(crate_dir).unwrap().permissions(); + perms.set_mode(0o555); // r-xr-xr-x + fs::set_permissions(crate_dir, perms).unwrap(); +} + +/// Create a file inside the -working directory and leak the +/// handle. Windows prevents renaming a directory when any file inside it +/// has an open handle. The handle stays open until the rustc process exits. +#[cfg(windows)] +fn poison_windows(working_dir: &PathBuf) { + let poison_file = working_dir.join("_poison_handle"); + let f = fs::File::create(&poison_file).unwrap(); + // Leak the handle so it stays open for the lifetime of the rustc process. + std::mem::forget(f); +} + +/// Find the crate directory for `foo` inside the incremental compilation dir. +/// +/// The incremental directory layout is: +/// {incr_dir}/{crate_name}-{stable_crate_id}/ +fn find_crate_dir(incr_dir: &str) -> PathBuf { + let mut dirs = fs::read_dir(incr_dir).unwrap().filter_map(|e| { + let e = e.ok()?; + let name = e.file_name(); + let name = name.to_str()?; + if e.file_type().ok()?.is_dir() && name.starts_with("foo-") { Some(e.path()) } else { None } + }); + + let first = + dirs.next().unwrap_or_else(|| panic!("no foo-* crate directory found in {incr_dir}")); + assert!( + dirs.next().is_none(), + "expected exactly one foo-* crate directory in {incr_dir}, found multiple" + ); + first +} + +/// Find the session directory ending in "-working" inside the crate directory +fn find_working_dir(crate_dir: &PathBuf) -> PathBuf { + for entry in fs::read_dir(crate_dir).unwrap() { + let entry = entry.unwrap(); + let name = entry.file_name(); + let name = name.to_str().unwrap().to_string(); + if name.starts_with("s-") && name.ends_with("-working") { + return entry.path(); + } + } + panic!("no -working session directory found in {}", crate_dir.display()); +} diff --git a/tests/run-make/incremental-finalize-fail/rmake.rs b/tests/run-make/incremental-finalize-fail/rmake.rs new file mode 100644 index 0000000000000..36ba2a48ca46b --- /dev/null +++ b/tests/run-make/incremental-finalize-fail/rmake.rs @@ -0,0 +1,103 @@ +//! Test that a failure to finalize the incremental compilation session directory +//! (i.e., the rename from "-working" to the SVH-based name) results in a +//! note, not an ICE, and that the compilation output is still produced. +//! +//! Strategy: +//! 1. Build the `poison` proc-macro crate +//! 2. Compile foo.rs with incremental compilation +//! The proc macro runs mid-compilation (after prepare_session_directory +//! but before finalize_session_directory) and sabotages the rename: +//! - On Unix: removes write permission from the crate directory, +//! so rename() fails with EACCES. +//! - On Windows: creates and leaks an open file handle inside the +//! -working directory, so rename() fails with ERROR_ACCESS_DENIED. +//! 3. Assert that stderr contains the finalize failure messages + +use std::fs; +use std::path::{Path, PathBuf}; + +use run_make_support::rustc; + +/// Guard that restores permissions on the incremental directory on drop, +/// to ensure cleanup is possible +struct IncrDirCleanup; + +fn main() { + let _cleanup = IncrDirCleanup; + + // Build the poison proc-macro crate + rustc().input("poison/lib.rs").crate_name("poison").crate_type("proc-macro").run(); + + let poison_dylib = find_proc_macro_dylib("poison"); + + // Incremental compile with the poison macro active + let out = rustc() + .input("foo.rs") + .crate_type("rlib") + .incremental("incr") + .extern_("poison", &poison_dylib) + .env("POISON_INCR_DIR", "incr") + .run(); + + out.assert_stderr_contains("note: did not finalize incremental compilation session directory"); + out.assert_stderr_contains( + "help: the next build will not be able to reuse work from this compilation", + ); + out.assert_stderr_not_contains("internal compiler error"); +} + +impl Drop for IncrDirCleanup { + fn drop(&mut self) { + let incr = Path::new("incr"); + if !incr.exists() { + return; + } + + #[cfg(unix)] + restore_permissions(incr); + } +} + +/// Recursively restore write permissions so rm -rf works after the chmod trick +#[cfg(unix)] +fn restore_permissions(path: &Path) { + use std::os::unix::fs::PermissionsExt; + if let Ok(entries) = fs::read_dir(path) { + for entry in entries.filter_map(|e| e.ok()) { + if entry.file_type().map_or(false, |ft| ft.is_dir()) { + let mut perms = match fs::metadata(entry.path()) { + Ok(m) => m.permissions(), + Err(_) => continue, + }; + perms.set_mode(0o755); + let _ = fs::set_permissions(entry.path(), perms); + } + } + } +} + +/// Locate the compiled proc-macro dylib by scanning the current directory. +fn find_proc_macro_dylib(name: &str) -> PathBuf { + let prefix = if cfg!(target_os = "windows") { "" } else { "lib" }; + + let ext: &str = if cfg!(target_os = "macos") { + "dylib" + } else if cfg!(target_os = "windows") { + "dll" + } else { + "so" + }; + + let lib_name = format!("{prefix}{name}.{ext}"); + + for entry in fs::read_dir(".").unwrap() { + let entry = entry.unwrap(); + let name = entry.file_name(); + let name = name.to_str().unwrap(); + if name == lib_name { + return entry.path(); + } + } + + panic!("could not find proc-macro dylib for `{name}`"); +} From 46a9efc86a990fc1332bfba78e2a6016c861fcfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 9 Mar 2026 23:28:01 +0000 Subject: [PATCH 10/15] Detect more cases of method shadowing with incorrect arguments ``` error[E0061]: this method takes 0 arguments but 1 argument was supplied --> $DIR/shadowed-intrinsic-method.rs:18:7 | LL | a.borrow(()); | ^^^^^^ -- unexpected argument of type `()` | note: the `borrow` call is resolved to the method in `std::borrow::Borrow`, shadowing the method of the same name on the inherent impl for `A` --> $DIR/shadowed-intrinsic-method.rs:18:7 | LL | use std::borrow::Borrow; | ------------------- `std::borrow::Borrow` imported here ... LL | a.borrow(()); | ^^^^^^ refers to `std::borrow::Borrow::borrow` note: method defined here --> $SRC_DIR/core/src/borrow.rs:LL:COL help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly | LL - a.borrow(()); LL + A::borrow(&mut a, ()); | help: remove the extra argument | LL - a.borrow(()); LL + a.borrow(); | ``` --- compiler/rustc_hir_typeck/src/demand.rs | 57 +++++---- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 + tests/ui/methods/shadowed-intrinsic-method.rs | 35 ++++++ .../methods/shadowed-intrinsic-method.stderr | 111 ++++++++++++++++++ ...-lookup-returns-sig-with-fewer-args.stderr | 14 +++ 5 files changed, 198 insertions(+), 21 deletions(-) create mode 100644 tests/ui/methods/shadowed-intrinsic-method.rs create mode 100644 tests/ui/methods/shadowed-intrinsic-method.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 0d49e06240532..47bf767ec122e 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -29,7 +29,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if expr_ty == expected { return; } - self.annotate_alternative_method_deref(err, expr, error); + self.annotate_alternative_method_deref_for_unop(err, expr, error); self.explain_self_literal(err, expr, expected, expr_ty); // Use `||` to give these suggestions a precedence @@ -899,7 +899,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } - fn annotate_alternative_method_deref( + fn annotate_alternative_method_deref_for_unop( &self, err: &mut Diag<'_>, expr: &hir::Expr<'_>, @@ -919,7 +919,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let hir::ExprKind::Unary(hir::UnOp::Deref, deref) = lhs.kind else { return; }; - let hir::ExprKind::MethodCall(path, base, args, _) = deref.kind else { + self.annotate_alternative_method_deref(err, deref, Some(expected)) + } + + #[tracing::instrument(skip(self, err), level = "debug")] + pub(crate) fn annotate_alternative_method_deref( + &self, + err: &mut Diag<'_>, + expr: &hir::Expr<'_>, + expected: Option>, + ) { + let hir::ExprKind::MethodCall(path, base, args, _) = expr.kind else { return; }; let Some(self_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(base) else { @@ -929,7 +939,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Ok(pick) = self.lookup_probe_for_diagnostic( path.ident, self_ty, - deref, + expr, probe::ProbeScope::TraitsInScope, None, ) else { @@ -939,10 +949,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Ok(in_scope_methods) = self.probe_for_name_many( probe::Mode::MethodCall, path.ident, - Some(expected), + expected, probe::IsSuggestion(true), self_ty, - deref.hir_id, + expr.hir_id, probe::ProbeScope::TraitsInScope, ) else { return; @@ -954,10 +964,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Ok(all_methods) = self.probe_for_name_many( probe::Mode::MethodCall, path.ident, - Some(expected), + expected, probe::IsSuggestion(true), self_ty, - deref.hir_id, + expr.hir_id, probe::ProbeScope::AllTraits, ) else { return; @@ -965,21 +975,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let suggestions: Vec<_> = all_methods .into_iter() - .filter(|c| c.item.def_id != pick.item.def_id) - .map(|c| { + .filter_map(|c| { + if c.item.def_id == pick.item.def_id { + return None; + } let m = c.item; let generic_args = ty::GenericArgs::for_item(self.tcx, m.def_id, |param, _| { - self.var_for_def(deref.span, param) + self.var_for_def(expr.span, param) }); - let mutability = - match self.tcx.fn_sig(m.def_id).skip_binder().input(0).skip_binder().kind() { - ty::Ref(_, _, hir::Mutability::Mut) => "&mut ", - ty::Ref(_, _, _) => "&", - _ => "", - }; - vec![ + let fn_sig = self.tcx.fn_sig(m.def_id); + if fn_sig.skip_binder().inputs().skip_binder().len() != args.len() + 1 { + return None; + } + let mutability = match fn_sig.skip_binder().input(0).skip_binder().kind() { + ty::Ref(_, _, hir::Mutability::Mut) => "&mut ", + ty::Ref(_, _, _) => "&", + _ => "", + }; + Some(vec![ ( - deref.span.until(base.span), + expr.span.until(base.span), format!( "{}({}", with_no_trimmed_paths!( @@ -989,10 +1004,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), ), match &args { - [] => (base.span.shrink_to_hi().with_hi(deref.span.hi()), ")".to_string()), + [] => (base.span.shrink_to_hi().with_hi(expr.span.hi()), ")".to_string()), [first, ..] => (base.span.between(first.span), ", ".to_string()), }, - ] + ]) }) .collect(); if suggestions.is_empty() { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 0471fd965cd82..f92dfb8bad7be 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2853,6 +2853,8 @@ impl<'a, 'b, 'tcx> ArgMatchingCtxt<'a, 'b, 'tcx> { ); return; } + + self.annotate_alternative_method_deref(err, self.call_expr, None); } /// A "softer" version of the `demand_compatible`, which checks types without persisting them, diff --git a/tests/ui/methods/shadowed-intrinsic-method.rs b/tests/ui/methods/shadowed-intrinsic-method.rs new file mode 100644 index 0000000000000..3d27c2597d98e --- /dev/null +++ b/tests/ui/methods/shadowed-intrinsic-method.rs @@ -0,0 +1,35 @@ +use std::borrow::Borrow; + +struct A; + +impl A { fn borrow(&mut self, _: ()) {} } + +struct B; + +fn main() { + // The fully-qualified path for items within functions is unnameable from outside that function. + impl B { fn borrow(&mut self, _: ()) {} } + + struct C; + // The fully-qualified path for items within functions is unnameable from outside that function. + impl C { fn borrow(&mut self, _: ()) {} } + + let mut a = A; + a.borrow(()); //~ ERROR E0061 + // A::borrow(&mut a, ()); + let mut b = B; + b.borrow(()); //~ ERROR E0061 + // This currently suggests `main::::borrow`, which is not correct, it should be + // B::borrow(&mut b, ()); + let mut c = C; + c.borrow(()); //~ ERROR E0061 + // This currently suggests `main::C::borrow`, which is not correct, it should be + // C::borrow(&mut c, ()); +} + +fn foo() { + let mut b = B; + b.borrow(()); //~ ERROR E0061 + // This currently suggests `main::::borrow`, which is not correct, it should be + // B::borrow(&mut b, ()); +} diff --git a/tests/ui/methods/shadowed-intrinsic-method.stderr b/tests/ui/methods/shadowed-intrinsic-method.stderr new file mode 100644 index 0000000000000..4de38fd396a09 --- /dev/null +++ b/tests/ui/methods/shadowed-intrinsic-method.stderr @@ -0,0 +1,111 @@ +error[E0061]: this method takes 0 arguments but 1 argument was supplied + --> $DIR/shadowed-intrinsic-method.rs:18:7 + | +LL | a.borrow(()); + | ^^^^^^ -- unexpected argument of type `()` + | +note: the `borrow` call is resolved to the method in `std::borrow::Borrow`, shadowing the method of the same name on the inherent impl for `A` + --> $DIR/shadowed-intrinsic-method.rs:18:7 + | +LL | use std::borrow::Borrow; + | ------------------- `std::borrow::Borrow` imported here +... +LL | a.borrow(()); + | ^^^^^^ refers to `std::borrow::Borrow::borrow` +note: method defined here + --> $SRC_DIR/core/src/borrow.rs:LL:COL +help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly + | +LL - a.borrow(()); +LL + A::borrow(&mut a, ()); + | +help: remove the extra argument + | +LL - a.borrow(()); +LL + a.borrow(); + | + +error[E0061]: this method takes 0 arguments but 1 argument was supplied + --> $DIR/shadowed-intrinsic-method.rs:21:7 + | +LL | b.borrow(()); + | ^^^^^^ -- unexpected argument of type `()` + | +note: the `borrow` call is resolved to the method in `std::borrow::Borrow`, shadowing the method of the same name on the inherent impl for `main::` + --> $DIR/shadowed-intrinsic-method.rs:21:7 + | +LL | use std::borrow::Borrow; + | ------------------- `std::borrow::Borrow` imported here +... +LL | b.borrow(()); + | ^^^^^^ refers to `std::borrow::Borrow::borrow` +note: method defined here + --> $SRC_DIR/core/src/borrow.rs:LL:COL +help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly + | +LL - b.borrow(()); +LL + main::::borrow(&mut b, ()); + | +help: remove the extra argument + | +LL - b.borrow(()); +LL + b.borrow(); + | + +error[E0061]: this method takes 0 arguments but 1 argument was supplied + --> $DIR/shadowed-intrinsic-method.rs:25:7 + | +LL | c.borrow(()); + | ^^^^^^ -- unexpected argument of type `()` + | +note: the `borrow` call is resolved to the method in `std::borrow::Borrow`, shadowing the method of the same name on the inherent impl for `main::C` + --> $DIR/shadowed-intrinsic-method.rs:25:7 + | +LL | use std::borrow::Borrow; + | ------------------- `std::borrow::Borrow` imported here +... +LL | c.borrow(()); + | ^^^^^^ refers to `std::borrow::Borrow::borrow` +note: method defined here + --> $SRC_DIR/core/src/borrow.rs:LL:COL +help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly + | +LL - c.borrow(()); +LL + main::C::borrow(&mut c, ()); + | +help: remove the extra argument + | +LL - c.borrow(()); +LL + c.borrow(); + | + +error[E0061]: this method takes 0 arguments but 1 argument was supplied + --> $DIR/shadowed-intrinsic-method.rs:32:7 + | +LL | b.borrow(()); + | ^^^^^^ -- unexpected argument of type `()` + | +note: the `borrow` call is resolved to the method in `std::borrow::Borrow`, shadowing the method of the same name on the inherent impl for `main::` + --> $DIR/shadowed-intrinsic-method.rs:32:7 + | +LL | use std::borrow::Borrow; + | ------------------- `std::borrow::Borrow` imported here +... +LL | b.borrow(()); + | ^^^^^^ refers to `std::borrow::Borrow::borrow` +note: method defined here + --> $SRC_DIR/core/src/borrow.rs:LL:COL +help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly + | +LL - b.borrow(()); +LL + main::::borrow(&mut b, ()); + | +help: remove the extra argument + | +LL - b.borrow(()); +LL + b.borrow(); + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr index 0f86916fcdae4..e5d22a2251f22 100644 --- a/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr +++ b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr @@ -11,6 +11,20 @@ note: method defined here | LL | pub fn get(&self, data: i32) { | ^^^ --------- +note: the `get` call is resolved to the method in `Target`, shadowing the method of the same name on trait `RandomTrait` + --> $DIR/diagnostic-method-lookup-returns-sig-with-fewer-args.rs:4:12 + | +LL | target.get(10.0); // (used to crash here) + | ^^^ refers to `Target::get` + = note: additionally, there are 1 other available methods that aren't in scope +help: you might have meant to call one of the other methods; you can use the fully-qualified path to call one of them explicitly + | +LL - target.get(10.0); // (used to crash here) +LL + <_ as std::slice::SliceIndex<_>>::get(target, 10.0); // (used to crash here) + | +LL - target.get(10.0); // (used to crash here) +LL + <_ as object::read::elf::relocation::Relr>::get(&target, 10.0); // (used to crash here) + | error: aborting due to 1 previous error From 0a5a78c2e9a48f0eeab63440427a3ff3baa4873d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 10 Mar 2026 15:24:11 +0000 Subject: [PATCH 11/15] Account for inherent methods --- compiler/rustc_hir_typeck/src/demand.rs | 48 ++++++++++++------- .../methods/shadowed-intrinsic-method.stderr | 4 +- .../suggestions/shadowed-lplace-method.fixed | 2 +- .../suggestions/shadowed-lplace-method.stderr | 2 +- 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 47bf767ec122e..2d41455b65a3c 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1,5 +1,5 @@ use rustc_errors::{Applicability, Diag, MultiSpan, listify}; -use rustc_hir::def::Res; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, find_attr}; use rustc_infer::infer::DefineOpaqueTypes; @@ -723,8 +723,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::Path { res: hir::def::Res::Def( - hir::def::DefKind::Static { .. } - | hir::def::DefKind::Const { .. }, + DefKind::Static { .. } | DefKind::Const { .. }, def_id, ), .. @@ -987,22 +986,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if fn_sig.skip_binder().inputs().skip_binder().len() != args.len() + 1 { return None; } - let mutability = match fn_sig.skip_binder().input(0).skip_binder().kind() { - ty::Ref(_, _, hir::Mutability::Mut) => "&mut ", - ty::Ref(_, _, _) => "&", - _ => "", + let rcvr_ty = fn_sig.skip_binder().input(0).skip_binder(); + let (mutability, ty) = match rcvr_ty.kind() { + ty::Ref(_, ty, hir::Mutability::Mut) => ("&mut ", ty), + ty::Ref(_, ty, _) => ("&", ty), + _ => ("", &rcvr_ty), + }; + let path = match self.tcx.assoc_parent(m.def_id) { + Some((_, DefKind::Impl { of_trait: true })) => with_no_trimmed_paths!( + // We have `impl Trait for T {}`, suggest `::method`. + self.tcx.def_path_str_with_args(m.def_id, generic_args) + ) + .to_string(), + Some((_, DefKind::Impl { of_trait: false })) => { + with_no_trimmed_paths!(if let ty::Adt(def, _) = ty.kind() { + // We have `impl T {}`, suggest `T::method`. + format!("{}::{}", self.tcx.def_path_str(def.did()), path.ident) + } else { + // This should be unreachable, as `impl &'a T {}` is invalid. + format!("{ty}::{}", path.ident) + }) + } + // Fallback for arbitrary self types. + _ => with_no_trimmed_paths!( + self.tcx.def_path_str_with_args(m.def_id, generic_args) + ) + .to_string(), }; Some(vec![ - ( - expr.span.until(base.span), - format!( - "{}({}", - with_no_trimmed_paths!( - self.tcx.def_path_str_with_args(m.def_id, generic_args,) - ), - mutability, - ), - ), + (expr.span.until(base.span), format!("{path}({}", mutability,)), match &args { [] => (base.span.shrink_to_hi().with_hi(expr.span.hi()), ")".to_string()), [first, ..] => (base.span.between(first.span), ", ".to_string()), @@ -1278,7 +1290,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let hir::def::Res::Def(kind, def_id) = path.res else { return; }; - let callable_kind = if matches!(kind, hir::def::DefKind::Ctor(_, _)) { + let callable_kind = if matches!(kind, DefKind::Ctor(_, _)) { CallableKind::Constructor } else { CallableKind::Function diff --git a/tests/ui/methods/shadowed-intrinsic-method.stderr b/tests/ui/methods/shadowed-intrinsic-method.stderr index 4de38fd396a09..a7fda06bee331 100644 --- a/tests/ui/methods/shadowed-intrinsic-method.stderr +++ b/tests/ui/methods/shadowed-intrinsic-method.stderr @@ -44,7 +44,7 @@ note: method defined here help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly | LL - b.borrow(()); -LL + main::::borrow(&mut b, ()); +LL + B::borrow(&mut b, ()); | help: remove the extra argument | @@ -98,7 +98,7 @@ note: method defined here help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly | LL - b.borrow(()); -LL + main::::borrow(&mut b, ()); +LL + B::borrow(&mut b, ()); | help: remove the extra argument | diff --git a/tests/ui/suggestions/shadowed-lplace-method.fixed b/tests/ui/suggestions/shadowed-lplace-method.fixed index 87db01a3b230b..fc94782f516a4 100644 --- a/tests/ui/suggestions/shadowed-lplace-method.fixed +++ b/tests/ui/suggestions/shadowed-lplace-method.fixed @@ -6,5 +6,5 @@ use std::rc::Rc; fn main() { let rc = Rc::new(RefCell::new(true)); - *std::cell::RefCell::<_>::borrow_mut(&rc) = false; //~ ERROR E0308 + *std::cell::RefCell::borrow_mut(&rc) = false; //~ ERROR E0308 } diff --git a/tests/ui/suggestions/shadowed-lplace-method.stderr b/tests/ui/suggestions/shadowed-lplace-method.stderr index aab9e442007ff..3469da21b1f04 100644 --- a/tests/ui/suggestions/shadowed-lplace-method.stderr +++ b/tests/ui/suggestions/shadowed-lplace-method.stderr @@ -19,7 +19,7 @@ LL | *rc.borrow_mut() = false; help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly | LL - *rc.borrow_mut() = false; -LL + *std::cell::RefCell::<_>::borrow_mut(&rc) = false; +LL + *std::cell::RefCell::borrow_mut(&rc) = false; | error: aborting due to 1 previous error From a72d2261a9900f67131de8abb6aaa7aed3b4de97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 10 Mar 2026 15:45:24 +0000 Subject: [PATCH 12/15] Tweak output --- compiler/rustc_hir_typeck/src/demand.rs | 13 ++++++------- tests/ui/methods/shadowed-intrinsic-method.rs | 2 ++ .../methods/shadowed-intrinsic-method.stderr | 18 +++++++++--------- .../suggestions/shadowed-lplace-method.fixed | 2 +- .../suggestions/shadowed-lplace-method.stderr | 2 +- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 2d41455b65a3c..01365a8c559c3 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -993,19 +993,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => ("", &rcvr_ty), }; let path = match self.tcx.assoc_parent(m.def_id) { - Some((_, DefKind::Impl { of_trait: true })) => with_no_trimmed_paths!( + Some((_, DefKind::Impl { of_trait: true })) => { // We have `impl Trait for T {}`, suggest `::method`. - self.tcx.def_path_str_with_args(m.def_id, generic_args) - ) - .to_string(), + self.tcx.def_path_str_with_args(m.def_id, generic_args).to_string() + } Some((_, DefKind::Impl { of_trait: false })) => { - with_no_trimmed_paths!(if let ty::Adt(def, _) = ty.kind() { + if let ty::Adt(def, _) = ty.kind() { // We have `impl T {}`, suggest `T::method`. format!("{}::{}", self.tcx.def_path_str(def.did()), path.ident) } else { // This should be unreachable, as `impl &'a T {}` is invalid. format!("{ty}::{}", path.ident) - }) + } } // Fallback for arbitrary self types. _ => with_no_trimmed_paths!( @@ -1014,7 +1013,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .to_string(), }; Some(vec![ - (expr.span.until(base.span), format!("{path}({}", mutability,)), + (expr.span.until(base.span), format!("{path}({}", mutability)), match &args { [] => (base.span.shrink_to_hi().with_hi(expr.span.hi()), ")".to_string()), [first, ..] => (base.span.between(first.span), ", ".to_string()), diff --git a/tests/ui/methods/shadowed-intrinsic-method.rs b/tests/ui/methods/shadowed-intrinsic-method.rs index 3d27c2597d98e..8350d6a7ba5f0 100644 --- a/tests/ui/methods/shadowed-intrinsic-method.rs +++ b/tests/ui/methods/shadowed-intrinsic-method.rs @@ -1,3 +1,5 @@ +// Can't use rustfix because we provide two suggestions: +// to remove the arg for `Borrow::borrow` or to call `Type::borrow`. use std::borrow::Borrow; struct A; diff --git a/tests/ui/methods/shadowed-intrinsic-method.stderr b/tests/ui/methods/shadowed-intrinsic-method.stderr index a7fda06bee331..a832714cd1f97 100644 --- a/tests/ui/methods/shadowed-intrinsic-method.stderr +++ b/tests/ui/methods/shadowed-intrinsic-method.stderr @@ -1,11 +1,11 @@ error[E0061]: this method takes 0 arguments but 1 argument was supplied - --> $DIR/shadowed-intrinsic-method.rs:18:7 + --> $DIR/shadowed-intrinsic-method.rs:20:7 | LL | a.borrow(()); | ^^^^^^ -- unexpected argument of type `()` | note: the `borrow` call is resolved to the method in `std::borrow::Borrow`, shadowing the method of the same name on the inherent impl for `A` - --> $DIR/shadowed-intrinsic-method.rs:18:7 + --> $DIR/shadowed-intrinsic-method.rs:20:7 | LL | use std::borrow::Borrow; | ------------------- `std::borrow::Borrow` imported here @@ -26,13 +26,13 @@ LL + a.borrow(); | error[E0061]: this method takes 0 arguments but 1 argument was supplied - --> $DIR/shadowed-intrinsic-method.rs:21:7 + --> $DIR/shadowed-intrinsic-method.rs:23:7 | LL | b.borrow(()); | ^^^^^^ -- unexpected argument of type `()` | note: the `borrow` call is resolved to the method in `std::borrow::Borrow`, shadowing the method of the same name on the inherent impl for `main::` - --> $DIR/shadowed-intrinsic-method.rs:21:7 + --> $DIR/shadowed-intrinsic-method.rs:23:7 | LL | use std::borrow::Borrow; | ------------------- `std::borrow::Borrow` imported here @@ -53,13 +53,13 @@ LL + b.borrow(); | error[E0061]: this method takes 0 arguments but 1 argument was supplied - --> $DIR/shadowed-intrinsic-method.rs:25:7 + --> $DIR/shadowed-intrinsic-method.rs:27:7 | LL | c.borrow(()); | ^^^^^^ -- unexpected argument of type `()` | note: the `borrow` call is resolved to the method in `std::borrow::Borrow`, shadowing the method of the same name on the inherent impl for `main::C` - --> $DIR/shadowed-intrinsic-method.rs:25:7 + --> $DIR/shadowed-intrinsic-method.rs:27:7 | LL | use std::borrow::Borrow; | ------------------- `std::borrow::Borrow` imported here @@ -71,7 +71,7 @@ note: method defined here help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly | LL - c.borrow(()); -LL + main::C::borrow(&mut c, ()); +LL + C::borrow(&mut c, ()); | help: remove the extra argument | @@ -80,13 +80,13 @@ LL + c.borrow(); | error[E0061]: this method takes 0 arguments but 1 argument was supplied - --> $DIR/shadowed-intrinsic-method.rs:32:7 + --> $DIR/shadowed-intrinsic-method.rs:34:7 | LL | b.borrow(()); | ^^^^^^ -- unexpected argument of type `()` | note: the `borrow` call is resolved to the method in `std::borrow::Borrow`, shadowing the method of the same name on the inherent impl for `main::` - --> $DIR/shadowed-intrinsic-method.rs:32:7 + --> $DIR/shadowed-intrinsic-method.rs:34:7 | LL | use std::borrow::Borrow; | ------------------- `std::borrow::Borrow` imported here diff --git a/tests/ui/suggestions/shadowed-lplace-method.fixed b/tests/ui/suggestions/shadowed-lplace-method.fixed index fc94782f516a4..e7f6df9fff8fb 100644 --- a/tests/ui/suggestions/shadowed-lplace-method.fixed +++ b/tests/ui/suggestions/shadowed-lplace-method.fixed @@ -6,5 +6,5 @@ use std::rc::Rc; fn main() { let rc = Rc::new(RefCell::new(true)); - *std::cell::RefCell::borrow_mut(&rc) = false; //~ ERROR E0308 + *RefCell::borrow_mut(&rc) = false; //~ ERROR E0308 } diff --git a/tests/ui/suggestions/shadowed-lplace-method.stderr b/tests/ui/suggestions/shadowed-lplace-method.stderr index 3469da21b1f04..dfd52b9b5587b 100644 --- a/tests/ui/suggestions/shadowed-lplace-method.stderr +++ b/tests/ui/suggestions/shadowed-lplace-method.stderr @@ -19,7 +19,7 @@ LL | *rc.borrow_mut() = false; help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly | LL - *rc.borrow_mut() = false; -LL + *std::cell::RefCell::borrow_mut(&rc) = false; +LL + *RefCell::borrow_mut(&rc) = false; | error: aborting due to 1 previous error From 0bd285251d76cb97eaa4469b204cceb43ea6053a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 25 Mar 2026 19:22:02 +0000 Subject: [PATCH 13/15] Tweak wording on "other methods available" note Handle correct gramar in the face of a single other option, or many. --- compiler/rustc_hir_typeck/src/demand.rs | 8 +++++--- ...ostic-method-lookup-returns-sig-with-fewer-args.stderr | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 01365a8c559c3..c5ad8cf33e8bb 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1,4 +1,4 @@ -use rustc_errors::{Applicability, Diag, MultiSpan, listify}; +use rustc_errors::{Applicability, Diag, MultiSpan, listify, pluralize}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, find_attr}; @@ -1072,9 +1072,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), ); if suggestions.len() > other_methods_in_scope.len() { + let n = suggestions.len() - other_methods_in_scope.len(); err.note(format!( - "additionally, there are {} other available methods that aren't in scope", - suggestions.len() - other_methods_in_scope.len() + "additionally, there {are} {n} other available method{s} that {are}n't in scope", + are = pluralize!("is", n), + s = pluralize!(n), )); } err.multipart_suggestions( diff --git a/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr index e5d22a2251f22..c683f09f19106 100644 --- a/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr +++ b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr @@ -16,7 +16,7 @@ note: the `get` call is resolved to the method in `Target`, shadowing the method | LL | target.get(10.0); // (used to crash here) | ^^^ refers to `Target::get` - = note: additionally, there are 1 other available methods that aren't in scope + = note: additionally, there is 1 other available method that isn't in scope help: you might have meant to call one of the other methods; you can use the fully-qualified path to call one of them explicitly | LL - target.get(10.0); // (used to crash here) From b5605cd6ab936bcf1226725a74437a8e5c2aa9c2 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 26 Mar 2026 10:43:49 +0000 Subject: [PATCH 14/15] move many tests out of `ui/unsafe` --- tests/ui/{unsafe => union}/access_union_field.rs | 0 tests/ui/{unsafe => union}/access_union_field.stderr | 0 tests/ui/{unsafe => union}/union-assignop.rs | 0 tests/ui/{unsafe => union}/union-assignop.stderr | 0 tests/ui/{unsafe => union}/union-modification.rs | 0 tests/ui/{unsafe => union}/union-pat-in-param.rs | 0 tests/ui/{unsafe => union}/union-pat-in-param.stderr | 0 tests/ui/{unsafe => union}/union.rs | 0 tests/ui/{unsafe => union}/union.stderr | 0 tests/ui/{unsafe => union}/union_access_through_block.rs | 0 tests/ui/{unsafe => union}/union_destructure.rs | 0 tests/ui/{unsafe => union}/union_wild_or_wild.rs | 0 tests/ui/{unsafe => unsafe-binders}/move-out-of-non-copy.rs | 0 tests/ui/{unsafe => unsafe-binders}/move-out-of-non-copy.stderr | 0 .../initializing-ranged-via-ctor.rs | 0 .../initializing-ranged-via-ctor.stderr | 0 .../ranged-ctor-as-fn-ptr.rs | 0 .../ranged-ctor-as-fn-ptr.stderr | 0 .../unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints.rs | 0 .../{ => rustc_layout_scalar_valid_range}/ranged_ints.stderr | 0 .../unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints2.rs | 0 .../{ => rustc_layout_scalar_valid_range}/ranged_ints2.stderr | 0 .../{ => rustc_layout_scalar_valid_range}/ranged_ints2_const.rs | 0 .../ranged_ints2_const.stderr | 0 .../unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints3.rs | 0 .../{ => rustc_layout_scalar_valid_range}/ranged_ints3.stderr | 0 .../{ => rustc_layout_scalar_valid_range}/ranged_ints3_const.rs | 0 .../ranged_ints3_const.stderr | 0 .../{ => rustc_layout_scalar_valid_range}/ranged_ints3_match.rs | 0 .../ranged_ints3_match.stderr | 0 .../unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints4.rs | 0 .../{ => rustc_layout_scalar_valid_range}/ranged_ints4.stderr | 0 .../{ => rustc_layout_scalar_valid_range}/ranged_ints4_const.rs | 0 .../ranged_ints4_const.stderr | 0 .../{ => rustc_layout_scalar_valid_range}/ranged_ints_const.rs | 0 .../ranged_ints_const.stderr | 0 .../{ => rustc_layout_scalar_valid_range}/ranged_ints_macro.rs | 0 37 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{unsafe => union}/access_union_field.rs (100%) rename tests/ui/{unsafe => union}/access_union_field.stderr (100%) rename tests/ui/{unsafe => union}/union-assignop.rs (100%) rename tests/ui/{unsafe => union}/union-assignop.stderr (100%) rename tests/ui/{unsafe => union}/union-modification.rs (100%) rename tests/ui/{unsafe => union}/union-pat-in-param.rs (100%) rename tests/ui/{unsafe => union}/union-pat-in-param.stderr (100%) rename tests/ui/{unsafe => union}/union.rs (100%) rename tests/ui/{unsafe => union}/union.stderr (100%) rename tests/ui/{unsafe => union}/union_access_through_block.rs (100%) rename tests/ui/{unsafe => union}/union_destructure.rs (100%) rename tests/ui/{unsafe => union}/union_wild_or_wild.rs (100%) rename tests/ui/{unsafe => unsafe-binders}/move-out-of-non-copy.rs (100%) rename tests/ui/{unsafe => unsafe-binders}/move-out-of-non-copy.stderr (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/initializing-ranged-via-ctor.rs (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/initializing-ranged-via-ctor.stderr (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged-ctor-as-fn-ptr.rs (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged-ctor-as-fn-ptr.stderr (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints.rs (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints.stderr (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints2.rs (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints2.stderr (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints2_const.rs (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints2_const.stderr (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints3.rs (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints3.stderr (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints3_const.rs (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints3_const.stderr (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints3_match.rs (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints3_match.stderr (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints4.rs (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints4.stderr (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints4_const.rs (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints4_const.stderr (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints_const.rs (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints_const.stderr (100%) rename tests/ui/unsafe/{ => rustc_layout_scalar_valid_range}/ranged_ints_macro.rs (100%) diff --git a/tests/ui/unsafe/access_union_field.rs b/tests/ui/union/access_union_field.rs similarity index 100% rename from tests/ui/unsafe/access_union_field.rs rename to tests/ui/union/access_union_field.rs diff --git a/tests/ui/unsafe/access_union_field.stderr b/tests/ui/union/access_union_field.stderr similarity index 100% rename from tests/ui/unsafe/access_union_field.stderr rename to tests/ui/union/access_union_field.stderr diff --git a/tests/ui/unsafe/union-assignop.rs b/tests/ui/union/union-assignop.rs similarity index 100% rename from tests/ui/unsafe/union-assignop.rs rename to tests/ui/union/union-assignop.rs diff --git a/tests/ui/unsafe/union-assignop.stderr b/tests/ui/union/union-assignop.stderr similarity index 100% rename from tests/ui/unsafe/union-assignop.stderr rename to tests/ui/union/union-assignop.stderr diff --git a/tests/ui/unsafe/union-modification.rs b/tests/ui/union/union-modification.rs similarity index 100% rename from tests/ui/unsafe/union-modification.rs rename to tests/ui/union/union-modification.rs diff --git a/tests/ui/unsafe/union-pat-in-param.rs b/tests/ui/union/union-pat-in-param.rs similarity index 100% rename from tests/ui/unsafe/union-pat-in-param.rs rename to tests/ui/union/union-pat-in-param.rs diff --git a/tests/ui/unsafe/union-pat-in-param.stderr b/tests/ui/union/union-pat-in-param.stderr similarity index 100% rename from tests/ui/unsafe/union-pat-in-param.stderr rename to tests/ui/union/union-pat-in-param.stderr diff --git a/tests/ui/unsafe/union.rs b/tests/ui/union/union.rs similarity index 100% rename from tests/ui/unsafe/union.rs rename to tests/ui/union/union.rs diff --git a/tests/ui/unsafe/union.stderr b/tests/ui/union/union.stderr similarity index 100% rename from tests/ui/unsafe/union.stderr rename to tests/ui/union/union.stderr diff --git a/tests/ui/unsafe/union_access_through_block.rs b/tests/ui/union/union_access_through_block.rs similarity index 100% rename from tests/ui/unsafe/union_access_through_block.rs rename to tests/ui/union/union_access_through_block.rs diff --git a/tests/ui/unsafe/union_destructure.rs b/tests/ui/union/union_destructure.rs similarity index 100% rename from tests/ui/unsafe/union_destructure.rs rename to tests/ui/union/union_destructure.rs diff --git a/tests/ui/unsafe/union_wild_or_wild.rs b/tests/ui/union/union_wild_or_wild.rs similarity index 100% rename from tests/ui/unsafe/union_wild_or_wild.rs rename to tests/ui/union/union_wild_or_wild.rs diff --git a/tests/ui/unsafe/move-out-of-non-copy.rs b/tests/ui/unsafe-binders/move-out-of-non-copy.rs similarity index 100% rename from tests/ui/unsafe/move-out-of-non-copy.rs rename to tests/ui/unsafe-binders/move-out-of-non-copy.rs diff --git a/tests/ui/unsafe/move-out-of-non-copy.stderr b/tests/ui/unsafe-binders/move-out-of-non-copy.stderr similarity index 100% rename from tests/ui/unsafe/move-out-of-non-copy.stderr rename to tests/ui/unsafe-binders/move-out-of-non-copy.stderr diff --git a/tests/ui/unsafe/initializing-ranged-via-ctor.rs b/tests/ui/unsafe/rustc_layout_scalar_valid_range/initializing-ranged-via-ctor.rs similarity index 100% rename from tests/ui/unsafe/initializing-ranged-via-ctor.rs rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/initializing-ranged-via-ctor.rs diff --git a/tests/ui/unsafe/initializing-ranged-via-ctor.stderr b/tests/ui/unsafe/rustc_layout_scalar_valid_range/initializing-ranged-via-ctor.stderr similarity index 100% rename from tests/ui/unsafe/initializing-ranged-via-ctor.stderr rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/initializing-ranged-via-ctor.stderr diff --git a/tests/ui/unsafe/ranged-ctor-as-fn-ptr.rs b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged-ctor-as-fn-ptr.rs similarity index 100% rename from tests/ui/unsafe/ranged-ctor-as-fn-ptr.rs rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged-ctor-as-fn-ptr.rs diff --git a/tests/ui/unsafe/ranged-ctor-as-fn-ptr.stderr b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged-ctor-as-fn-ptr.stderr similarity index 100% rename from tests/ui/unsafe/ranged-ctor-as-fn-ptr.stderr rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged-ctor-as-fn-ptr.stderr diff --git a/tests/ui/unsafe/ranged_ints.rs b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints.rs similarity index 100% rename from tests/ui/unsafe/ranged_ints.rs rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints.rs diff --git a/tests/ui/unsafe/ranged_ints.stderr b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints.stderr similarity index 100% rename from tests/ui/unsafe/ranged_ints.stderr rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints.stderr diff --git a/tests/ui/unsafe/ranged_ints2.rs b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints2.rs similarity index 100% rename from tests/ui/unsafe/ranged_ints2.rs rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints2.rs diff --git a/tests/ui/unsafe/ranged_ints2.stderr b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints2.stderr similarity index 100% rename from tests/ui/unsafe/ranged_ints2.stderr rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints2.stderr diff --git a/tests/ui/unsafe/ranged_ints2_const.rs b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints2_const.rs similarity index 100% rename from tests/ui/unsafe/ranged_ints2_const.rs rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints2_const.rs diff --git a/tests/ui/unsafe/ranged_ints2_const.stderr b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints2_const.stderr similarity index 100% rename from tests/ui/unsafe/ranged_ints2_const.stderr rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints2_const.stderr diff --git a/tests/ui/unsafe/ranged_ints3.rs b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints3.rs similarity index 100% rename from tests/ui/unsafe/ranged_ints3.rs rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints3.rs diff --git a/tests/ui/unsafe/ranged_ints3.stderr b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints3.stderr similarity index 100% rename from tests/ui/unsafe/ranged_ints3.stderr rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints3.stderr diff --git a/tests/ui/unsafe/ranged_ints3_const.rs b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints3_const.rs similarity index 100% rename from tests/ui/unsafe/ranged_ints3_const.rs rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints3_const.rs diff --git a/tests/ui/unsafe/ranged_ints3_const.stderr b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints3_const.stderr similarity index 100% rename from tests/ui/unsafe/ranged_ints3_const.stderr rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints3_const.stderr diff --git a/tests/ui/unsafe/ranged_ints3_match.rs b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints3_match.rs similarity index 100% rename from tests/ui/unsafe/ranged_ints3_match.rs rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints3_match.rs diff --git a/tests/ui/unsafe/ranged_ints3_match.stderr b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints3_match.stderr similarity index 100% rename from tests/ui/unsafe/ranged_ints3_match.stderr rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints3_match.stderr diff --git a/tests/ui/unsafe/ranged_ints4.rs b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints4.rs similarity index 100% rename from tests/ui/unsafe/ranged_ints4.rs rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints4.rs diff --git a/tests/ui/unsafe/ranged_ints4.stderr b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints4.stderr similarity index 100% rename from tests/ui/unsafe/ranged_ints4.stderr rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints4.stderr diff --git a/tests/ui/unsafe/ranged_ints4_const.rs b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints4_const.rs similarity index 100% rename from tests/ui/unsafe/ranged_ints4_const.rs rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints4_const.rs diff --git a/tests/ui/unsafe/ranged_ints4_const.stderr b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints4_const.stderr similarity index 100% rename from tests/ui/unsafe/ranged_ints4_const.stderr rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints4_const.stderr diff --git a/tests/ui/unsafe/ranged_ints_const.rs b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints_const.rs similarity index 100% rename from tests/ui/unsafe/ranged_ints_const.rs rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints_const.rs diff --git a/tests/ui/unsafe/ranged_ints_const.stderr b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints_const.stderr similarity index 100% rename from tests/ui/unsafe/ranged_ints_const.stderr rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints_const.stderr diff --git a/tests/ui/unsafe/ranged_ints_macro.rs b/tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints_macro.rs similarity index 100% rename from tests/ui/unsafe/ranged_ints_macro.rs rename to tests/ui/unsafe/rustc_layout_scalar_valid_range/ranged_ints_macro.rs From 5efde4b7287fed9bf39dddebbb3464efa1d11f97 Mon Sep 17 00:00:00 2001 From: apiraino Date: Thu, 26 Mar 2026 16:32:50 +0000 Subject: [PATCH 15/15] Create GPU target notification group MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Create GPU target notification group * Update triagebot.toml Co-authored-by: 许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com> --- triagebot.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 8d6401c490561..07b3bd295dbe1 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -194,6 +194,11 @@ Hi relnotes-interest-group, this issue/PR could use some help in reviewing / adjusting release notes. Could you take a look if available? Thanks <3 """ +[ping.gpu-target] +message = """\ +Hi GPU experts, this issue/PR could use some guidance on how this should be +resolved/implemented. Could you take a look if available? Thanks <3 +""" # ------------------------------------------------------------------------------ # Autolabels