Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_data_structures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
37 changes: 37 additions & 0 deletions compiler/rustc_data_structures/src/marker.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use std::alloc::Allocator;
#[cfg(not(bootstrap))]
use std::marker::Move;
use std::marker::PointeeSized;

#[diagnostic::on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \
Expand All @@ -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]
Expand All @@ -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<T> where T: ?Sized + ?Move + PointeeSized]
[std::rc::Rc<T, A> where T: ?Sized + ?Move, A: Allocator]
[std::rc::Weak<T, A> 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",
Expand Down Expand Up @@ -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]
Expand All @@ -114,6 +134,23 @@ impls_dyn_sync_neg!(
[std::sync::mpsc::Sender<T> 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<T> where T: ?Sized + ?Move ]
[std::cell::RefCell<T> where T: ?Sized + ?Move ]
[std::cell::UnsafeCell<T> where T: ?Sized + ?Move ]
[std::ptr::NonNull<T> where T: ?Sized + ?Move + PointeeSized]
[std::rc::Rc<T, A> where T: ?Sized + ?Move , A: Allocator]
[std::rc::Weak<T, A> where T: ?Sized + ?Move , A: Allocator]
[std::cell::OnceCell<T> where T]
[std::sync::mpsc::Receiver<T> where T]
[std::sync::mpsc::Sender<T> where T]
);

#[cfg(any(
unix,
target_os = "hermit",
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down
31 changes: 28 additions & 3 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -1821,15 +1827,19 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
fn winnow_candidates(
&mut self,
has_non_region_infer: bool,
is_default_auto_trait: bool,
mut candidates: Vec<EvaluatedCandidate<'tcx>>,
) -> Option<SelectionCandidate<'tcx>> {
if candidates.len() == 1 {
return Some(candidates.pop().unwrap().candidate);
}

// 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.
Expand Down Expand Up @@ -1874,6 +1884,21 @@ 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.
Expand Down
8 changes: 7 additions & 1 deletion library/alloc/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2039,7 +2039,10 @@ unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Box<T, A> {}
// 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<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T, Global> {}
impl<T: ?Sized + Unsize<U> + ?core::marker::Move, U: ?Sized + ?core::marker::Move>
DispatchFromDyn<Box<U>> for Box<T, Global>
{
}

#[stable(feature = "box_borrow", since = "1.1.0")]
impl<T: ?Sized, A: Allocator> Borrow<T> for Box<T, A> {
Expand Down Expand Up @@ -2141,3 +2144,6 @@ impl<E: Error> Error for Box<E> {
Error::provide(&**self, request);
}
}

#[unstable(feature = "move_trait", issue = "none")]
unsafe impl<T: ?Sized + ?core::marker::Move, A: Allocator> core::marker::Move for Box<T, A> {}
1 change: 1 addition & 0 deletions library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
1 change: 1 addition & 0 deletions library/alloctests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
21 changes: 12 additions & 9 deletions library/core/src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -309,7 +309,7 @@ pub use once::OnceCell;
#[stable(feature = "rust1", since = "1.0.0")]
#[repr(transparent)]
#[rustc_pub_transparent]
pub struct Cell<T: ?Sized> {
pub struct Cell<T: ?Sized + ?Move> {
value: UnsafeCell<T>,
}

Expand All @@ -322,7 +322,7 @@ unsafe impl<T: ?Sized> Send for Cell<T> 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<T: ?Sized> !Sync for Cell<T> {}
impl<T: ?Sized + ?Move> !Sync for Cell<T> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Copy> Clone for Cell<T> {
Expand Down Expand Up @@ -669,7 +669,7 @@ impl<T: CoerceUnsized<U>, U> CoerceUnsized<Cell<U>> for Cell<T> {}
// `self: Cell<&Self>` won't work
// `self: CellWrapper<Self>` becomes possible
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Cell<U>> for Cell<T> {}
impl<T: DispatchFromDyn<U> + ?Move, U: ?Move> DispatchFromDyn<Cell<U>> for Cell<T> {}

impl<T> Cell<[T]> {
/// Returns a `&[Cell<T>]` from a `&Cell<[T]>`
Expand Down Expand Up @@ -2185,12 +2185,12 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
#[stable(feature = "rust1", since = "1.0.0")]
#[repr(transparent)]
#[rustc_pub_transparent]
pub struct UnsafeCell<T: ?Sized> {
pub struct UnsafeCell<T: ?Sized + ?Move> {
value: T,
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> !Sync for UnsafeCell<T> {}
impl<T: ?Sized + ?Move> !Sync for UnsafeCell<T> {}

impl<T> UnsafeCell<T> {
/// Constructs a new instance of `UnsafeCell` which will wrap the specified
Expand Down Expand Up @@ -2455,7 +2455,7 @@ impl<T: CoerceUnsized<U>, U> CoerceUnsized<UnsafeCell<U>> for UnsafeCell<T> {}
// `self: UnsafeCell<&Self>` won't work
// `self: UnsafeCellWrapper<Self>` becomes possible
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<UnsafeCell<U>> for UnsafeCell<T> {}
impl<T: DispatchFromDyn<U> + ?Move, U: ?Move> DispatchFromDyn<UnsafeCell<U>> for UnsafeCell<T> {}

/// [`UnsafeCell`], but [`Sync`].
///
Expand All @@ -2473,7 +2473,7 @@ impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<UnsafeCell<U>> for UnsafeCell<T>
#[repr(transparent)]
#[rustc_diagnostic_item = "SyncUnsafeCell"]
#[rustc_pub_transparent]
pub struct SyncUnsafeCell<T: ?Sized> {
pub struct SyncUnsafeCell<T: ?Sized + ?Move> {
value: UnsafeCell<T>,
}

Expand Down Expand Up @@ -2563,7 +2563,10 @@ impl<T: CoerceUnsized<U>, U> CoerceUnsized<SyncUnsafeCell<U>> for SyncUnsafeCell
// `self: SyncUnsafeCellWrapper<Self>` becomes possible
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
//#[unstable(feature = "sync_unsafe_cell", issue = "95439")]
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<SyncUnsafeCell<U>> for SyncUnsafeCell<T> {}
impl<T: DispatchFromDyn<U> + ?Move, U: ?Move> DispatchFromDyn<SyncUnsafeCell<U>>
for SyncUnsafeCell<T>
{
}

#[allow(unused)]
fn assert_coerce_unsized(
Expand Down
26 changes: 22 additions & 4 deletions library/core/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ pub trait PointeeSized {
#[lang = "unsize"]
#[rustc_deny_explicit_impl]
#[rustc_do_not_implement_via_object]
pub trait Unsize<T: PointeeSized>: PointeeSized {
pub trait Unsize<T: PointeeSized + ?crate::marker::Move>: PointeeSized {
// Empty.
}

Expand Down Expand Up @@ -819,7 +819,7 @@ impl<T: PointeeSized> !Sync for *mut T {}
/// [drop check]: Drop#drop-check
#[lang = "phantom_data"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct PhantomData<T: PointeeSized>;
pub struct PhantomData<T: PointeeSized + ?crate::marker::Move>;

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: PointeeSized> Hash for PhantomData<T> {
Expand Down Expand Up @@ -913,7 +913,7 @@ pub trait DiscriminantKind {
pub unsafe auto trait Freeze {}

#[unstable(feature = "freeze", issue = "121675")]
impl<T: PointeeSized> !Freeze for UnsafeCell<T> {}
impl<T: PointeeSized + ?crate::marker::Move> !Freeze for UnsafeCell<T> {}
marker_impls! {
#[unstable(feature = "freeze", issue = "121675")]
unsafe Freeze for
Expand All @@ -933,7 +933,7 @@ marker_impls! {
#[lang = "unsafe_unpin"]
pub(crate) unsafe auto trait UnsafeUnpin {}

impl<T: ?Sized> !UnsafeUnpin for UnsafePinned<T> {}
impl<T: ?Sized + ?crate::marker::Move> !UnsafeUnpin for UnsafePinned<T> {}
unsafe impl<T: ?Sized> UnsafeUnpin for PhantomData<T> {}
unsafe impl<T: ?Sized> UnsafeUnpin for *const T {}
unsafe impl<T: ?Sized> UnsafeUnpin for *mut T {}
Expand Down Expand Up @@ -1372,3 +1372,21 @@ 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 + ?Move} *const T,
{T: ?Sized + PointeeSized + ?Move} *mut T,
{T: ?Sized + PointeeSized + ?Move} &T,
{T: ?Sized + PointeeSized + ?Move} &mut T,
{T: ?Sized + PointeeSized + ?Move} PhantomData<T>,
}
Loading
Loading