From 74c99d9c96ae53e4a2d584ad97e9407feabaf964 Mon Sep 17 00:00:00 2001 From: 0xEgao Date: Wed, 24 Jun 2026 00:17:04 +0530 Subject: [PATCH 01/13] Document NonNull layout guarantees --- library/core/src/num/nonzero.rs | 4 ++-- library/core/src/ptr/non_null.rs | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 5863fd57e71e6..b6532f6064330 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -82,7 +82,7 @@ impl_zeroable_primitive!( /// /// `NonZero` is guaranteed to have the same layout and bit validity as `T` /// with the exception that the all-zero bit pattern is invalid. -/// `Option>` is guaranteed to be compatible with `T`, including in +/// `Option>` is guaranteed to be ABI-compatible with `T`, including in /// FFI. /// /// Thanks to the [null pointer optimization], `NonZero` and @@ -525,7 +525,7 @@ macro_rules! nonzero_integer { /// #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`")] /// with the exception that `0` is not a valid instance. - #[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`,")] + #[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be ABI-compatible with `", stringify!($Int), "`,")] /// including in FFI. /// /// Thanks to the [null pointer optimization], diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index bafc37469b32f..b30c9f8196ded 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -47,7 +47,12 @@ use crate::{fmt, hash, intrinsics, mem, ptr}; /// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr` /// is never used for mutation. /// -/// # Representation +/// # Layout +/// +/// `NonNull` is guaranteed to have the same layout and bit validity as `*mut T` +/// with the exception that a null pointer is invalid. +/// `Option>` is guaranteed to be ABI-compatible with `*mut T`, including in +/// FFI. /// /// Thanks to the [null pointer optimization], /// `NonNull` and `Option>` From b587ba0402e0760029e9e52704ae09fb9a45ad64 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Mon, 6 Jul 2026 15:48:20 +0200 Subject: [PATCH 02/13] Add do_not_recommend test --- .../auxiliary/foreign_blanket_impl.rs | 10 ++++ .../method_call.current.stderr | 57 +++++++++++++++++++ .../do_not_recommend/method_call.next.stderr | 45 +++++++++++++++ .../do_not_recommend/method_call.rs | 38 +++++++++++++ 4 files changed, 150 insertions(+) create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/auxiliary/foreign_blanket_impl.rs create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/method_call.current.stderr create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/method_call.next.stderr create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/method_call.rs diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/auxiliary/foreign_blanket_impl.rs b/tests/ui/diagnostic_namespace/do_not_recommend/auxiliary/foreign_blanket_impl.rs new file mode 100644 index 0000000000000..b3490d743b9bd --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/auxiliary/foreign_blanket_impl.rs @@ -0,0 +1,10 @@ +pub struct ForeignType(pub T); + +pub trait DoNotMentionThis {} + +#[diagnostic::do_not_recommend] +impl Clone for ForeignType { + fn clone(&self) -> Self { + todo!() + } +} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/method_call.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/method_call.current.stderr new file mode 100644 index 0000000000000..0fd90fae5e6fd --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/method_call.current.stderr @@ -0,0 +1,57 @@ +error[E0277]: the trait bound `ForeignType: Clone` is not satisfied + --> $DIR/method_call.rs:21:30 + | +LL | let _ = Clone::clone(&f); + | ^^ the trait `Clone` is not implemented for `ForeignType` + +error[E0599]: the method `clone` exists for struct `ForeignType`, but its trait bounds were not satisfied + --> $DIR/method_call.rs:24:19 + | +LL | let _ = f.clone(); + | ^^^^^ method cannot be called on `ForeignType` due to unsatisfied trait bounds + | + ::: $DIR/auxiliary/foreign_blanket_impl.rs:1:1 + | +LL | pub struct ForeignType(pub T); + | ------------------------- doesn't satisfy `ForeignType: Clone` + | + = note: the following trait bounds were not satisfied: + `u8: DoNotMentionThis` + which is required by `ForeignType: Clone` + +error[E0277]: the trait bound `LocalType: Clone` is not satisfied + --> $DIR/method_call.rs:31:30 + | +LL | let _ = Clone::clone(&l); + | ^^ the trait `Clone` is not implemented for `LocalType` + | +help: consider annotating `LocalType` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | pub struct LocalType(pub T); + | + +error[E0599]: the method `clone` exists for struct `LocalType`, but its trait bounds were not satisfied + --> $DIR/method_call.rs:34:19 + | +LL | pub struct LocalType(pub T); + | ----------------------- method `clone` not found for this struct because it doesn't satisfy `LocalType: Clone` +... +LL | let _ = l.clone(); + | ^^^^^ method cannot be called on `LocalType` due to unsatisfied trait bounds + | +note: trait bound `u8: DoNotMentionThis` was not satisfied + --> $DIR/method_call.rs:12:9 + | +LL | impl Clone for LocalType { + | ^^^^^^^^^^^^^^^^ ----- ------------ + | | + | unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `clone`, perhaps you need to implement it: + candidate #1: `Clone` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/method_call.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/method_call.next.stderr new file mode 100644 index 0000000000000..1bd7267b6ee99 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/method_call.next.stderr @@ -0,0 +1,45 @@ +error[E0277]: the trait bound `ForeignType: Clone` is not satisfied + --> $DIR/method_call.rs:21:30 + | +LL | let _ = Clone::clone(&f); + | ------------ ^^ the trait `Clone` is not implemented for `ForeignType` + | | + | required by a bound introduced by this call + +error[E0599]: no method named `clone` found for struct `ForeignType` in the current scope + --> $DIR/method_call.rs:24:19 + | +LL | let _ = f.clone(); + | ^^^^^ method not found in `ForeignType` + +error[E0277]: the trait bound `LocalType: Clone` is not satisfied + --> $DIR/method_call.rs:31:30 + | +LL | let _ = Clone::clone(&l); + | ------------ ^^ the trait `Clone` is not implemented for `LocalType` + | | + | required by a bound introduced by this call + | +help: consider annotating `LocalType` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | pub struct LocalType(pub T); + | + +error[E0599]: no method named `clone` found for struct `LocalType` in the current scope + --> $DIR/method_call.rs:34:19 + | +LL | pub struct LocalType(pub T); + | ----------------------- method `clone` not found for this struct +... +LL | let _ = l.clone(); + | ^^^^^ method not found in `LocalType` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `clone`, perhaps you need to implement it: + candidate #1: `Clone` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/method_call.rs b/tests/ui/diagnostic_namespace/do_not_recommend/method_call.rs new file mode 100644 index 0000000000000..2b10cacd30227 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/method_call.rs @@ -0,0 +1,38 @@ +//@aux-build:foreign_blanket_impl.rs +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +extern crate foreign_blanket_impl; +use foreign_blanket_impl::{DoNotMentionThis, ForeignType}; + +pub struct LocalType(pub T); + +#[diagnostic::do_not_recommend] +impl Clone for LocalType { + fn clone(&self) -> Self { + todo!() + } +} + +fn main() { + { + let f = ForeignType(42_u8); + let _ = Clone::clone(&f); + //~^ERROR the trait bound `ForeignType: Clone` is not satisfied [E0277] + + let _ = f.clone(); + //[next]~^ERROR no method named `clone` found for struct `ForeignType` in the current scope [E0599] + //[current]~^^ERROR the method `clone` exists for struct `ForeignType`, but its trait bounds were not satisfied [E0599] + } + + { + let l = LocalType(42_u8); + let _ = Clone::clone(&l); + //~^ERROR the trait bound `LocalType: Clone` is not satisfied [E0277] + + let _ = l.clone(); + //[next]~^ERROR no method named `clone` found for struct `LocalType` in the current scope [E0599] + //[current]~^^ERROR the method `clone` exists for struct `LocalType`, but its trait bounds were not satisfied [E0599] + } +} From 60aa191c32e3e3f36e6a354b6b5e0b248128a3cf Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Tue, 23 Jun 2026 02:26:19 +0000 Subject: [PATCH 03/13] Pretty-print user self types too. --- compiler/rustc_middle/src/ty/generic_args.rs | 6 +- compiler/rustc_middle/src/ty/print/pretty.rs | 23 + .../rustc_middle/src/ty/typeck_results.rs | 24 +- ..._of_reborrow.SimplifyCfg-initial.after.mir | 18 +- ...ignment.main.SimplifyCfg-initial.after.mir | 4 +- .../issue_101867.main.built.after.mir | 4 +- ...otations.match_assoc_const.built.after.mir | 4 +- ...ns.match_assoc_const_range.built.after.mir | 8 +- ...d_in_vec.build-{closure#0}.built.after.mir | 399 ++++++++++++++++++ tests/mir-opt/coroutine/unwind_in_vec.rs | 10 + .../issue_99325.main.built.after.32bit.mir | 4 +- .../issue_99325.main.built.after.64bit.mir | 4 +- 12 files changed, 464 insertions(+), 44 deletions(-) create mode 100644 tests/mir-opt/coroutine/unwind_in_vec.build-{closure#0}.built.after.mir create mode 100644 tests/mir-opt/coroutine/unwind_in_vec.rs diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 6b5733e87b14c..a9ca6bfef5534 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -8,7 +8,7 @@ use std::ptr::NonNull; use rustc_data_structures::intern::Interned; use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_hir::def_id::DefId; -use rustc_macros::{StableHash, TyDecodable, TyEncodable, extension}; +use rustc_macros::{Lift, StableHash, TyDecodable, TyEncodable, extension}; use rustc_serialize::{Decodable, Encodable}; use rustc_type_ir::WithCachedTypeInfo; use rustc_type_ir::walk::TypeWalker; @@ -715,7 +715,7 @@ impl<'tcx, T: TypeVisitable>> TypeVisitable> for &'tcx /// Stores the user-given args to reach some fully qualified path /// (e.g., `::Item` or `::Item`). #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(StableHash, TypeFoldable, TypeVisitable)] +#[derive(StableHash, TypeFoldable, TypeVisitable, Lift)] pub struct UserArgs<'tcx> { /// The args for the item as given by the user. pub args: GenericArgsRef<'tcx>, @@ -742,7 +742,7 @@ pub struct UserArgs<'tcx> { /// the self type, giving `Foo`. Finally, we unify that with /// the self type here, which contains `?A` to be `&'static u32` #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(StableHash, TypeFoldable, TypeVisitable)] +#[derive(StableHash, TypeFoldable, TypeVisitable, Lift)] pub struct UserSelfTy<'tcx> { pub impl_def_id: DefId, pub self_ty: Ty<'tcx>, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 03d13e6a81a6e..2d45b6feb59f0 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3418,6 +3418,29 @@ define_print_and_forward_display! { self.kind().print(p)?; } + ty::UserTypeKind<'tcx> { + match *self { + Self::Ty(ty) => { + write!(p, "Ty(")?; + ty.print(p)?; + } + Self::TypeOf(def_id, ty::UserArgs { args, user_self_ty }) => { + write!(p, "TypeOf(")?; + p.print_def_path(def_id, args)?; + if let Some(ty::UserSelfTy { impl_def_id, self_ty }) = user_self_ty { + write!(p, " at for ", key.disambiguated_data.as_sym(false))?; + self_ty.print(p)?; + write!(p, ">")?; + } + } + } + write!(p, ")")?; + } + GenericArg<'tcx> { match self.kind() { GenericArgKind::Lifetime(lt) => lt.print(p)?, diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 65a713602ed07..e11bc6d38495b 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -13,7 +13,7 @@ use rustc_hir::{ self as hir, BindingMode, ByRef, HirId, ItemLocalId, ItemLocalMap, ItemLocalSet, Mutability, }; use rustc_index::IndexVec; -use rustc_macros::{StableHash, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; +use rustc_macros::{Lift, StableHash, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_session::Session; use rustc_span::Span; @@ -798,7 +798,7 @@ impl<'tcx> UserType<'tcx> { /// from constants that are named via paths, like `Foo::::new` and /// so forth. #[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)] -#[derive(Eq, Hash, StableHash, TypeFoldable, TypeVisitable)] +#[derive(Eq, Hash, StableHash, TypeFoldable, TypeVisitable, Lift)] pub enum UserTypeKind<'tcx> { Ty(Ty<'tcx>), @@ -863,24 +863,12 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> { impl<'tcx> std::fmt::Display for UserType<'tcx> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if self.bounds.is_empty() { - self.kind.fmt(f) - } else { - self.kind.fmt(f)?; + self.kind.fmt(f)?; + for b in self.bounds { write!(f, " + ")?; - std::fmt::Debug::fmt(&self.bounds, f) - } - } -} - -impl<'tcx> std::fmt::Display for UserTypeKind<'tcx> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Ty(arg0) => { - ty::print::with_no_trimmed_paths!(write!(f, "Ty({})", arg0)) - } - Self::TypeOf(arg0, arg1) => write!(f, "TypeOf({:?}, {:?})", arg0, arg1), + b.fmt(f)?; } + Ok(()) } } diff --git a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir index 40527446e5dd5..039046198419f 100644 --- a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir @@ -2,33 +2,33 @@ | User Type Annotations | 0: user_ty: Canonical { value: Ty(*const ^c_0), max_universe: U0, var_kinds: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:8:10: 8:18, inferred_ty: *const [i32; 10] -| 1: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:10:10: 10:25, inferred_ty: *const dyn std::marker::Send +| 1: user_ty: Canonical { value: Ty(*const dyn Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:10:10: 10:25, inferred_ty: *const dyn std::marker::Send | 2: user_ty: Canonical { value: Ty(*const ^c_0), max_universe: U0, var_kinds: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10] | 3: user_ty: Canonical { value: Ty(*const ^c_0), max_universe: U0, var_kinds: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10] | 4: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, var_kinds: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10] | 5: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, var_kinds: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10] -| 6: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send -| 7: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send +| 6: user_ty: Canonical { value: Ty(*const dyn Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send +| 7: user_ty: Canonical { value: Ty(*const dyn Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send | 8: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, var_kinds: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32] | 9: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, var_kinds: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32] | 10: user_ty: Canonical { value: Ty(*const ^c_0), max_universe: U0, var_kinds: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:19:10: 19:18, inferred_ty: *const [i32; 10] -| 11: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:21:10: 21:25, inferred_ty: *const dyn std::marker::Send +| 11: user_ty: Canonical { value: Ty(*const dyn Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:21:10: 21:25, inferred_ty: *const dyn std::marker::Send | 12: user_ty: Canonical { value: Ty(*const ^c_0), max_universe: U0, var_kinds: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10] | 13: user_ty: Canonical { value: Ty(*const ^c_0), max_universe: U0, var_kinds: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10] | 14: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, var_kinds: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10] | 15: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, var_kinds: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10] -| 16: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send -| 17: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send +| 16: user_ty: Canonical { value: Ty(*const dyn Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send +| 17: user_ty: Canonical { value: Ty(*const dyn Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send | 18: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, var_kinds: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32] | 19: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, var_kinds: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32] | 20: user_ty: Canonical { value: Ty(*mut ^c_0), max_universe: U0, var_kinds: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:29:10: 29:16, inferred_ty: *mut [i32; 10] -| 21: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:31:10: 31:23, inferred_ty: *mut dyn std::marker::Send +| 21: user_ty: Canonical { value: Ty(*mut dyn Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:31:10: 31:23, inferred_ty: *mut dyn std::marker::Send | 22: user_ty: Canonical { value: Ty(*mut ^c_0), max_universe: U0, var_kinds: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10] | 23: user_ty: Canonical { value: Ty(*mut ^c_0), max_universe: U0, var_kinds: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10] | 24: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, var_kinds: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10] | 25: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, var_kinds: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10] -| 26: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send -| 27: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send +| 26: user_ty: Canonical { value: Ty(*mut dyn Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send +| 27: user_ty: Canonical { value: Ty(*mut dyn Send), max_universe: U0, var_kinds: [Region(U0)] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send | 28: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, var_kinds: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32] | 29: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, var_kinds: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32] | diff --git a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir index aa7d75242b408..af4d568c7c768 100644 --- a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir @@ -1,8 +1,8 @@ // MIR for `main` after SimplifyCfg-initial | User Type Annotations -| 0: user_ty: Canonical { value: Ty(std::option::Option>), max_universe: U0, var_kinds: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option> -| 1: user_ty: Canonical { value: Ty(std::option::Option>), max_universe: U0, var_kinds: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option> +| 0: user_ty: Canonical { value: Ty(Option>), max_universe: U0, var_kinds: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option> +| 1: user_ty: Canonical { value: Ty(Option>), max_universe: U0, var_kinds: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option> | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/building/issue_101867.main.built.after.mir b/tests/mir-opt/building/issue_101867.main.built.after.mir index f68217a497b0b..70f602aa236e8 100644 --- a/tests/mir-opt/building/issue_101867.main.built.after.mir +++ b/tests/mir-opt/building/issue_101867.main.built.after.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: Ty(std::option::Option), max_universe: U0, var_kinds: [] }, span: $DIR/issue_101867.rs:5:12: 5:22, inferred_ty: std::option::Option -| 1: user_ty: Canonical { value: Ty(std::option::Option), max_universe: U0, var_kinds: [] }, span: $DIR/issue_101867.rs:5:12: 5:22, inferred_ty: std::option::Option +| 0: user_ty: Canonical { value: Ty(Option), max_universe: U0, var_kinds: [] }, span: $DIR/issue_101867.rs:5:12: 5:22, inferred_ty: std::option::Option +| 1: user_ty: Canonical { value: Ty(Option), max_universe: U0, var_kinds: [] }, span: $DIR/issue_101867.rs:5:12: 5:22, inferred_ty: std::option::Option | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir b/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir index 8ec5028250b0d..c8c3fe6445763 100644 --- a/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir +++ b/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir @@ -1,8 +1,8 @@ // MIR for `match_assoc_const` after built | User Type Annotations -| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/user_type_annotations.rs:55:9: 55:44, inferred_ty: u32 -| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/user_type_annotations.rs:55:9: 55:44, inferred_ty: u32 +| 0: user_ty: Canonical { value: TypeOf(>::FOO), max_universe: U0, var_kinds: [] }, span: $DIR/user_type_annotations.rs:55:9: 55:44, inferred_ty: u32 +| 1: user_ty: Canonical { value: TypeOf(>::FOO), max_universe: U0, var_kinds: [] }, span: $DIR/user_type_annotations.rs:55:9: 55:44, inferred_ty: u32 | fn match_assoc_const() -> () { let mut _0: (); diff --git a/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir b/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir index 61e5d9b459d0e..0797cf0a1f8e7 100644 --- a/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir +++ b/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir @@ -1,10 +1,10 @@ // MIR for `match_assoc_const_range` after built | User Type Annotations -| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/user_type_annotations.rs:63:11: 63:46, inferred_ty: u32 -| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/user_type_annotations.rs:63:11: 63:46, inferred_ty: u32 -| 2: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/user_type_annotations.rs:64:9: 64:44, inferred_ty: u32 -| 3: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/user_type_annotations.rs:64:9: 64:44, inferred_ty: u32 +| 0: user_ty: Canonical { value: TypeOf(>::FOO), max_universe: U0, var_kinds: [] }, span: $DIR/user_type_annotations.rs:63:11: 63:46, inferred_ty: u32 +| 1: user_ty: Canonical { value: TypeOf(>::FOO), max_universe: U0, var_kinds: [] }, span: $DIR/user_type_annotations.rs:63:11: 63:46, inferred_ty: u32 +| 2: user_ty: Canonical { value: TypeOf(>::FOO), max_universe: U0, var_kinds: [] }, span: $DIR/user_type_annotations.rs:64:9: 64:44, inferred_ty: u32 +| 3: user_ty: Canonical { value: TypeOf(>::FOO), max_universe: U0, var_kinds: [] }, span: $DIR/user_type_annotations.rs:64:9: 64:44, inferred_ty: u32 | fn match_assoc_const_range() -> () { let mut _0: (); diff --git a/tests/mir-opt/coroutine/unwind_in_vec.build-{closure#0}.built.after.mir b/tests/mir-opt/coroutine/unwind_in_vec.build-{closure#0}.built.after.mir new file mode 100644 index 0000000000000..fc75f261ea01b --- /dev/null +++ b/tests/mir-opt/coroutine/unwind_in_vec.build-{closure#0}.built.after.mir @@ -0,0 +1,399 @@ +// MIR for `build::{closure#0}` after built + +| User Type Annotations +| 0: user_ty: Canonical { value: TypeOf(Box<^c_0>::new_uninit at for Box<^c_1, ^c_2>>), max_universe: U0, var_kinds: [Ty { ui: U0, sub_root: 0 }, Ty { ui: U0, sub_root: 1 }, Ty { ui: U0, sub_root: 2 }] }, span: $SRC_DIR/alloc/src/macros.rs:LL:COL, inferred_ty: fn() -> std::boxed::Box> {std::boxed::Box::<[std::string::String; 5]>::new_uninit} +| +fn build::{closure#0}(_1: {async fn body of build()}, _2: std::future::ResumeTy) -> Vec +yields () + { + debug _task_context => _2; + debug s => (_1.0: u64); + let mut _0: std::vec::Vec; + let _3: u64; + let mut _4: std::boxed::Box>; + let mut _5: std::boxed::Box>; + let mut _6: std::string::String; + let mut _7: &str; + let _8: &str; + let mut _9: std::string::String; + let mut _10: &str; + let _11: &str; + let mut _12: std::string::String; + let mut _13: &str; + let _14: &str; + let mut _15: std::string::String; + let mut _16: &str; + let _17: &str; + let mut _18: std::string::String; + let mut _19: &str; + let _20: &str; + scope 1 { + debug s => _3; + } + + bb0: { + StorageLive(_3); + _3 = copy (_1.0: u64); + FakeRead(ForLet(None), _3); + StorageLive(_4); + StorageLive(_5); + _5 = Box::<[String; 5]>::new_uninit() -> [return: bb1, unwind: bb50]; + } + + bb1: { + StorageLive(_6); + StorageLive(_7); + StorageLive(_8); + _8 = const "0"; + _7 = &(*_8); + _6 = ::to_string(move _7) -> [return: bb2, unwind: bb47]; + } + + bb2: { + StorageDead(_7); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _11 = const "1"; + _10 = &(*_11); + _9 = ::to_string(move _10) -> [return: bb3, unwind: bb43]; + } + + bb3: { + StorageDead(_10); + StorageLive(_12); + StorageLive(_13); + StorageLive(_14); + _14 = const "2"; + _13 = &(*_14); + _12 = ::to_string(move _13) -> [return: bb4, unwind: bb38]; + } + + bb4: { + StorageDead(_13); + StorageLive(_15); + StorageLive(_16); + StorageLive(_17); + _17 = const "3"; + _16 = &(*_17); + _15 = ::to_string(move _16) -> [return: bb5, unwind: bb32]; + } + + bb5: { + StorageDead(_16); + StorageLive(_18); + StorageLive(_19); + StorageLive(_20); + _20 = const "4"; + _19 = &(*_20); + _18 = ::to_string(move _19) -> [return: bb6, unwind: bb24]; + } + + bb6: { + StorageDead(_19); + ((((*_5).1: std::mem::ManuallyDrop<[std::string::String; 5]>).0: std::mem::MaybeDangling<[std::string::String; 5]>).0: [std::string::String; 5]) = [move _6, move _9, move _12, move _15, move _18]; + drop(_18) -> [return: bb7, unwind: bb25, drop: bb15]; + } + + bb7: { + StorageDead(_18); + drop(_15) -> [return: bb8, unwind: bb26, drop: bb16]; + } + + bb8: { + StorageDead(_15); + drop(_12) -> [return: bb9, unwind: bb27, drop: bb17]; + } + + bb9: { + StorageDead(_12); + drop(_9) -> [return: bb10, unwind: bb28, drop: bb18]; + } + + bb10: { + StorageDead(_9); + drop(_6) -> [return: bb11, unwind: bb29, drop: bb19]; + } + + bb11: { + StorageDead(_6); + _4 = move _5; + drop(_5) -> [return: bb12, unwind: bb22]; + } + + bb12: { + StorageDead(_5); + _0 = std::boxed::box_assume_init_into_vec_unsafe::(move _4) -> [return: bb13, unwind: bb23]; + } + + bb13: { + StorageDead(_4); + StorageDead(_20); + StorageDead(_17); + StorageDead(_14); + StorageDead(_11); + StorageDead(_8); + StorageDead(_3); + drop(_1) -> [return: bb14, unwind: bb52, drop: bb21]; + } + + bb14: { + return; + } + + bb15: { + StorageDead(_18); + drop(_15) -> [return: bb16, unwind: bb53]; + } + + bb16: { + StorageDead(_15); + drop(_12) -> [return: bb17, unwind: bb54]; + } + + bb17: { + StorageDead(_12); + drop(_9) -> [return: bb18, unwind: bb55]; + } + + bb18: { + StorageDead(_9); + drop(_6) -> [return: bb19, unwind: bb56]; + } + + bb19: { + StorageDead(_6); + drop(_5) -> [return: bb20, unwind: bb57]; + } + + bb20: { + StorageDead(_5); + StorageDead(_4); + StorageDead(_20); + StorageDead(_17); + StorageDead(_14); + StorageDead(_11); + StorageDead(_8); + StorageDead(_3); + drop(_1) -> [return: bb21, unwind: bb52]; + } + + bb21: { + coroutine_drop; + } + + bb22 (cleanup): { + StorageDead(_5); + goto -> bb23; + } + + bb23 (cleanup): { + drop(_4) -> [return: bb31, unwind terminate(cleanup)]; + } + + bb24 (cleanup): { + StorageDead(_19); + goto -> bb25; + } + + bb25 (cleanup): { + StorageDead(_18); + drop(_15) -> [return: bb26, unwind terminate(cleanup)]; + } + + bb26 (cleanup): { + StorageDead(_15); + drop(_12) -> [return: bb27, unwind terminate(cleanup)]; + } + + bb27 (cleanup): { + StorageDead(_12); + drop(_9) -> [return: bb28, unwind terminate(cleanup)]; + } + + bb28 (cleanup): { + StorageDead(_9); + drop(_6) -> [return: bb29, unwind terminate(cleanup)]; + } + + bb29 (cleanup): { + StorageDead(_6); + drop(_5) -> [return: bb30, unwind terminate(cleanup)]; + } + + bb30 (cleanup): { + StorageDead(_5); + goto -> bb31; + } + + bb31 (cleanup): { + StorageDead(_4); + StorageDead(_20); + goto -> bb37; + } + + bb32 (cleanup): { + StorageDead(_16); + StorageDead(_15); + drop(_12) -> [return: bb33, unwind terminate(cleanup)]; + } + + bb33 (cleanup): { + StorageDead(_12); + drop(_9) -> [return: bb34, unwind terminate(cleanup)]; + } + + bb34 (cleanup): { + StorageDead(_9); + drop(_6) -> [return: bb35, unwind terminate(cleanup)]; + } + + bb35 (cleanup): { + StorageDead(_6); + drop(_5) -> [return: bb36, unwind terminate(cleanup)]; + } + + bb36 (cleanup): { + StorageDead(_5); + StorageDead(_4); + goto -> bb37; + } + + bb37 (cleanup): { + StorageDead(_17); + goto -> bb42; + } + + bb38 (cleanup): { + StorageDead(_13); + StorageDead(_12); + drop(_9) -> [return: bb39, unwind terminate(cleanup)]; + } + + bb39 (cleanup): { + StorageDead(_9); + drop(_6) -> [return: bb40, unwind terminate(cleanup)]; + } + + bb40 (cleanup): { + StorageDead(_6); + drop(_5) -> [return: bb41, unwind terminate(cleanup)]; + } + + bb41 (cleanup): { + StorageDead(_5); + StorageDead(_4); + goto -> bb42; + } + + bb42 (cleanup): { + StorageDead(_14); + goto -> bb46; + } + + bb43 (cleanup): { + StorageDead(_10); + StorageDead(_9); + drop(_6) -> [return: bb44, unwind terminate(cleanup)]; + } + + bb44 (cleanup): { + StorageDead(_6); + drop(_5) -> [return: bb45, unwind terminate(cleanup)]; + } + + bb45 (cleanup): { + StorageDead(_5); + StorageDead(_4); + goto -> bb46; + } + + bb46 (cleanup): { + StorageDead(_11); + goto -> bb49; + } + + bb47 (cleanup): { + StorageDead(_7); + StorageDead(_6); + drop(_5) -> [return: bb48, unwind terminate(cleanup)]; + } + + bb48 (cleanup): { + StorageDead(_5); + StorageDead(_4); + goto -> bb49; + } + + bb49 (cleanup): { + StorageDead(_8); + goto -> bb51; + } + + bb50 (cleanup): { + StorageDead(_5); + StorageDead(_4); + goto -> bb51; + } + + bb51 (cleanup): { + StorageDead(_3); + drop(_1) -> [return: bb52, unwind terminate(cleanup)]; + } + + bb52 (cleanup): { + resume; + } + + bb53 (cleanup): { + StorageDead(_15); + drop(_12) -> [return: bb54, unwind terminate(cleanup)]; + } + + bb54 (cleanup): { + StorageDead(_12); + drop(_9) -> [return: bb55, unwind terminate(cleanup)]; + } + + bb55 (cleanup): { + StorageDead(_9); + drop(_6) -> [return: bb56, unwind terminate(cleanup)]; + } + + bb56 (cleanup): { + StorageDead(_6); + drop(_5) -> [return: bb57, unwind terminate(cleanup)]; + } + + bb57 (cleanup): { + StorageDead(_5); + StorageDead(_4); + StorageDead(_20); + StorageDead(_17); + StorageDead(_14); + StorageDead(_11); + StorageDead(_8); + StorageDead(_3); + drop(_1) -> [return: bb52, unwind terminate(cleanup)]; + } +} + +ALLOC0 (size: 1, align: 1) { + 34 │ 4 +} + +ALLOC1 (size: 1, align: 1) { + 33 │ 3 +} + +ALLOC2 (size: 1, align: 1) { + 32 │ 2 +} + +ALLOC3 (size: 1, align: 1) { + 31 │ 1 +} + +ALLOC4 (size: 1, align: 1) { + 30 │ 0 +} diff --git a/tests/mir-opt/coroutine/unwind_in_vec.rs b/tests/mir-opt/coroutine/unwind_in_vec.rs new file mode 100644 index 0000000000000..46389c91d9abc --- /dev/null +++ b/tests/mir-opt/coroutine/unwind_in_vec.rs @@ -0,0 +1,10 @@ +// Regression test for #154720 +//@ edition: 2018 +//@ needs-unwind +//@ skip-filecheck + +// EMIT_MIR unwind_in_vec.build-{closure#0}.built.after.mir +#[inline(never)] +pub async fn build(s: u64) -> Vec { + vec!["0".to_string(), "1".to_string(), "2".to_string(), "3".to_string(), "4".to_string()] +} diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir index 4a028248d6633..ea20caa3ca2c7 100644 --- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [AliasConst(No, Alias { kind: Anon { def_id: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}) }, args: [], .. })], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 0: user_ty: Canonical { value: TypeOf(function_with_bytes<&*b"AAAA">), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(function_with_bytes<{ &[0x41, 0x41, 0x41, 0x41] }>), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir index 4a028248d6633..ea20caa3ca2c7 100644 --- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [AliasConst(No, Alias { kind: Anon { def_id: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}) }, args: [], .. })], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 0: user_ty: Canonical { value: TypeOf(function_with_bytes<&*b"AAAA">), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(function_with_bytes<{ &[0x41, 0x41, 0x41, 0x41] }>), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); From 393f1f27b9118e3a1721362ee406ee67d990fa31 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Thu, 9 Jul 2026 23:06:20 +0200 Subject: [PATCH 04/13] enable `do_not_recommend` attr for method call errors in current solver --- compiler/rustc_hir_typeck/src/method/probe.rs | 8 +++++- .../method_call.current.stderr | 26 ++++--------------- .../do_not_recommend/method_call.rs | 10 +++---- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index ce22ab937391e..8d51f7d101d8b 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1886,7 +1886,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ) -> traits::SelectionResult<'tcx, traits::Selection<'tcx>> { let obligation = traits::Obligation::new(self.tcx, self.misc(self.span), self.param_env, trait_ref); - traits::SelectionContext::new(self).select(&obligation) + let candidate = traits::SelectionContext::new(self).select(&obligation); + if let Ok(Some(traits::ImplSource::UserDefined(impl_source_user_defined_data))) = &candidate + && self.infcx.tcx.do_not_recommend_impl(impl_source_user_defined_data.impl_def_id) + { + return Err(traits::SelectionError::Unimplemented); + } + candidate } /// Used for ambiguous method call error reporting. Uses probing that throws away the result internally, diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/method_call.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/method_call.current.stderr index 0fd90fae5e6fd..625d5b6ea5ab5 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/method_call.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/method_call.current.stderr @@ -4,20 +4,11 @@ error[E0277]: the trait bound `ForeignType: Clone` is not satisfied LL | let _ = Clone::clone(&f); | ^^ the trait `Clone` is not implemented for `ForeignType` -error[E0599]: the method `clone` exists for struct `ForeignType`, but its trait bounds were not satisfied +error[E0599]: no method named `clone` found for struct `ForeignType` in the current scope --> $DIR/method_call.rs:24:19 | LL | let _ = f.clone(); - | ^^^^^ method cannot be called on `ForeignType` due to unsatisfied trait bounds - | - ::: $DIR/auxiliary/foreign_blanket_impl.rs:1:1 - | -LL | pub struct ForeignType(pub T); - | ------------------------- doesn't satisfy `ForeignType: Clone` - | - = note: the following trait bounds were not satisfied: - `u8: DoNotMentionThis` - which is required by `ForeignType: Clone` + | ^^^^^ method not found in `ForeignType` error[E0277]: the trait bound `LocalType: Clone` is not satisfied --> $DIR/method_call.rs:31:30 @@ -31,22 +22,15 @@ LL + #[derive(Clone)] LL | pub struct LocalType(pub T); | -error[E0599]: the method `clone` exists for struct `LocalType`, but its trait bounds were not satisfied +error[E0599]: no method named `clone` found for struct `LocalType` in the current scope --> $DIR/method_call.rs:34:19 | LL | pub struct LocalType(pub T); - | ----------------------- method `clone` not found for this struct because it doesn't satisfy `LocalType: Clone` + | ----------------------- method `clone` not found for this struct ... LL | let _ = l.clone(); - | ^^^^^ method cannot be called on `LocalType` due to unsatisfied trait bounds - | -note: trait bound `u8: DoNotMentionThis` was not satisfied - --> $DIR/method_call.rs:12:9 + | ^^^^^ method not found in `LocalType` | -LL | impl Clone for LocalType { - | ^^^^^^^^^^^^^^^^ ----- ------------ - | | - | unsatisfied trait bound introduced here = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `Clone` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/method_call.rs b/tests/ui/diagnostic_namespace/do_not_recommend/method_call.rs index 2b10cacd30227..c28c86fae209a 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/method_call.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/method_call.rs @@ -2,7 +2,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver - +//@forbid-output: DoNotMentionThis extern crate foreign_blanket_impl; use foreign_blanket_impl::{DoNotMentionThis, ForeignType}; @@ -22,8 +22,8 @@ fn main() { //~^ERROR the trait bound `ForeignType: Clone` is not satisfied [E0277] let _ = f.clone(); - //[next]~^ERROR no method named `clone` found for struct `ForeignType` in the current scope [E0599] - //[current]~^^ERROR the method `clone` exists for struct `ForeignType`, but its trait bounds were not satisfied [E0599] + //~^ERROR no method named `clone` found for struct `ForeignType` in the current scope [E0599] + } { @@ -32,7 +32,7 @@ fn main() { //~^ERROR the trait bound `LocalType: Clone` is not satisfied [E0277] let _ = l.clone(); - //[next]~^ERROR no method named `clone` found for struct `LocalType` in the current scope [E0599] - //[current]~^^ERROR the method `clone` exists for struct `LocalType`, but its trait bounds were not satisfied [E0599] + //~^ERROR no method named `clone` found for struct `LocalType` in the current scope [E0599] + } } From 08d79a6ec93089cf3f7c5a1db239b5f7371a12dc Mon Sep 17 00:00:00 2001 From: Amirhossein Akhlaghpour Date: Fri, 10 Jul 2026 14:28:39 +0330 Subject: [PATCH 05/13] chore: add codegen test for issue 91010 Signed-off-by: Amirhossein Akhlaghpour --- tests/codegen-llvm/issues/issue-91010.rs | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/codegen-llvm/issues/issue-91010.rs diff --git a/tests/codegen-llvm/issues/issue-91010.rs b/tests/codegen-llvm/issues/issue-91010.rs new file mode 100644 index 0000000000000..0b1b2526ca1cd --- /dev/null +++ b/tests/codegen-llvm/issues/issue-91010.rs @@ -0,0 +1,28 @@ +// Regression test for preserving constant return values after a use of the +// same local through `black_box` or formatting. + +//@ compile-flags: -Copt-level=3 + +#![crate_type = "lib"] + +use std::hint::black_box; + +// CHECK-LABEL: @black_box_ref_constant +#[no_mangle] +pub fn black_box_ref_constant() -> i32 { + let x = 1; + black_box(&x); + + // CHECK: ret i32 1 + x +} + +// CHECK-LABEL: @format_ref_constant +#[no_mangle] +pub fn format_ref_constant() -> i32 { + let x = 1; + println!("{}", x); + + // CHECK: ret i32 1 + x +} From 77bce37c6503f032cdce56ae8a5b30eb4f018c54 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sat, 11 Jul 2026 13:56:19 +0200 Subject: [PATCH 06/13] Rename `select_trait_candidate` --- compiler/rustc_hir_typeck/src/method/probe.rs | 8 +++++--- .../diagnostic_namespace/do_not_recommend/method_call.rs | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 8d51f7d101d8b..d071e0625a398 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1880,7 +1880,7 @@ impl<'tcx> Pick<'tcx> { } impl<'a, 'tcx> ProbeContext<'a, 'tcx> { - fn select_trait_candidate( + fn select_trait_candidate_for_diagnostics( &self, trait_ref: ty::TraitRef<'tcx>, ) -> traits::SelectionResult<'tcx, traits::Selection<'tcx>> { @@ -1920,7 +1920,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { xform_self_ty, self_ty, ); - match self.select_trait_candidate(trait_ref) { + match self.select_trait_candidate_for_diagnostics(trait_ref) { Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => { // If only a single impl matches, make the error message point // to that impl. @@ -2089,7 +2089,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ocx.register_obligation(obligation); } else { result = ProbeResult::NoMatch; - if let Ok(Some(candidate)) = self.select_trait_candidate(trait_ref) { + if let Ok(Some(candidate)) = + self.select_trait_candidate_for_diagnostics(trait_ref) + { for nested_obligation in candidate.nested_obligations() { if !self.infcx.predicate_may_hold(&nested_obligation) { possibly_unsatisfied_predicates.push(( diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/method_call.rs b/tests/ui/diagnostic_namespace/do_not_recommend/method_call.rs index c28c86fae209a..5f59984a6ddd9 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/method_call.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/method_call.rs @@ -33,6 +33,6 @@ fn main() { let _ = l.clone(); //~^ERROR no method named `clone` found for struct `LocalType` in the current scope [E0599] - + } } From e8f64cc4f6b881bf7784537b9af937d6dffc43bd Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 12 Jul 2026 12:39:39 +0900 Subject: [PATCH 07/13] rustc_target: Add acquire-release to implied features of v8 --- compiler/rustc_target/src/target_features.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 611bf5950d27d..8c1ebee8416e5 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -194,7 +194,7 @@ static ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("v6m", Unstable(sym::arm_target_feature), &["v6"]), ("v6t2", Unstable(sym::arm_target_feature), &["v6k", "v8m", "thumb2"]), ("v7", Unstable(sym::arm_target_feature), &["v6t2"]), - ("v8", Unstable(sym::arm_target_feature), &["v7"]), + ("v8", Unstable(sym::arm_target_feature), &["v7", "acquire-release"]), ("v8.1m.main", Unstable(sym::arm_target_feature), &["v8m.main"]), ("v8m", Unstable(sym::arm_target_feature), &["v6m"]), ("v8m.main", Unstable(sym::arm_target_feature), &["v7"]), From c6748782afce501b8f3a8ba1c83165ebf1320f91 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 13 Jul 2026 16:10:59 +1000 Subject: [PATCH 08/13] Add a case to the `multiple-tail-expr-behind-cfg.rs` test This demonstrates the `if cfg!(..)` suggestion being applied wrongly, when a `cfg` attribute is followed by a non-`cfg` attribute. --- .../multiple-tail-expr-behind-cfg.rs | 7 +++++ .../multiple-tail-expr-behind-cfg.stderr | 29 ++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs index 371f19d487268..fcf0dcf478444 100644 --- a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs +++ b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs @@ -14,6 +14,13 @@ fn bar() -> String { String::new() } +fn baz() -> String { + #[cfg(false)] + [1, 2, 3].iter().map(|c| c.to_string()).collect::() //~ ERROR expected `;`, found `#` + #[allow(unused)] + String::new() +} + fn main() { println!("{}", foo()); } diff --git a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr index 3a97a14b3c301..f5bbb78882687 100644 --- a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr +++ b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr @@ -44,11 +44,38 @@ help: alternatively, consider surrounding the expression with a block LL | { [1, 2, 3].iter().map(|c| c.to_string()).collect::() } | + + +error: expected `;`, found `#` + --> $DIR/multiple-tail-expr-behind-cfg.rs:19:64 + | +LL | #[cfg(false)] + | ------------- only `;` terminated statements or tail expressions are allowed after this attribute +LL | [1, 2, 3].iter().map(|c| c.to_string()).collect::() + | ^ expected `;` here +LL | #[allow(unused)] + | - unexpected token + | +help: add `;` here + | +LL | [1, 2, 3].iter().map(|c| c.to_string()).collect::(); + | + +help: alternatively, consider surrounding the expression with a block + | +LL | { [1, 2, 3].iter().map(|c| c.to_string()).collect::() } + | + + +help: it seems like you are trying to provide different expressions depending on `cfg`, consider using `if cfg!(..)` + | +LL ~ if cfg!(false) { +LL ~ [1, 2, 3].iter().map(|c| c.to_string()).collect::() +LL ~ } else if cfg!(unused) { +LL ~ String::new() +LL + } + | + error: cannot find attribute `attr` in this scope --> $DIR/multiple-tail-expr-behind-cfg.rs:13:7 | LL | #[attr] | ^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors From 895538515599db58b843620d251d5b977d09dcc9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 13 Jul 2026 15:55:44 +1000 Subject: [PATCH 09/13] Fix typo in `attr_on_non_tail_expr` The line `&& segment.ident.name == sym::cfg` duplicates a line from just a few lines above in the same if-let chain. It's clear from context that the `segment` is a copy/paste error and should be `next_segment`. This fixes the erroneous suggestion given for `multiple-tail-expr-behind-cfg.rs`. --- compiler/rustc_parse/src/parser/diagnostics.rs | 2 +- .../parser/attribute/multiple-tail-expr-behind-cfg.stderr | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 254e7e410f579..a4f0f5610081d 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -873,7 +873,7 @@ impl<'a> Parser<'a> { && let ast::AttrKind::Normal(next_attr_kind) = next_attr.kind && let Some(next_attr_args_span) = next_attr_kind.item.args.span() && let [next_segment] = &next_attr_kind.item.path.segments[..] - && segment.ident.name == sym::cfg + && next_segment.ident.name == sym::cfg { let next_expr = match snapshot.parse_expr() { Ok(next_expr) => next_expr, diff --git a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr index f5bbb78882687..c8f3d50edd103 100644 --- a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr +++ b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr @@ -62,14 +62,6 @@ help: alternatively, consider surrounding the expression with a block | LL | { [1, 2, 3].iter().map(|c| c.to_string()).collect::() } | + + -help: it seems like you are trying to provide different expressions depending on `cfg`, consider using `if cfg!(..)` - | -LL ~ if cfg!(false) { -LL ~ [1, 2, 3].iter().map(|c| c.to_string()).collect::() -LL ~ } else if cfg!(unused) { -LL ~ String::new() -LL + } - | error: cannot find attribute `attr` in this scope --> $DIR/multiple-tail-expr-behind-cfg.rs:13:7 From 5a5d1305fdc5256dbbfab7f536a4703df2ceb923 Mon Sep 17 00:00:00 2001 From: qaijuang <237468078+qaijuang@users.noreply.github.com> Date: Sat, 6 Jun 2026 01:36:14 -0400 Subject: [PATCH 10/13] add regression tests --- ...suggestion-path-156244.edition_2015.stderr | 67 ++++++++++++++++++- ...suggestion-path-156244.edition_2018.stderr | 67 ++++++++++++++++++- .../private-import-suggestion-path-156244.rs | 38 +++++++++++ 3 files changed, 170 insertions(+), 2 deletions(-) diff --git a/tests/ui/imports/private-import-suggestion-path-156244.edition_2015.stderr b/tests/ui/imports/private-import-suggestion-path-156244.edition_2015.stderr index 95b1760e6a239..aa531667c03ad 100644 --- a/tests/ui/imports/private-import-suggestion-path-156244.edition_2015.stderr +++ b/tests/ui/imports/private-import-suggestion-path-156244.edition_2015.stderr @@ -76,6 +76,71 @@ LL - use crate::rename::inner::Item as Item1; LL + use outer::actual::Item as Item1; | -error: aborting due to 4 previous errors +error[E0603]: struct import `Hi` is private + --> $DIR/private-import-suggestion-path-156244.rs:51:14 + | +LL | use testing::Hi; + | ^^ private struct import + | +note: the struct import `Hi` is defined here... + --> $DIR/private-import-suggestion-path-156244.rs:48:9 + | +LL | use super::public::Hi; + | ^^^^^^^^^^^^^^^^^ +note: ...and refers to the struct `Hi` which is defined here + --> $DIR/private-import-suggestion-path-156244.rs:44:5 + | +LL | pub struct Hi; + | ^^^^^^^^^^^^^^ you could import this directly +help: import `Hi` directly + | +LL - use testing::Hi; +LL + use super::public::Hi; + | + +error[E0603]: struct import `Hi` is private + --> $DIR/private-import-suggestion-path-156244.rs:67:37 + | +LL | use inaccessible_ancestor::testing::Hi; + | ^^ private struct import + | +note: the struct import `Hi` is defined here... + --> $DIR/private-import-suggestion-path-156244.rs:63:13 + | +LL | use super::private::public::Hi; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...and refers to the struct `Hi` which is defined here + --> $DIR/private-import-suggestion-path-156244.rs:58:13 + | +LL | pub struct Hi; + | ^^^^^^^^^^^^^^ you could import this directly +help: import `Hi` directly + | +LL - use inaccessible_ancestor::testing::Hi; +LL + use super::private::public::Hi; + | + +error[E0603]: module import `mem` is private + --> $DIR/private-import-suggestion-path-156244.rs:77:21 + | +LL | use external_alias::mem; + | ^^^ private module import + | +note: the module import `mem` is defined here... + --> $DIR/private-import-suggestion-path-156244.rs:74:9 + | +LL | use super::s::mem; + | ^^^^^^^^^^^^^ +note: ...and refers to the module `mem` which is defined here + --> $SRC_DIR/std/src/lib.rs:LL:COL + | + = note: you could import this directly +help: import `mem` directly + | +LL - use external_alias::mem; +LL + use core::mem; + | + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/private-import-suggestion-path-156244.edition_2018.stderr b/tests/ui/imports/private-import-suggestion-path-156244.edition_2018.stderr index e153b0cdc95aa..20b0c198830e0 100644 --- a/tests/ui/imports/private-import-suggestion-path-156244.edition_2018.stderr +++ b/tests/ui/imports/private-import-suggestion-path-156244.edition_2018.stderr @@ -76,6 +76,71 @@ LL - use crate::rename::inner::Item as Item1; LL + use crate::outer::actual::Item as Item1; | -error: aborting due to 4 previous errors +error[E0603]: struct import `Hi` is private + --> $DIR/private-import-suggestion-path-156244.rs:51:14 + | +LL | use testing::Hi; + | ^^ private struct import + | +note: the struct import `Hi` is defined here... + --> $DIR/private-import-suggestion-path-156244.rs:48:9 + | +LL | use super::public::Hi; + | ^^^^^^^^^^^^^^^^^ +note: ...and refers to the struct `Hi` which is defined here + --> $DIR/private-import-suggestion-path-156244.rs:44:5 + | +LL | pub struct Hi; + | ^^^^^^^^^^^^^^ you could import this directly +help: import `Hi` directly + | +LL - use testing::Hi; +LL + use super::public::Hi; + | + +error[E0603]: struct import `Hi` is private + --> $DIR/private-import-suggestion-path-156244.rs:67:37 + | +LL | use inaccessible_ancestor::testing::Hi; + | ^^ private struct import + | +note: the struct import `Hi` is defined here... + --> $DIR/private-import-suggestion-path-156244.rs:63:13 + | +LL | use super::private::public::Hi; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...and refers to the struct `Hi` which is defined here + --> $DIR/private-import-suggestion-path-156244.rs:58:13 + | +LL | pub struct Hi; + | ^^^^^^^^^^^^^^ you could import this directly +help: import `Hi` directly + | +LL - use inaccessible_ancestor::testing::Hi; +LL + use super::private::public::Hi; + | + +error[E0603]: module import `mem` is private + --> $DIR/private-import-suggestion-path-156244.rs:77:21 + | +LL | use external_alias::mem; + | ^^^ private module import + | +note: the module import `mem` is defined here... + --> $DIR/private-import-suggestion-path-156244.rs:74:9 + | +LL | use super::s::mem; + | ^^^^^^^^^^^^^ +note: ...and refers to the module `mem` which is defined here + --> $SRC_DIR/std/src/lib.rs:LL:COL + | + = note: you could import this directly +help: import `mem` directly + | +LL - use external_alias::mem; +LL + use core::mem; + | + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/private-import-suggestion-path-156244.rs b/tests/ui/imports/private-import-suggestion-path-156244.rs index 3f9d247097f7d..8732564920720 100644 --- a/tests/ui/imports/private-import-suggestion-path-156244.rs +++ b/tests/ui/imports/private-import-suggestion-path-156244.rs @@ -39,4 +39,42 @@ mod bad { //~^ ERROR module import `inner` is private [E0603] } +// Regression test for https://github.com/rust-lang/rust/issues/157455: no root `super`. +mod public { + pub struct Hi; +} + +mod testing { + use super::public::Hi; +} + +use testing::Hi; +//~^ ERROR struct import `Hi` is private [E0603] + +// Regression test for https://github.com/rust-lang/rust/issues/157455: no private ancestors. +mod inaccessible_ancestor { + mod private { + pub mod public { + pub struct Hi; + } + } + + pub mod testing { + use super::private::public::Hi; + } +} + +use inaccessible_ancestor::testing::Hi; +//~^ ERROR struct import `Hi` is private [E0603] + +// Regression test for https://github.com/rust-lang/rust/issues/157455: no external alias rewrite. +use std as s; + +mod external_alias { + use super::s::mem; +} + +use external_alias::mem; +//~^ ERROR module import `mem` is private [E0603] + fn main() {} From 6be6d756605c5f7e0de39981afc11cf1b5cf44a2 Mon Sep 17 00:00:00 2001 From: qaijuang <237468078+qaijuang@users.noreply.github.com> Date: Sat, 6 Jun 2026 02:59:55 -0400 Subject: [PATCH 11/13] fix relative paths in private import suggestions --- .../rustc_resolve/src/diagnostics/impls.rs | 99 +++++++++++++++++-- ...suggestion-path-156244.edition_2015.stderr | 7 +- ...suggestion-path-156244.edition_2018.stderr | 7 +- 3 files changed, 91 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index ab8554f2652ee..800f4f1e482c3 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -2668,17 +2668,96 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { match binding.kind { DeclKind::Import { source_decl, import, .. } => { - // Don't include `{{root}}` in suggestions - it's an internal symbol - // that should never be shown to users. - let path = import - .module_path - .iter() - .filter(|seg| seg.ident.name != kw::PathRoot) - .map(|seg| seg.ident.clone()) - .chain(std::iter::once(ident)) - .collect::>(); let through_reexport = !matches!(source_decl.kind, DeclKind::Def(_)); - sugg_paths.push((path, through_reexport)); + let uses_relative_path = import + .module_path + .first() + .is_some_and(|seg| matches!(seg.ident.name, kw::SelfLower | kw::Super)); + let res_def_id = res.opt_def_id(); + let path = if uses_relative_path { + // A path recovered from `self`/`super` is only useful if both the + // target and every module segment can be named from the failing use site. + let module_path = if let Some(ModuleOrUniformRoot::Module(module)) = + import.imported_module.get() + && module.is_local() + && let Some(module_path) = self.module_path_names(module) + && let Some(mut def_id) = module.opt_def_id() + && res_def_id.is_none_or(|def_id| { + self.is_accessible_from( + self.tcx.visibility(def_id), + parent_scope.module, + ) + }) { + // `module_path_names` tells us the resolved module's canonical path. + // Before suggesting that path from the failing use site, make sure + // every segment in it can actually be named from there. + let mut visible_from_use_site = true; + while let Some(parent) = self.tcx.opt_parent(def_id) { + if !self.is_accessible_from( + self.tcx.visibility(def_id), + parent_scope.module, + ) { + visible_from_use_site = false; + break; + } + if parent.is_top_level_module() { + break; + } + def_id = parent; + } + if visible_from_use_site { Some(module_path) } else { None } + } else { + None + }; + + if let Some(module_path) = module_path { + // `import.module_path` is relative to the import's module, not to the + // failing use site. + let mut suggestion = ImportSuggestion { + did: res_def_id, + descr: "", + path: Path { + span: ident.span, + segments: module_path + .into_iter() + .chain(std::iter::once(ident.name)) + .map(|name| { + ast::PathSegment::from_ident(Ident::with_dummy_span( + name, + )) + }) + .collect(), + tokens: None, + }, + accessible: true, + doc_visible: true, + via_import: false, + note: None, + is_stable: true, + }; + // Reuse the existing relative shortening policy. The fields above + // other than `did` and `path` are not used by this helper. + self.shorten_candidate_path(&mut suggestion, parent_scope.module); + Some(suggestion.path.segments.iter().map(|seg| seg.ident).collect()) + } else { + None + } + } else { + // Don't include `{{root}}` in suggestions - it's an internal symbol + // that should never be shown to users. + Some( + import + .module_path + .iter() + .filter(|seg| seg.ident.name != kw::PathRoot) + .map(|seg| seg.ident.clone()) + .chain(std::iter::once(ident)) + .collect::>(), + ) + }; + if let Some(path) = path { + sugg_paths.push((path, through_reexport)); + } } DeclKind::Def(_) => {} } diff --git a/tests/ui/imports/private-import-suggestion-path-156244.edition_2015.stderr b/tests/ui/imports/private-import-suggestion-path-156244.edition_2015.stderr index aa531667c03ad..9e51641447f89 100644 --- a/tests/ui/imports/private-import-suggestion-path-156244.edition_2015.stderr +++ b/tests/ui/imports/private-import-suggestion-path-156244.edition_2015.stderr @@ -95,7 +95,7 @@ LL | pub struct Hi; help: import `Hi` directly | LL - use testing::Hi; -LL + use super::public::Hi; +LL + use public::Hi; | error[E0603]: struct import `Hi` is private @@ -114,11 +114,6 @@ note: ...and refers to the struct `Hi` which is defined here | LL | pub struct Hi; | ^^^^^^^^^^^^^^ you could import this directly -help: import `Hi` directly - | -LL - use inaccessible_ancestor::testing::Hi; -LL + use super::private::public::Hi; - | error[E0603]: module import `mem` is private --> $DIR/private-import-suggestion-path-156244.rs:77:21 diff --git a/tests/ui/imports/private-import-suggestion-path-156244.edition_2018.stderr b/tests/ui/imports/private-import-suggestion-path-156244.edition_2018.stderr index 20b0c198830e0..c1f059a09d4d9 100644 --- a/tests/ui/imports/private-import-suggestion-path-156244.edition_2018.stderr +++ b/tests/ui/imports/private-import-suggestion-path-156244.edition_2018.stderr @@ -95,7 +95,7 @@ LL | pub struct Hi; help: import `Hi` directly | LL - use testing::Hi; -LL + use super::public::Hi; +LL + use public::Hi; | error[E0603]: struct import `Hi` is private @@ -114,11 +114,6 @@ note: ...and refers to the struct `Hi` which is defined here | LL | pub struct Hi; | ^^^^^^^^^^^^^^ you could import this directly -help: import `Hi` directly - | -LL - use inaccessible_ancestor::testing::Hi; -LL + use super::private::public::Hi; - | error[E0603]: module import `mem` is private --> $DIR/private-import-suggestion-path-156244.rs:77:21 From 59a09407e01949c4bca2fd5a312f15e33d763681 Mon Sep 17 00:00:00 2001 From: qaijuang <237468078+qaijuang@users.noreply.github.com> Date: Fri, 10 Jul 2026 20:33:40 -0400 Subject: [PATCH 12/13] address suggested nits --- .../rustc_resolve/src/diagnostics/impls.rs | 71 ++++++++----------- 1 file changed, 30 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 800f4f1e482c3..b56e1263c17c8 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -2433,18 +2433,27 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Some(path) } - /// Shortens a candidate import path to use `super::` (up to 1 level) or `self::` (same module) - /// relative to the current scope, if possible. Only applies to crate-local items and - /// only when the resulting path is actually shorter than the original. fn shorten_candidate_path( &self, suggestion: &mut ImportSuggestion, current_module: Module<'ra>, + ) { + self.shorten_import_path(suggestion.did, &mut suggestion.path, current_module); + } + + /// Shortens an import path to use `super::` (up to 1 level) or `self::` (same module) + /// relative to the current scope, if possible. Only applies to crate-local items and + /// only when the resulting path is actually shorter than the original. + fn shorten_import_path( + &self, + did: Option, + path: &mut Path, + current_module: Module<'ra>, ) { const MAX_SUPER_PATH_ITEMS_IN_SUGGESTION: usize = 1; // Only shorten local items. - if suggestion.did.is_none_or(|did| !did.is_local()) { + if did.is_none_or(|did| !did.is_local()) { return; } @@ -2457,12 +2466,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // doesn't start with `Crate`, prepend it (edition 2015 paths are relative // to the crate root without an explicit `crate::` prefix). let candidate_names = { - let filtered_segments: Vec<_> = suggestion - .path - .segments - .iter() - .filter(|segment| segment.ident.name != kw::PathRoot) - .collect(); + let filtered_segments: Vec<_> = + path.segments.iter().filter(|segment| segment.ident.name != kw::PathRoot).collect(); let mut candidate_names: Vec = filtered_segments.iter().map(|segment| segment.ident.name).collect(); @@ -2511,11 +2516,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // Only apply if the result is strictly shorter than the original path. - if new_segments.len() >= suggestion.path.segments.len() { + if new_segments.len() >= path.segments.len() { return; } - suggestion.path = Path { span: suggestion.path.span, segments: new_segments }; + *path = Path { span: path.span, segments: new_segments }; } fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) { @@ -2710,38 +2715,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None }; - if let Some(module_path) = module_path { + module_path.map(|module_path| { // `import.module_path` is relative to the import's module, not to the // failing use site. - let mut suggestion = ImportSuggestion { - did: res_def_id, - descr: "", - path: Path { - span: ident.span, - segments: module_path - .into_iter() - .chain(std::iter::once(ident.name)) - .map(|name| { - ast::PathSegment::from_ident(Ident::with_dummy_span( - name, - )) - }) - .collect(), - tokens: None, - }, - accessible: true, - doc_visible: true, - via_import: false, - note: None, - is_stable: true, + let mut path = Path { + span: ident.span, + segments: module_path + .into_iter() + .chain(std::iter::once(ident.name)) + .map(|name| { + ast::PathSegment::from_ident(Ident::with_dummy_span(name)) + }) + .collect(), }; - // Reuse the existing relative shortening policy. The fields above - // other than `did` and `path` are not used by this helper. - self.shorten_candidate_path(&mut suggestion, parent_scope.module); - Some(suggestion.path.segments.iter().map(|seg| seg.ident).collect()) - } else { - None - } + self.shorten_import_path(res_def_id, &mut path, parent_scope.module); + path.segments.iter().map(|seg| seg.ident).collect() + }) } else { // Don't include `{{root}}` in suggestions - it's an internal symbol // that should never be shown to users. From db1ab0b18facd9cd231d2a2fbcf625d7817b021d Mon Sep 17 00:00:00 2001 From: qaijuang <237468078+qaijuang@users.noreply.github.com> Date: Fri, 10 Jul 2026 20:33:54 -0400 Subject: [PATCH 13/13] split only rustfix eligible test --- ...suggestion-path-156244.edition_2015.stderr | 34 ++++--------------- ...suggestion-path-156244.edition_2018.stderr | 34 ++++--------------- .../private-import-suggestion-path-156244.rs | 12 ------- .../private-import-suggestion-relative.fixed | 17 ++++++++++ .../private-import-suggestion-relative.rs | 17 ++++++++++ .../private-import-suggestion-relative.stderr | 25 ++++++++++++++ 6 files changed, 71 insertions(+), 68 deletions(-) create mode 100644 tests/ui/imports/private-import-suggestion-relative.fixed create mode 100644 tests/ui/imports/private-import-suggestion-relative.rs create mode 100644 tests/ui/imports/private-import-suggestion-relative.stderr diff --git a/tests/ui/imports/private-import-suggestion-path-156244.edition_2015.stderr b/tests/ui/imports/private-import-suggestion-path-156244.edition_2015.stderr index 9e51641447f89..2a8795b6ab93c 100644 --- a/tests/ui/imports/private-import-suggestion-path-156244.edition_2015.stderr +++ b/tests/ui/imports/private-import-suggestion-path-156244.edition_2015.stderr @@ -77,52 +77,30 @@ LL + use outer::actual::Item as Item1; | error[E0603]: struct import `Hi` is private - --> $DIR/private-import-suggestion-path-156244.rs:51:14 - | -LL | use testing::Hi; - | ^^ private struct import - | -note: the struct import `Hi` is defined here... - --> $DIR/private-import-suggestion-path-156244.rs:48:9 - | -LL | use super::public::Hi; - | ^^^^^^^^^^^^^^^^^ -note: ...and refers to the struct `Hi` which is defined here - --> $DIR/private-import-suggestion-path-156244.rs:44:5 - | -LL | pub struct Hi; - | ^^^^^^^^^^^^^^ you could import this directly -help: import `Hi` directly - | -LL - use testing::Hi; -LL + use public::Hi; - | - -error[E0603]: struct import `Hi` is private - --> $DIR/private-import-suggestion-path-156244.rs:67:37 + --> $DIR/private-import-suggestion-path-156244.rs:55:37 | LL | use inaccessible_ancestor::testing::Hi; | ^^ private struct import | note: the struct import `Hi` is defined here... - --> $DIR/private-import-suggestion-path-156244.rs:63:13 + --> $DIR/private-import-suggestion-path-156244.rs:51:13 | LL | use super::private::public::Hi; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...and refers to the struct `Hi` which is defined here - --> $DIR/private-import-suggestion-path-156244.rs:58:13 + --> $DIR/private-import-suggestion-path-156244.rs:46:13 | LL | pub struct Hi; | ^^^^^^^^^^^^^^ you could import this directly error[E0603]: module import `mem` is private - --> $DIR/private-import-suggestion-path-156244.rs:77:21 + --> $DIR/private-import-suggestion-path-156244.rs:65:21 | LL | use external_alias::mem; | ^^^ private module import | note: the module import `mem` is defined here... - --> $DIR/private-import-suggestion-path-156244.rs:74:9 + --> $DIR/private-import-suggestion-path-156244.rs:62:9 | LL | use super::s::mem; | ^^^^^^^^^^^^^ @@ -136,6 +114,6 @@ LL - use external_alias::mem; LL + use core::mem; | -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/private-import-suggestion-path-156244.edition_2018.stderr b/tests/ui/imports/private-import-suggestion-path-156244.edition_2018.stderr index c1f059a09d4d9..9f112fe4e7551 100644 --- a/tests/ui/imports/private-import-suggestion-path-156244.edition_2018.stderr +++ b/tests/ui/imports/private-import-suggestion-path-156244.edition_2018.stderr @@ -77,52 +77,30 @@ LL + use crate::outer::actual::Item as Item1; | error[E0603]: struct import `Hi` is private - --> $DIR/private-import-suggestion-path-156244.rs:51:14 - | -LL | use testing::Hi; - | ^^ private struct import - | -note: the struct import `Hi` is defined here... - --> $DIR/private-import-suggestion-path-156244.rs:48:9 - | -LL | use super::public::Hi; - | ^^^^^^^^^^^^^^^^^ -note: ...and refers to the struct `Hi` which is defined here - --> $DIR/private-import-suggestion-path-156244.rs:44:5 - | -LL | pub struct Hi; - | ^^^^^^^^^^^^^^ you could import this directly -help: import `Hi` directly - | -LL - use testing::Hi; -LL + use public::Hi; - | - -error[E0603]: struct import `Hi` is private - --> $DIR/private-import-suggestion-path-156244.rs:67:37 + --> $DIR/private-import-suggestion-path-156244.rs:55:37 | LL | use inaccessible_ancestor::testing::Hi; | ^^ private struct import | note: the struct import `Hi` is defined here... - --> $DIR/private-import-suggestion-path-156244.rs:63:13 + --> $DIR/private-import-suggestion-path-156244.rs:51:13 | LL | use super::private::public::Hi; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...and refers to the struct `Hi` which is defined here - --> $DIR/private-import-suggestion-path-156244.rs:58:13 + --> $DIR/private-import-suggestion-path-156244.rs:46:13 | LL | pub struct Hi; | ^^^^^^^^^^^^^^ you could import this directly error[E0603]: module import `mem` is private - --> $DIR/private-import-suggestion-path-156244.rs:77:21 + --> $DIR/private-import-suggestion-path-156244.rs:65:21 | LL | use external_alias::mem; | ^^^ private module import | note: the module import `mem` is defined here... - --> $DIR/private-import-suggestion-path-156244.rs:74:9 + --> $DIR/private-import-suggestion-path-156244.rs:62:9 | LL | use super::s::mem; | ^^^^^^^^^^^^^ @@ -136,6 +114,6 @@ LL - use external_alias::mem; LL + use core::mem; | -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/private-import-suggestion-path-156244.rs b/tests/ui/imports/private-import-suggestion-path-156244.rs index 8732564920720..71e01470060bf 100644 --- a/tests/ui/imports/private-import-suggestion-path-156244.rs +++ b/tests/ui/imports/private-import-suggestion-path-156244.rs @@ -39,18 +39,6 @@ mod bad { //~^ ERROR module import `inner` is private [E0603] } -// Regression test for https://github.com/rust-lang/rust/issues/157455: no root `super`. -mod public { - pub struct Hi; -} - -mod testing { - use super::public::Hi; -} - -use testing::Hi; -//~^ ERROR struct import `Hi` is private [E0603] - // Regression test for https://github.com/rust-lang/rust/issues/157455: no private ancestors. mod inaccessible_ancestor { mod private { diff --git a/tests/ui/imports/private-import-suggestion-relative.fixed b/tests/ui/imports/private-import-suggestion-relative.fixed new file mode 100644 index 0000000000000..52579f0a08eb7 --- /dev/null +++ b/tests/ui/imports/private-import-suggestion-relative.fixed @@ -0,0 +1,17 @@ +//@ run-rustfix + +#![allow(unused)] + +// Regression test for https://github.com/rust-lang/rust/issues/157455. +mod public { + pub struct Hi; +} + +mod testing { + use super::public::Hi; +} + +use public::Hi; +//~^ ERROR struct import `Hi` is private [E0603] + +fn main() {} diff --git a/tests/ui/imports/private-import-suggestion-relative.rs b/tests/ui/imports/private-import-suggestion-relative.rs new file mode 100644 index 0000000000000..9a012e8252879 --- /dev/null +++ b/tests/ui/imports/private-import-suggestion-relative.rs @@ -0,0 +1,17 @@ +//@ run-rustfix + +#![allow(unused)] + +// Regression test for https://github.com/rust-lang/rust/issues/157455. +mod public { + pub struct Hi; +} + +mod testing { + use super::public::Hi; +} + +use testing::Hi; +//~^ ERROR struct import `Hi` is private [E0603] + +fn main() {} diff --git a/tests/ui/imports/private-import-suggestion-relative.stderr b/tests/ui/imports/private-import-suggestion-relative.stderr new file mode 100644 index 0000000000000..033351e27c3c5 --- /dev/null +++ b/tests/ui/imports/private-import-suggestion-relative.stderr @@ -0,0 +1,25 @@ +error[E0603]: struct import `Hi` is private + --> $DIR/private-import-suggestion-relative.rs:14:14 + | +LL | use testing::Hi; + | ^^ private struct import + | +note: the struct import `Hi` is defined here... + --> $DIR/private-import-suggestion-relative.rs:11:9 + | +LL | use super::public::Hi; + | ^^^^^^^^^^^^^^^^^ +note: ...and refers to the struct `Hi` which is defined here + --> $DIR/private-import-suggestion-relative.rs:7:5 + | +LL | pub struct Hi; + | ^^^^^^^^^^^^^^ you could import this directly +help: import `Hi` directly + | +LL - use testing::Hi; +LL + use public::Hi; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0603`.