Skip to content
Draft
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
15 changes: 8 additions & 7 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2101,24 +2101,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
{
return;
}
if self.tcx.features().more_maybe_bounds() {
return;
}
}
RelaxedBoundPolicy::Forbidden(reason) => {
if self.tcx.features().more_maybe_bounds() {
return;
}

match reason {
RelaxedBoundForbiddenReason::TraitObjectTy => {
if self.tcx.features().more_maybe_bounds() {
return;
}

self.dcx().span_err(
span,
"relaxed bounds are not permitted in trait object types",
);
return;
}
RelaxedBoundForbiddenReason::SuperTrait => {
if self.tcx.features().more_maybe_bounds() {
return;
}

let mut diag = self.dcx().struct_span_err(
span,
"relaxed bounds are not permitted in supertrait bounds",
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
}
};

if let Node::TraitItem(item) = node {
let mut bounds = Vec::new();
icx.lowerer().add_default_trait_item_bounds(item, &mut bounds);
predicates.extend(bounds);
}

let generics = tcx.generics_of(def_id);

// Below we'll consider the bounds on the type parameters (including `Self`)
Expand Down
142 changes: 13 additions & 129 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use std::assert_matches::assert_matches;
use std::ops::ControlFlow;

use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::codes::*;
use rustc_errors::struct_span_code_err;
use rustc_hir as hir;
use rustc_hir::PolyTraitRef;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
use rustc_hir::{AmbigArg, PolyTraitRef};
use rustc_middle::bug;
use rustc_middle::ty::{
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
Expand Down Expand Up @@ -230,122 +231,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}

/// Checks whether `Self: DefaultAutoTrait` bounds should be added on trait super bounds
/// or associated items.
///
/// To keep backward compatibility with existing code, `experimental_default_bounds` bounds
/// should be added everywhere, including super bounds. However this causes a huge performance
/// costs. For optimization purposes instead of adding default supertraits, bounds
/// are added to the associated items:
///
/// ```ignore(illustrative)
/// // Default bounds are generated in the following way:
/// trait Trait {
/// fn foo(&self) where Self: Leak {}
/// }
///
/// // instead of this:
/// trait Trait: Leak {
/// fn foo(&self) {}
/// }
/// ```
/// It is not always possible to do this because of backward compatibility:
///
/// ```ignore(illustrative)
/// pub trait Trait<Rhs = Self> {}
/// pub trait Trait1 : Trait {}
/// //~^ ERROR: `Rhs` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait`
/// ```
///
/// or:
///
/// ```ignore(illustrative)
/// trait Trait {
/// type Type where Self: Sized;
/// }
/// trait Trait2<T> : Trait<Type = T> {}
/// //~^ ERROR: `DefaultAutoTrait` required for `Trait2`, by implicit `Self: DefaultAutoTrait` in `Trait::Type`
/// ```
///
/// Therefore, `experimental_default_bounds` are still being added to supertraits if
/// the `SelfTyParam` or `AssocItemConstraint` were found in a trait header.
fn requires_default_supertraits(
&self,
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
hir_generics: &'tcx hir::Generics<'tcx>,
) -> bool {
struct TraitInfoCollector;

impl<'tcx> hir::intravisit::Visitor<'tcx> for TraitInfoCollector {
type Result = ControlFlow<()>;

fn visit_assoc_item_constraint(
&mut self,
_constraint: &'tcx hir::AssocItemConstraint<'tcx>,
) -> Self::Result {
ControlFlow::Break(())
}

fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result {
if matches!(
&t.kind,
hir::TyKind::Path(hir::QPath::Resolved(
_,
hir::Path { res: hir::def::Res::SelfTyParam { .. }, .. },
))
) {
return ControlFlow::Break(());
}
hir::intravisit::walk_ty(self, t)
}
}

let mut found = false;
for bound in hir_bounds {
found |= hir::intravisit::walk_param_bound(&mut TraitInfoCollector, bound).is_break();
}
found |= hir::intravisit::walk_generics(&mut TraitInfoCollector, hir_generics).is_break();
found
}

/// Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if
/// they are not added as super trait bounds to the trait itself. See
/// `requires_default_supertraits` for more information.
pub(crate) fn add_default_trait_item_bounds(
&self,
trait_item: &hir::TraitItem<'tcx>,
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
) {
let tcx = self.tcx();
if !tcx.sess.opts.unstable_opts.experimental_default_bounds {
return;
}

let parent = tcx.local_parent(trait_item.hir_id().owner.def_id);
let hir::Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else {
unreachable!();
};

let (trait_generics, trait_bounds) = match parent_trait.kind {
hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => (generics, supertraits),
hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits),
_ => unreachable!(),
};

if !self.requires_default_supertraits(trait_bounds, trait_generics) {
let self_ty_where_predicates = (parent, trait_item.generics.predicates);
self.add_default_traits(
bounds,
tcx.types.self_param,
&[],
Some(self_ty_where_predicates),
trait_item.span,
);
}
}

/// Lazily sets `experimental_default_bounds` to true on trait super bounds.
/// See `requires_default_supertraits` for more information.
/// Sets `experimental_default_bounds` to true on trait super bounds.
pub(crate) fn add_default_super_traits(
&self,
trait_def_id: LocalDefId,
Expand All @@ -354,21 +240,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
hir_generics: &'tcx hir::Generics<'tcx>,
span: Span,
) {
if !self.tcx().sess.opts.unstable_opts.experimental_default_bounds {
assert_matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias);

if self.tcx().trait_is_auto(trait_def_id.to_def_id()) {
return;
}

assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias));
if self.requires_default_supertraits(hir_bounds, hir_generics) {
let self_ty_where_predicates = (trait_def_id, hir_generics.predicates);
self.add_default_traits(
bounds,
self.tcx().types.self_param,
hir_bounds,
Some(self_ty_where_predicates),
span,
);
}
self.add_default_traits(
bounds,
self.tcx().types.self_param,
hir_bounds,
Some((trait_def_id, hir_generics.predicates)),
span,
);
}

pub(crate) fn add_default_traits(
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
.explicit_super_predicates_of(def_id)
.iter_identity_copied()
.filter_map(|(pred, _)| pred.as_trait_clause())
.filter(|pred| !cx.tcx.is_lang_item(pred.def_id(), hir::LangItem::MetaSized));
.filter(|pred| !cx.tcx.is_lang_item(pred.def_id(), hir::LangItem::MetaSized))
.filter(|pred| !cx.tcx.is_default_trait(pred.def_id()));
if direct_super_traits_iter.count() > 1 {
cx.emit_span_lint(
MULTIPLE_SUPERTRAIT_UPCASTABLE,
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 @@ -2240,7 +2240,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
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
Loading
Loading