From aeaec5bdaab455ffc69969a79990cce9b0c1be32 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 4 Sep 2025 17:52:39 +0200 Subject: [PATCH 1/6] rarw --- .../src/hir_ty_lowering/bounds.rs | 4 +- compiler/rustc_session/src/options.rs | 2 +- library/alloc/src/boxed.rs | 8 ++- library/alloc/src/lib.rs | 1 + library/alloctests/tests/lib.rs | 1 + library/core/src/cell.rs | 21 ++++---- library/core/src/marker.rs | 25 +++++++-- library/core/src/ops/unsize.rs | 54 +++++++++++++------ library/core/src/panic/unwind_safe.rs | 2 +- library/core/src/pin.rs | 4 +- library/core/src/pin/unsafe_pinned.rs | 8 +-- library/core/src/ptr/non_null.rs | 13 +++-- library/core/src/ptr/unique.rs | 9 ++-- library/coretests/tests/lib.rs | 1 + library/std/src/lib.rs | 1 + 15 files changed, 107 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 99dc8e6e52217..3da8d8c7236ca 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -231,7 +231,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - /// Adds `experimental_default_bounds` bounds to the supertrait bounds. + /// Sets `experimental_default_bounds` to true on trait super bounds. pub(crate) fn add_default_super_traits( &self, trait_def_id: LocalDefId, @@ -242,8 +242,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) { assert_matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias); - // Supertraits for auto trait are unsound according to the unstable book: - // https://doc.rust-lang.org/beta/unstable-book/language-features/auto-traits.html#supertraits if self.tcx().trait_is_auto(trait_def_id.to_def_id()) { return; } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 69facde693689..ea5b187080e8a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2307,7 +2307,7 @@ options! { "Use WebAssembly error handling for wasm32-unknown-emscripten"), enforce_type_length_limit: bool = (false, parse_bool, [TRACKED], "enforce the type length limit when monomorphizing instances in codegen"), - experimental_default_bounds: bool = (false, parse_bool, [TRACKED], + experimental_default_bounds: bool = (true, parse_bool, [TRACKED], "enable default bounds for experimental group of auto traits"), export_executable_symbols: bool = (false, parse_bool, [TRACKED], "export symbols from executables, as if they were dynamic libraries"), diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 98c9f6b51ab86..28826913a877f 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2039,7 +2039,10 @@ unsafe impl PinCoerceUnsized for Box {} // Handling arbitrary custom allocators (which can affect the `Box` layout heavily!) // would need a lot of codegen and interpreter adjustments. #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U: ?Sized> DispatchFromDyn> for Box {} +impl + ?core::marker::Move, U: ?Sized + ?core::marker::Move> + DispatchFromDyn> for Box +{ +} #[stable(feature = "box_borrow", since = "1.1.0")] impl Borrow for Box { @@ -2141,3 +2144,6 @@ impl Error for Box { Error::provide(&**self, request); } } + +#[unstable(feature = "move_trait", issue = "none")] +unsafe impl core::marker::Move for Box {} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index cba1ce40f75d5..f03492069cc86 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -133,6 +133,7 @@ #![feature(local_waker)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array_transpose)] +#![feature(move_trait)] #![feature(panic_internals)] #![feature(pattern)] #![feature(pin_coerce_unsized_trait)] diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index bf446ae1ba42b..ae16d70e5443f 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -13,6 +13,7 @@ #![feature(int_format_into)] #![feature(linked_list_cursors)] #![feature(map_try_insert)] +#![feature(move_trait)] #![feature(pattern)] #![feature(trusted_len)] #![feature(try_reserve_kind)] diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 9b53b75ebee80..9562b6523f7e7 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -252,7 +252,7 @@ use crate::cmp::Ordering; use crate::fmt::{self, Debug, Display}; -use crate::marker::{PhantomData, Unsize}; +use crate::marker::{Move, PhantomData, Unsize}; use crate::mem; use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; use crate::panic::const_panic; @@ -309,7 +309,7 @@ pub use once::OnceCell; #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] #[rustc_pub_transparent] -pub struct Cell { +pub struct Cell { value: UnsafeCell, } @@ -322,7 +322,7 @@ unsafe impl Send for Cell where T: Send {} // having an explicit negative impl is nice for documentation purposes // and results in nicer error messages. #[stable(feature = "rust1", since = "1.0.0")] -impl !Sync for Cell {} +impl !Sync for Cell {} #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Cell { @@ -669,7 +669,7 @@ impl, U> CoerceUnsized> for Cell {} // `self: Cell<&Self>` won't work // `self: CellWrapper` becomes possible #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U> DispatchFromDyn> for Cell {} +impl + ?Move, U: ?Move> DispatchFromDyn> for Cell {} impl Cell<[T]> { /// Returns a `&[Cell]` from a `&Cell<[T]>` @@ -2185,12 +2185,12 @@ impl fmt::Display for RefMut<'_, T> { #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] #[rustc_pub_transparent] -pub struct UnsafeCell { +pub struct UnsafeCell { value: T, } #[stable(feature = "rust1", since = "1.0.0")] -impl !Sync for UnsafeCell {} +impl !Sync for UnsafeCell {} impl UnsafeCell { /// Constructs a new instance of `UnsafeCell` which will wrap the specified @@ -2455,7 +2455,7 @@ impl, U> CoerceUnsized> for UnsafeCell {} // `self: UnsafeCell<&Self>` won't work // `self: UnsafeCellWrapper` becomes possible #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U> DispatchFromDyn> for UnsafeCell {} +impl + ?Move, U: ?Move> DispatchFromDyn> for UnsafeCell {} /// [`UnsafeCell`], but [`Sync`]. /// @@ -2473,7 +2473,7 @@ impl, U> DispatchFromDyn> for UnsafeCell #[repr(transparent)] #[rustc_diagnostic_item = "SyncUnsafeCell"] #[rustc_pub_transparent] -pub struct SyncUnsafeCell { +pub struct SyncUnsafeCell { value: UnsafeCell, } @@ -2563,7 +2563,10 @@ impl, U> CoerceUnsized> for SyncUnsafeCell // `self: SyncUnsafeCellWrapper` becomes possible #[unstable(feature = "dispatch_from_dyn", issue = "none")] //#[unstable(feature = "sync_unsafe_cell", issue = "95439")] -impl, U> DispatchFromDyn> for SyncUnsafeCell {} +impl + ?Move, U: ?Move> DispatchFromDyn> + for SyncUnsafeCell +{ +} #[allow(unused)] fn assert_coerce_unsized( diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index d03d7a43469a7..e0b39546f3b2f 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -236,7 +236,7 @@ pub trait PointeeSized { #[lang = "unsize"] #[rustc_deny_explicit_impl] #[rustc_do_not_implement_via_object] -pub trait Unsize: PointeeSized { +pub trait Unsize: PointeeSized { // Empty. } @@ -819,7 +819,7 @@ impl !Sync for *mut T {} /// [drop check]: Drop#drop-check #[lang = "phantom_data"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct PhantomData; +pub struct PhantomData; #[stable(feature = "rust1", since = "1.0.0")] impl Hash for PhantomData { @@ -913,7 +913,7 @@ pub trait DiscriminantKind { pub unsafe auto trait Freeze {} #[unstable(feature = "freeze", issue = "121675")] -impl !Freeze for UnsafeCell {} +impl !Freeze for UnsafeCell {} marker_impls! { #[unstable(feature = "freeze", issue = "121675")] unsafe Freeze for @@ -933,7 +933,7 @@ marker_impls! { #[lang = "unsafe_unpin"] pub(crate) unsafe auto trait UnsafeUnpin {} -impl !UnsafeUnpin for UnsafePinned {} +impl !UnsafeUnpin for UnsafePinned {} unsafe impl UnsafeUnpin for PhantomData {} unsafe impl UnsafeUnpin for *const T {} unsafe impl UnsafeUnpin for *mut T {} @@ -1372,3 +1372,20 @@ pub trait CoercePointeeValidated { pub trait Reborrow { // Empty. } + +/// Types that do not require a stable memory address, and so can be freely +/// `move`d. +#[lang = "default_trait1"] +#[rustc_unsafe_specialization_marker] +#[unstable(feature = "move_trait", issue = "none")] +pub unsafe auto trait Move { + // empty. +} +marker_impls! { + #[unstable(feature = "move_trait", issue = "none")] + unsafe Move for + {T: ?Sized + PointeeSized} *const T, + {T: ?Sized + PointeeSized} *mut T, + {T: ?Sized + PointeeSized} &T, + {T: ?Sized + PointeeSized} &mut T, +} diff --git a/library/core/src/ops/unsize.rs b/library/core/src/ops/unsize.rs index f0781ee01fd53..6ba0bd7fdd320 100644 --- a/library/core/src/ops/unsize.rs +++ b/library/core/src/ops/unsize.rs @@ -1,4 +1,4 @@ -use crate::marker::{PointeeSized, Unsize}; +use crate::marker::{Move, PointeeSized, Unsize}; /// Trait that indicates that this is a pointer or a wrapper for one, /// where unsizing can be performed on the pointee. @@ -39,34 +39,46 @@ pub trait CoerceUnsized { // &mut T -> &mut U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<&'a mut U> for &'a mut T {} +impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<&'a mut U> + for &'a mut T +{ +} // &mut T -> &U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, 'b: 'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<&'a U> for &'b mut T {} +impl<'a, 'b: 'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<&'a U> + for &'b mut T +{ +} // &mut T -> *mut U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<*mut U> for &'a mut T {} +impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<*mut U> for &'a mut T {} // &mut T -> *const U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<*const U> for &'a mut T {} +impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<*const U> + for &'a mut T +{ +} // &T -> &U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, 'b: 'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<&'a U> for &'b T {} +impl<'a, 'b: 'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<&'a U> + for &'b T +{ +} // &T -> *const U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl<'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<*const U> for &'a T {} +impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized> CoerceUnsized<*const U> for &'a T {} // *mut T -> *mut U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl, U: PointeeSized> CoerceUnsized<*mut U> for *mut T {} +impl, U: PointeeSized> CoerceUnsized<*mut U> for *mut T {} // *mut T -> *const U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl, U: PointeeSized> CoerceUnsized<*const U> for *mut T {} +impl, U: PointeeSized> CoerceUnsized<*const U> for *mut T {} // *const T -> *const U #[unstable(feature = "coerce_unsized", issue = "18598")] -impl, U: PointeeSized> CoerceUnsized<*const U> for *const T {} +impl, U: PointeeSized> CoerceUnsized<*const U> for *const T {} /// `DispatchFromDyn` is used in the implementation of dyn-compatibility[^1] checks (specifically /// allowing arbitrary self types), to guarantee that a method's receiver type can be dispatched on. @@ -116,19 +128,31 @@ impl, U: PointeeSized> CoerceUnsized<*const U> for * /// [^1]: Formerly known as *object safety*. #[unstable(feature = "dispatch_from_dyn", issue = "none")] #[lang = "dispatch_from_dyn"] -pub trait DispatchFromDyn { +pub trait DispatchFromDyn { // Empty. } // &T -> &U #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl<'a, T: PointeeSized + Unsize, U: PointeeSized> DispatchFromDyn<&'a U> for &'a T {} +impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized + ?Move> DispatchFromDyn<&'a U> + for &'a T +{ +} // &mut T -> &mut U #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl<'a, T: PointeeSized + Unsize, U: PointeeSized> DispatchFromDyn<&'a mut U> for &'a mut T {} +impl<'a, T: PointeeSized + ?Move + Unsize, U: PointeeSized + ?Move> DispatchFromDyn<&'a mut U> + for &'a mut T +{ +} // *const T -> *const U #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U: PointeeSized> DispatchFromDyn<*const U> for *const T {} +impl, U: PointeeSized + ?Move> DispatchFromDyn<*const U> + for *const T +{ +} // *mut T -> *mut U #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl, U: PointeeSized> DispatchFromDyn<*mut U> for *mut T {} +impl, U: PointeeSized + ?Move> DispatchFromDyn<*mut U> + for *mut T +{ +} diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index 722af55103839..72047f5c55d34 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -197,7 +197,7 @@ impl UnwindSafe for AssertUnwindSafe {} // only thing which doesn't implement it (which then transitively applies to // everything else). #[stable(feature = "catch_unwind", since = "1.9.0")] -impl !RefUnwindSafe for UnsafeCell {} +impl !RefUnwindSafe for UnsafeCell {} #[stable(feature = "catch_unwind", since = "1.9.0")] impl RefUnwindSafe for AssertUnwindSafe {} diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 535830f2e749f..d021f921f8182 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1091,7 +1091,7 @@ pub use self::unsafe_pinned::UnsafePinned; #[repr(transparent)] #[rustc_pub_transparent] #[derive(Copy, Clone)] -pub struct Pin { +pub struct Pin { pointer: Ptr, } @@ -1741,7 +1741,7 @@ where impl DispatchFromDyn> for Pin where Ptr: DispatchFromDyn + PinCoerceUnsized, - U: PinCoerceUnsized, + U: PinCoerceUnsized + ?crate::marker::Move, { } diff --git a/library/core/src/pin/unsafe_pinned.rs b/library/core/src/pin/unsafe_pinned.rs index ae03809b4581f..9fd419b7aa01f 100644 --- a/library/core/src/pin/unsafe_pinned.rs +++ b/library/core/src/pin/unsafe_pinned.rs @@ -1,5 +1,5 @@ use crate::cell::UnsafeCell; -use crate::marker::Unpin; +use crate::marker::{Move, Unpin}; use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::pin::Pin; use crate::{fmt, ptr}; @@ -24,7 +24,7 @@ use crate::{fmt, ptr}; #[lang = "unsafe_pinned"] #[repr(transparent)] #[unstable(feature = "unsafe_pinned", issue = "125735")] -pub struct UnsafePinned { +pub struct UnsafePinned { value: UnsafeCell, } @@ -36,7 +36,7 @@ unsafe impl Sync for UnsafePinned {} /// aliases from becoming invalidated. Therefore let's mark this as `!Unpin`. You can always opt /// back in to `Unpin` with an `impl` block, provided your API is still sound while unpinned. #[unstable(feature = "unsafe_pinned", issue = "125735")] -impl !Unpin for UnsafePinned {} +impl !Unpin for UnsafePinned {} // `Send` and `Sync` are inherited from `T`. This is similar to `SyncUnsafeCell`, since // we eventually concluded that `UnsafeCell` implicitly making things `!Sync` is sometimes @@ -177,6 +177,6 @@ impl, U> CoerceUnsized> for UnsafePinned // FIXME(unsafe_pinned) this logic is copied from UnsafeCell, is it still sound? #[unstable(feature = "dispatch_from_dyn", issue = "none")] // #[unstable(feature = "unsafe_pinned", issue = "125735")] -impl, U> DispatchFromDyn> for UnsafePinned {} +impl, U: ?Move> DispatchFromDyn> for UnsafePinned {} // FIXME(unsafe_pinned): impl PinCoerceUnsized for UnsafePinned? diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 10f83120428b9..94e4b1ac45a00 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1,3 +1,5 @@ +use core::marker::Move; + use crate::cmp::Ordering; use crate::marker::{PointeeSized, Unsize}; use crate::mem::{MaybeUninit, SizedTypeProperties}; @@ -72,7 +74,7 @@ use crate::{fmt, hash, intrinsics, mem, ptr}; #[rustc_layout_scalar_valid_range_start(1)] #[rustc_nonnull_optimization_guaranteed] #[rustc_diagnostic_item = "NonNull"] -pub struct NonNull { +pub struct NonNull { // Remember to use `.as_ptr()` instead of `.pointer`, as field projecting to // this is banned by . pointer: *const T, @@ -81,12 +83,12 @@ pub struct NonNull { /// `NonNull` pointers are not `Send` because the data they reference may be aliased. // N.B., this impl is unnecessary, but should provide better error messages. #[stable(feature = "nonnull", since = "1.25.0")] -impl !Send for NonNull {} +impl !Send for NonNull {} /// `NonNull` pointers are not `Sync` because the data they reference may be aliased. // N.B., this impl is unnecessary, but should provide better error messages. #[stable(feature = "nonnull", since = "1.25.0")] -impl !Sync for NonNull {} +impl !Sync for NonNull {} impl NonNull { /// Creates a pointer with the given address and no [provenance][crate::ptr#provenance]. @@ -1653,7 +1655,10 @@ impl Copy for NonNull {} impl CoerceUnsized> for NonNull where T: Unsize {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl DispatchFromDyn> for NonNull where T: Unsize {} +impl DispatchFromDyn> for NonNull where + T: Unsize +{ +} #[stable(feature = "pin", since = "1.33.0")] unsafe impl PinCoerceUnsized for NonNull {} diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index cdc8b6cc936df..554810540c0ac 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -1,5 +1,5 @@ use crate::fmt; -use crate::marker::{PhantomData, PointeeSized, Unsize}; +use crate::marker::{Move, PhantomData, PointeeSized, Unsize}; use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::pin::PinCoerceUnsized; use crate::ptr::NonNull; @@ -32,7 +32,7 @@ use crate::ptr::NonNull; )] #[doc(hidden)] #[repr(transparent)] -pub struct Unique { +pub struct Unique { pointer: NonNull, // NOTE: this marker has no consequences for variance, but is necessary // for dropck to understand that we logically own a `T`. @@ -169,7 +169,10 @@ impl Copy for Unique {} impl CoerceUnsized> for Unique where T: Unsize {} #[unstable(feature = "ptr_internals", issue = "none")] -impl DispatchFromDyn> for Unique where T: Unsize {} +impl DispatchFromDyn> for Unique where + T: Unsize +{ +} #[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] unsafe impl PinCoerceUnsized for Unique {} diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 1bdaa6965f64a..c3d35cf69d3d7 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -77,6 +77,7 @@ #![feature(maybe_uninit_uninit_array_transpose)] #![feature(maybe_uninit_write_slice)] #![feature(min_specialization)] +#![feature(move_trait)] #![feature(never_type)] #![feature(next_index)] #![feature(non_exhaustive_omitted_patterns_lint)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 97db0d6ab7513..14f98e2b381cb 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -359,6 +359,7 @@ #![feature(lazy_get)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_write_slice)] +#![feature(move_trait)] #![feature(panic_can_unwind)] #![feature(panic_internals)] #![feature(pin_coerce_unsized_trait)] From 319f0b2091aa661484789f665a13b7d73e64dca8 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 12 Sep 2025 10:10:11 +0200 Subject: [PATCH 2/6] w --- .../src/traits/select/mod.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 1dd31990ab73e..ac5dc56004523 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -474,7 +474,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } else { let has_non_region_infer = stack.obligation.predicate.has_non_region_infer(); - if let Some(candidate) = self.winnow_candidates(has_non_region_infer, candidates) { + let is_default_auto_trait = self + .tcx() + .as_lang_item(stack.obligation.predicate.def_id()) + .is_some_and(|lang_item| matches!(lang_item, LangItem::DefaultTrait1)); + if let Some(candidate) = + self.winnow_candidates(has_non_region_infer, is_default_auto_trait, candidates) + { self.filter_reservation_impls(candidate) } else { Ok(None) @@ -1821,6 +1827,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { fn winnow_candidates( &mut self, has_non_region_infer: bool, + is_default_auto_trait: bool, mut candidates: Vec>, ) -> Option> { if candidates.len() == 1 { @@ -1828,8 +1835,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } // We prefer `Sized` candidates over everything. - let mut sized_candidates = - candidates.iter().filter(|c| matches!(c.candidate, SizedCandidate)); + let mut sized_candidates = candidates.iter().filter(|c| { + matches!(c.candidate, SizedCandidate) + || (is_default_auto_trait + && matches!(c.candidate, AutoImplCandidate | ImplCandidate(..))) + }); if let Some(sized_candidate) = sized_candidates.next() { // There should only ever be a single sized candidate // as they would otherwise overlap. From 4a71036d24e37cb6e490d0e654d67553d1405d5b Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 12 Sep 2025 10:21:30 +0200 Subject: [PATCH 3/6] yeet, compiler impls --- compiler/rustc_data_structures/src/marker.rs | 37 ++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index 2be9ba292f976..fa7ba80e53dc5 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -1,5 +1,7 @@ use std::alloc::Allocator; use std::marker::PointeeSized; +#[cfg(not(bootstrap))] +use std::marker::Move; #[diagnostic::on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \ Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`")] @@ -25,6 +27,7 @@ macro_rules! impls_dyn_send_neg { } // Consistent with `std` +#[cfg(bootstrap)] impls_dyn_send_neg!( [std::env::Args] [std::env::ArgsOs] @@ -40,6 +43,22 @@ impls_dyn_send_neg!( [std::io::StderrLock<'_>] ); +#[cfg(not(bootstrap))] +impls_dyn_send_neg!( + [std::env::Args] + [std::env::ArgsOs] + [*const T where T: ?Sized + ?Move + PointeeSized] + [*mut T where T: ?Sized + ?Move + PointeeSized] + [std::ptr::NonNull where T: ?Sized + ?Move + PointeeSized] + [std::rc::Rc where T: ?Sized + ?Move, A: Allocator] + [std::rc::Weak where T: ?Sized + ?Move, A: Allocator] + [std::sync::MutexGuard<'_, T> where T: ?Sized + ?Move] + [std::sync::RwLockReadGuard<'_, T> where T: ?Sized + ?Move] + [std::sync::RwLockWriteGuard<'_, T> where T: ?Sized + ?Move] + [std::io::StdoutLock<'_>] + [std::io::StderrLock<'_>] +); + #[cfg(any( unix, target_os = "hermit", @@ -98,6 +117,7 @@ macro_rules! impls_dyn_sync_neg { } // Consistent with `std` +#[cfg(bootstrap)] impls_dyn_sync_neg!( [std::env::Args] [std::env::ArgsOs] @@ -114,6 +134,23 @@ impls_dyn_sync_neg!( [std::sync::mpsc::Sender where T] ); +#[cfg(not(bootstrap))] +impls_dyn_sync_neg!( + [std::env::Args] + [std::env::ArgsOs] + [*const T where T: ?Sized + ?Move + PointeeSized] + [*mut T where T: ?Sized + ?Move + PointeeSized] + [std::cell::Cell where T: ?Sized + ?Move ] + [std::cell::RefCell where T: ?Sized + ?Move ] + [std::cell::UnsafeCell where T: ?Sized + ?Move ] + [std::ptr::NonNull where T: ?Sized + ?Move + PointeeSized] + [std::rc::Rc where T: ?Sized + ?Move , A: Allocator] + [std::rc::Weak where T: ?Sized + ?Move , A: Allocator] + [std::cell::OnceCell where T] + [std::sync::mpsc::Receiver where T] + [std::sync::mpsc::Sender where T] +); + #[cfg(any( unix, target_os = "hermit", From 9a38230f54a9983bd142ede8067808b803489905 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 12 Sep 2025 10:35:20 +0200 Subject: [PATCH 4/6] nyaaaaaaa --- compiler/rustc_data_structures/src/lib.rs | 1 + compiler/rustc_middle/src/ty/context.rs | 1 + .../rustc_trait_selection/src/traits/select/mod.rs | 14 ++++++++++++++ library/core/src/marker.rs | 8 ++++---- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 17da3ea83c819..0812a661c4e1c 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -10,6 +10,7 @@ #![allow(internal_features)] #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] +#![cfg_attr(not(bootstrap), feature(move_trait))] #![deny(unsafe_op_in_unsafe_fn)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 218ac2cfbc19d..43527e9f59b59 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1506,6 +1506,7 @@ unsafe impl DynSync for TyCtxt<'_> {} fn _assert_tcx_fields() { sync::assert_dyn_sync::<&'_ GlobalCtxt<'_>>(); sync::assert_dyn_send::<&'_ GlobalCtxt<'_>>(); + } impl<'tcx> Deref for TyCtxt<'tcx> { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index ac5dc56004523..a9606d4bc3b69 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1884,6 +1884,20 @@ impl<'tcx> SelectionContext<'_, 'tcx> { break; } + if is_default_auto_trait { + // Need to prefer alias-bound over env candidates. + let alias_bound = candidates + .iter() + .filter_map(|c| if let ProjectionCandidate(i) = c.candidate { Some(i) } else { None }) + .try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) }); + match alias_bound { + Some(Some(index)) => return Some(ProjectionCandidate(index)), + Some(None) => {} + None => return None, + } + + } + // The next highest priority is for non-global where-bounds. However, while we don't // prefer global where-clauses here, we do bail with ambiguity when encountering both // a global and a non-global where-clause. diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index e0b39546f3b2f..edcdfec09b113 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1384,8 +1384,8 @@ pub unsafe auto trait Move { marker_impls! { #[unstable(feature = "move_trait", issue = "none")] unsafe Move for - {T: ?Sized + PointeeSized} *const T, - {T: ?Sized + PointeeSized} *mut T, - {T: ?Sized + PointeeSized} &T, - {T: ?Sized + PointeeSized} &mut T, + {T: ?Sized + PointeeSized + ?Move} *const T, + {T: ?Sized + PointeeSized + ?Move} *mut T, + {T: ?Sized + PointeeSized + ?Move} &T, + {T: ?Sized + PointeeSized + ?Move} &mut T, } From f257881fe78f7e830a2d7eac0b1de60bc8239029 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 12 Sep 2025 10:35:30 +0200 Subject: [PATCH 5/6] fmt --- compiler/rustc_data_structures/src/marker.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 1 - compiler/rustc_trait_selection/src/traits/select/mod.rs | 5 +++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index fa7ba80e53dc5..b806bac07989e 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -1,7 +1,7 @@ use std::alloc::Allocator; -use std::marker::PointeeSized; #[cfg(not(bootstrap))] use std::marker::Move; +use std::marker::PointeeSized; #[diagnostic::on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \ Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`")] diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 43527e9f59b59..218ac2cfbc19d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1506,7 +1506,6 @@ unsafe impl DynSync for TyCtxt<'_> {} fn _assert_tcx_fields() { sync::assert_dyn_sync::<&'_ GlobalCtxt<'_>>(); sync::assert_dyn_send::<&'_ GlobalCtxt<'_>>(); - } impl<'tcx> Deref for TyCtxt<'tcx> { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a9606d4bc3b69..773203053cca5 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1888,14 +1888,15 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // Need to prefer alias-bound over env candidates. let alias_bound = candidates .iter() - .filter_map(|c| if let ProjectionCandidate(i) = c.candidate { Some(i) } else { None }) + .filter_map( + |c| if let ProjectionCandidate(i) = c.candidate { Some(i) } else { None }, + ) .try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) }); match alias_bound { Some(Some(index)) => return Some(ProjectionCandidate(index)), Some(None) => {} None => return None, } - } // The next highest priority is for non-global where-bounds. However, while we don't From 851064fdde9869b589528ecd2d780730c714b83c Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 12 Sep 2025 11:16:55 +0200 Subject: [PATCH 6/6] w --- library/core/src/marker.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index edcdfec09b113..acb0ba36ee382 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1388,4 +1388,5 @@ marker_impls! { {T: ?Sized + PointeeSized + ?Move} *mut T, {T: ?Sized + PointeeSized + ?Move} &T, {T: ?Sized + PointeeSized + ?Move} &mut T, + {T: ?Sized + PointeeSized + ?Move} PhantomData, }