Auto merge of #137944 - davidtwco:sized-hierarchy, r=oli-obk
Sized Hierarchy: Part I This patch implements the non-const parts of rust-lang/rfcs#3729. It introduces two new traits to the standard library, `MetaSized` and `PointeeSized`. See the RFC for the rationale behind these traits and to discuss whether this change makes sense in the abstract. These traits are unstable (as is their constness), so users cannot refer to them without opting-in to `feature(sized_hierarchy)`. These traits are not behind `cfg`s as this would make implementation unfeasible, there would simply be too many `cfg`s required to add the necessary bounds everywhere. So, like `Sized`, these traits are automatically implemented by the compiler. RFC 3729 describes changes which are necessary to preserve backwards compatibility given the introduction of these traits, which are implemented and as follows: - `?Sized` is rewritten as `MetaSized` - `MetaSized` is added as a default supertrait for all traits w/out an explicit sizedness supertrait already. There are no edition migrations implemented in this, as these are primarily required for the constness parts of the RFC and prior to stabilisation of this (and so will come in follow-up PRs alongside the const parts). All diagnostic output should remain the same (showing `?Sized` even if the compiler sees `MetaSized`) unless the `sized_hierarchy` feature is enabled. Due to the use of unstable extern types in the standard library and rustc, some bounds in both projects have had to be relaxed already - this is unfortunate but unavoidable so that these extern types can continue to be used where they were before. Performing these relaxations in the standard library and rustc are desirable longer-term anyway, but some bounds are not as relaxed as they ideally would be due to the inability to relax `Deref::Target` (this will be investigated separately). It is hoped that this is implemented such that it could be merged and these traits could exist "under the hood" without that being observable to the user (other than in any performance impact this has on the compiler, etc). Some details might leak through due to the standard library relaxations, but this has not been observed in test output. **Notes:** - Any commits starting with "upstream:" can be ignored, as these correspond to other upstream PRs that this is based on which have yet to be merged. - This best reviewed commit-by-commit. I've attempted to make the implementation easy to follow and keep similar changes and test output updates together. - Each commit has a short description describing its purpose. - This patch is large but it's primarily in the test suite. - I've worked on the performance of this patch and a few optimisations are implemented so that the performance impact is neutral-to-minor. - `PointeeSized` is a different name from the RFC just to make it more obvious that it is different from `std::ptr::Pointee` but all the names are yet to be bikeshed anyway. - `@nikomatsakis` has confirmed [that this can proceed as an experiment from the t-lang side](https://rust-lang.zulipchat.com/#narrow/channel/435869-project-goals/topic/SVE.20and.20SME.20on.20AArch64.20.28goals.23270.29/near/506196491) - FCP in https://github.com/rust-lang/rust/pull/137944#issuecomment-2912207485 Fixes rust-lang/rust#79409. r? `@ghost` (I'll discuss this with relevant teams to find a reviewer)
This commit is contained in:
@@ -14,8 +14,14 @@
|
||||
#![no_core]
|
||||
#![allow(dead_code, internal_features, ambiguous_wide_pointer_comparisons)]
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
pub trait Sized: MetaSized {}
|
||||
|
||||
#[lang = "destruct"]
|
||||
pub trait Destruct {}
|
||||
@@ -24,35 +30,35 @@ pub trait Destruct {}
|
||||
pub trait Tuple {}
|
||||
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T: ?Sized> {}
|
||||
pub trait Unsize<T: PointeeSized>: PointeeSized {}
|
||||
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
|
||||
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
|
||||
impl<'a, 'b: 'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a U> for &'b T {}
|
||||
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a mut U> for &'a mut T {}
|
||||
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for *const T {}
|
||||
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*mut U> for *mut T {}
|
||||
|
||||
#[lang = "dispatch_from_dyn"]
|
||||
pub trait DispatchFromDyn<T> {}
|
||||
|
||||
// &T -> &U
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
|
||||
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<&'a U> for &'a T {}
|
||||
// &mut T -> &mut U
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
|
||||
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<&'a mut U> for &'a mut T {}
|
||||
// *const T -> *const U
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
|
||||
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<*const U> for *const T {}
|
||||
// *mut T -> *mut U
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T> {}
|
||||
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<*mut U> for *mut T {}
|
||||
impl<T: MetaSized + Unsize<U>, U: MetaSized> DispatchFromDyn<Box<U>> for Box<T> {}
|
||||
|
||||
#[lang = "legacy_receiver"]
|
||||
pub trait LegacyReceiver {}
|
||||
|
||||
impl<T: ?Sized> LegacyReceiver for &T {}
|
||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
||||
impl<T: ?Sized> LegacyReceiver for Box<T> {}
|
||||
impl<T: PointeeSized> LegacyReceiver for &T {}
|
||||
impl<T: PointeeSized> LegacyReceiver for &mut T {}
|
||||
impl<T: MetaSized> LegacyReceiver for Box<T> {}
|
||||
|
||||
#[lang = "copy"]
|
||||
pub trait Copy {}
|
||||
@@ -74,9 +80,9 @@ impl Copy for isize {}
|
||||
impl Copy for f32 {}
|
||||
impl Copy for f64 {}
|
||||
impl Copy for char {}
|
||||
impl<'a, T: ?Sized> Copy for &'a T {}
|
||||
impl<T: ?Sized> Copy for *const T {}
|
||||
impl<T: ?Sized> Copy for *mut T {}
|
||||
impl<'a, T: PointeeSized> Copy for &'a T {}
|
||||
impl<T: PointeeSized> Copy for *const T {}
|
||||
impl<T: PointeeSized> Copy for *mut T {}
|
||||
impl<T: Copy> Copy for Option<T> {}
|
||||
|
||||
#[lang = "sync"]
|
||||
@@ -94,17 +100,17 @@ unsafe impl Sync for i32 {}
|
||||
unsafe impl Sync for isize {}
|
||||
unsafe impl Sync for char {}
|
||||
unsafe impl Sync for f32 {}
|
||||
unsafe impl<'a, T: ?Sized> Sync for &'a T {}
|
||||
unsafe impl<'a, T: PointeeSized> Sync for &'a T {}
|
||||
unsafe impl<T: Sync, const N: usize> Sync for [T; N] {}
|
||||
|
||||
#[lang = "freeze"]
|
||||
unsafe auto trait Freeze {}
|
||||
|
||||
unsafe impl<T: ?Sized> Freeze for PhantomData<T> {}
|
||||
unsafe impl<T: ?Sized> Freeze for *const T {}
|
||||
unsafe impl<T: ?Sized> Freeze for *mut T {}
|
||||
unsafe impl<T: ?Sized> Freeze for &T {}
|
||||
unsafe impl<T: ?Sized> Freeze for &mut T {}
|
||||
unsafe impl<T: PointeeSized> Freeze for PhantomData<T> {}
|
||||
unsafe impl<T: PointeeSized> Freeze for *const T {}
|
||||
unsafe impl<T: PointeeSized> Freeze for *mut T {}
|
||||
unsafe impl<T: PointeeSized> Freeze for &T {}
|
||||
unsafe impl<T: PointeeSized> Freeze for &mut T {}
|
||||
|
||||
#[lang = "structural_peq"]
|
||||
pub trait StructuralPartialEq {}
|
||||
@@ -443,7 +449,7 @@ pub enum Option<T> {
|
||||
pub use Option::*;
|
||||
|
||||
#[lang = "phantom_data"]
|
||||
pub struct PhantomData<T: ?Sized>;
|
||||
pub struct PhantomData<T: PointeeSized>;
|
||||
|
||||
#[lang = "fn_once"]
|
||||
#[rustc_paren_sugar]
|
||||
@@ -564,18 +570,18 @@ pub trait Deref {
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(1)]
|
||||
#[rustc_nonnull_optimization_guaranteed]
|
||||
pub struct NonNull<T: ?Sized>(pub *const T);
|
||||
pub struct NonNull<T: PointeeSized>(pub *const T);
|
||||
|
||||
impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
|
||||
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
|
||||
impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
|
||||
impl<T: PointeeSized, U: PointeeSized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
|
||||
|
||||
pub struct Unique<T: ?Sized> {
|
||||
pub struct Unique<T: PointeeSized> {
|
||||
pub pointer: NonNull<T>,
|
||||
pub _marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
impl<T: PointeeSized, U: PointeeSized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
|
||||
#[lang = "global_alloc_ty"]
|
||||
pub struct Global;
|
||||
|
||||
@@ -19,8 +19,14 @@ unsafe extern "C" fn _Unwind_Resume() {
|
||||
intrinsics::unreachable();
|
||||
}
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
pub trait Sized: MetaSized {}
|
||||
|
||||
#[lang = "destruct"]
|
||||
pub trait Destruct {}
|
||||
@@ -29,35 +35,35 @@ pub trait Destruct {}
|
||||
pub trait Tuple {}
|
||||
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T: ?Sized> {}
|
||||
pub trait Unsize<T: PointeeSized>: PointeeSized {}
|
||||
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
|
||||
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
|
||||
impl<'a, 'b: 'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a U> for &'b T {}
|
||||
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a mut U> for &'a mut T {}
|
||||
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for *const T {}
|
||||
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*mut U> for *mut T {}
|
||||
|
||||
#[lang = "dispatch_from_dyn"]
|
||||
pub trait DispatchFromDyn<T> {}
|
||||
|
||||
// &T -> &U
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
|
||||
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<&'a U> for &'a T {}
|
||||
// &mut T -> &mut U
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
|
||||
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<&'a mut U> for &'a mut T {}
|
||||
// *const T -> *const U
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
|
||||
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<*const U> for *const T {}
|
||||
// *mut T -> *mut U
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U, ()>> for Box<T, ()> {}
|
||||
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<*mut U> for *mut T {}
|
||||
impl<T: MetaSized + Unsize<U>, U: MetaSized> DispatchFromDyn<Box<U, ()>> for Box<T, ()> {}
|
||||
|
||||
#[lang = "legacy_receiver"]
|
||||
pub trait LegacyReceiver {}
|
||||
|
||||
impl<T: ?Sized> LegacyReceiver for &T {}
|
||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
||||
impl<T: ?Sized, A: Allocator> LegacyReceiver for Box<T, A> {}
|
||||
impl<T: PointeeSized> LegacyReceiver for &T {}
|
||||
impl<T: PointeeSized> LegacyReceiver for &mut T {}
|
||||
impl<T: MetaSized> LegacyReceiver for Box<T> {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
trait Receiver {}
|
||||
@@ -84,9 +90,9 @@ impl Copy for i128 {}
|
||||
impl Copy for f32 {}
|
||||
impl Copy for f64 {}
|
||||
impl Copy for char {}
|
||||
impl<'a, T: ?Sized> Copy for &'a T {}
|
||||
impl<T: ?Sized> Copy for *const T {}
|
||||
impl<T: ?Sized> Copy for *mut T {}
|
||||
impl<'a, T: PointeeSized> Copy for &'a T {}
|
||||
impl<T: PointeeSized> Copy for *const T {}
|
||||
impl<T: PointeeSized> Copy for *mut T {}
|
||||
|
||||
#[lang = "sync"]
|
||||
pub unsafe trait Sync {}
|
||||
@@ -102,17 +108,17 @@ unsafe impl Sync for i16 {}
|
||||
unsafe impl Sync for i32 {}
|
||||
unsafe impl Sync for isize {}
|
||||
unsafe impl Sync for char {}
|
||||
unsafe impl<'a, T: ?Sized> Sync for &'a T {}
|
||||
unsafe impl<'a, T: PointeeSized> Sync for &'a T {}
|
||||
unsafe impl Sync for [u8; 16] {}
|
||||
|
||||
#[lang = "freeze"]
|
||||
unsafe auto trait Freeze {}
|
||||
|
||||
unsafe impl<T: ?Sized> Freeze for PhantomData<T> {}
|
||||
unsafe impl<T: ?Sized> Freeze for *const T {}
|
||||
unsafe impl<T: ?Sized> Freeze for *mut T {}
|
||||
unsafe impl<T: ?Sized> Freeze for &T {}
|
||||
unsafe impl<T: ?Sized> Freeze for &mut T {}
|
||||
unsafe impl<T: PointeeSized> Freeze for PhantomData<T> {}
|
||||
unsafe impl<T: PointeeSized> Freeze for *const T {}
|
||||
unsafe impl<T: PointeeSized> Freeze for *mut T {}
|
||||
unsafe impl<T: PointeeSized> Freeze for &T {}
|
||||
unsafe impl<T: PointeeSized> Freeze for &mut T {}
|
||||
|
||||
#[lang = "structural_peq"]
|
||||
pub trait StructuralPartialEq {}
|
||||
@@ -456,7 +462,7 @@ pub enum Option<T> {
|
||||
pub use Option::*;
|
||||
|
||||
#[lang = "phantom_data"]
|
||||
pub struct PhantomData<T: ?Sized>;
|
||||
pub struct PhantomData<T: PointeeSized>;
|
||||
|
||||
#[lang = "fn_once"]
|
||||
#[rustc_paren_sugar]
|
||||
@@ -576,18 +582,18 @@ impl Allocator for Global {}
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(1)]
|
||||
#[rustc_nonnull_optimization_guaranteed]
|
||||
pub struct NonNull<T: ?Sized>(pub *const T);
|
||||
pub struct NonNull<T: PointeeSized>(pub *const T);
|
||||
|
||||
impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
|
||||
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
|
||||
impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
|
||||
impl<T: PointeeSized, U: PointeeSized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
|
||||
|
||||
pub struct Unique<T: ?Sized> {
|
||||
pub struct Unique<T: PointeeSized> {
|
||||
pub pointer: NonNull<T>,
|
||||
pub _marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
impl<T: PointeeSized, U: PointeeSized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
|
||||
#[lang = "owned_box"]
|
||||
pub struct Box<T: ?Sized, A: Allocator = Global>(Unique<T>, A);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use std::ptr::Alignment;
|
||||
|
||||
use rustc_serialize::PointeeSized;
|
||||
|
||||
/// Returns the ABI-required minimum alignment of a type in bytes.
|
||||
///
|
||||
/// This is equivalent to [`align_of`], but also works for some unsized
|
||||
@@ -17,7 +19,7 @@ pub const fn align_of<T: ?Sized + Aligned>() -> Alignment {
|
||||
/// example `[T]` has alignment of `T`.
|
||||
///
|
||||
/// [`align_of::<Self>()`]: align_of
|
||||
pub unsafe trait Aligned {
|
||||
pub unsafe trait Aligned: PointeeSized {
|
||||
/// Alignment of `Self`.
|
||||
const ALIGN: Alignment;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![cfg_attr(bootstrap, feature(cfg_match))]
|
||||
#![cfg_attr(not(bootstrap), feature(cfg_select))]
|
||||
#![cfg_attr(not(bootstrap), feature(sized_hierarchy))]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
@@ -43,6 +44,9 @@ use std::fmt;
|
||||
pub use atomic_ref::AtomicRef;
|
||||
pub use ena::{snapshot_vec, undo_log, unify};
|
||||
pub use rustc_index::static_assert_size;
|
||||
// re-exported for `rustc_smir`
|
||||
// FIXME(sized_hierarchy): remove with `cfg(bootstrap)`, see `rustc_serialize/src/lib.rs`
|
||||
pub use rustc_serialize::PointeeSized;
|
||||
|
||||
pub mod aligned;
|
||||
pub mod base_n;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use std::alloc::Allocator;
|
||||
|
||||
use rustc_serialize::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`")]
|
||||
// This is an auto trait for types which can be sent across threads if `sync::is_dyn_thread_safe()`
|
||||
@@ -15,7 +17,7 @@ pub unsafe auto trait DynSend {}
|
||||
pub unsafe auto trait DynSync {}
|
||||
|
||||
// Same with `Sync` and `Send`.
|
||||
unsafe impl<T: DynSync + ?Sized> DynSend for &T {}
|
||||
unsafe impl<T: DynSync + ?Sized + PointeeSized> DynSend for &T {}
|
||||
|
||||
macro_rules! impls_dyn_send_neg {
|
||||
($([$t1: ty $(where $($generics1: tt)*)?])*) => {
|
||||
@@ -27,9 +29,9 @@ macro_rules! impls_dyn_send_neg {
|
||||
impls_dyn_send_neg!(
|
||||
[std::env::Args]
|
||||
[std::env::ArgsOs]
|
||||
[*const T where T: ?Sized]
|
||||
[*mut T where T: ?Sized]
|
||||
[std::ptr::NonNull<T> where T: ?Sized]
|
||||
[*const T where T: ?Sized + PointeeSized]
|
||||
[*mut T where T: ?Sized + PointeeSized]
|
||||
[std::ptr::NonNull<T> where T: ?Sized + PointeeSized]
|
||||
[std::rc::Rc<T, A> where T: ?Sized, A: Allocator]
|
||||
[std::rc::Weak<T, A> where T: ?Sized, A: Allocator]
|
||||
[std::sync::MutexGuard<'_, T> where T: ?Sized]
|
||||
@@ -100,12 +102,12 @@ macro_rules! impls_dyn_sync_neg {
|
||||
impls_dyn_sync_neg!(
|
||||
[std::env::Args]
|
||||
[std::env::ArgsOs]
|
||||
[*const T where T: ?Sized]
|
||||
[*mut T where T: ?Sized]
|
||||
[*const T where T: ?Sized + PointeeSized]
|
||||
[*mut T where T: ?Sized + PointeeSized]
|
||||
[std::cell::Cell<T> where T: ?Sized]
|
||||
[std::cell::RefCell<T> where T: ?Sized]
|
||||
[std::cell::UnsafeCell<T> where T: ?Sized]
|
||||
[std::ptr::NonNull<T> where T: ?Sized]
|
||||
[std::ptr::NonNull<T> where T: ?Sized + PointeeSized]
|
||||
[std::rc::Rc<T, A> where T: ?Sized, A: Allocator]
|
||||
[std::rc::Weak<T, A> where T: ?Sized, A: Allocator]
|
||||
[std::cell::OnceCell<T> where T]
|
||||
@@ -175,10 +177,10 @@ impl_dyn_sync!(
|
||||
[thin_vec::ThinVec<T> where T: DynSync]
|
||||
);
|
||||
|
||||
pub fn assert_dyn_sync<T: ?Sized + DynSync>() {}
|
||||
pub fn assert_dyn_send<T: ?Sized + DynSend>() {}
|
||||
pub fn assert_dyn_send_val<T: ?Sized + DynSend>(_t: &T) {}
|
||||
pub fn assert_dyn_send_sync_val<T: ?Sized + DynSync + DynSend>(_t: &T) {}
|
||||
pub fn assert_dyn_sync<T: ?Sized + PointeeSized + DynSync>() {}
|
||||
pub fn assert_dyn_send<T: ?Sized + PointeeSized + DynSend>() {}
|
||||
pub fn assert_dyn_send_val<T: ?Sized + PointeeSized + DynSend>(_t: &T) {}
|
||||
pub fn assert_dyn_send_sync_val<T: ?Sized + PointeeSized + DynSync + DynSend>(_t: &T) {}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct FromDyn<T>(T);
|
||||
@@ -231,10 +233,10 @@ impl<T> std::ops::DerefMut for FromDyn<T> {
|
||||
// an instance of `DynSend` and `DynSync`, since the compiler cannot infer
|
||||
// it automatically in some cases. (e.g. Box<dyn Send / Sync>)
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct IntoDynSyncSend<T: ?Sized>(pub T);
|
||||
pub struct IntoDynSyncSend<T: ?Sized + PointeeSized>(pub T);
|
||||
|
||||
unsafe impl<T: ?Sized + Send> DynSend for IntoDynSyncSend<T> {}
|
||||
unsafe impl<T: ?Sized + Sync> DynSync for IntoDynSyncSend<T> {}
|
||||
unsafe impl<T: ?Sized + PointeeSized + Send> DynSend for IntoDynSyncSend<T> {}
|
||||
unsafe impl<T: ?Sized + PointeeSized + Sync> DynSync for IntoDynSyncSend<T> {}
|
||||
|
||||
impl<T> std::ops::Deref for IntoDynSyncSend<T> {
|
||||
type Target = T;
|
||||
|
||||
@@ -237,6 +237,8 @@ declare_features! (
|
||||
(internal, profiler_runtime, "1.18.0", None),
|
||||
/// Allows using `rustc_*` attributes (RFC 572).
|
||||
(internal, rustc_attrs, "1.0.0", None),
|
||||
/// Introduces a hierarchy of `Sized` traits (RFC 3729).
|
||||
(unstable, sized_hierarchy, "CURRENT_RUSTC_VERSION", None),
|
||||
/// Allows using the `#[stable]` and `#[unstable]` attributes.
|
||||
(internal, staged_api, "1.0.0", None),
|
||||
/// Added for testing unstable lints; perma-unstable.
|
||||
|
||||
@@ -165,6 +165,8 @@ pub fn extract(attrs: &[impl AttributeExt]) -> Option<(Symbol, Span)> {
|
||||
language_item_table! {
|
||||
// Variant name, Name, Getter method name, Target Generic requirements;
|
||||
Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
MetaSized, sym::meta_sized, meta_sized_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
PointeeSized, sym::pointee_sized, pointee_sized_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
|
||||
/// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
|
||||
StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None;
|
||||
|
||||
@@ -76,6 +76,7 @@ pub use check::{check_abi, check_abi_fn_ptr, check_custom_abi};
|
||||
use rustc_abi::{ExternAbi, VariantIdx};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||
use rustc_errors::{Diag, ErrorGuaranteed, pluralize, struct_span_code_err};
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_index::bit_set::DenseBitSet;
|
||||
@@ -331,7 +332,7 @@ fn bounds_from_generic_predicates<'tcx>(
|
||||
ty::ClauseKind::Trait(trait_predicate) => {
|
||||
let entry = types.entry(trait_predicate.self_ty()).or_default();
|
||||
let def_id = trait_predicate.def_id();
|
||||
if !tcx.is_default_trait(def_id) {
|
||||
if !tcx.is_default_trait(def_id) && !tcx.is_lang_item(def_id, LangItem::Sized) {
|
||||
// Do not add that restriction to the list if it is a positive requirement.
|
||||
entry.push(trait_predicate.def_id());
|
||||
}
|
||||
|
||||
@@ -1258,6 +1258,11 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuarant
|
||||
debug!(?item.owner_id);
|
||||
|
||||
let def_id = item.owner_id.def_id;
|
||||
if tcx.is_lang_item(def_id.into(), LangItem::PointeeSized) {
|
||||
// `PointeeSized` is removed during lowering.
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let trait_def = tcx.trait_def(def_id);
|
||||
if trait_def.is_marker
|
||||
|| matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker)
|
||||
|
||||
@@ -44,6 +44,14 @@ fn associated_type_bounds<'tcx>(
|
||||
| PredicateFilter::SelfOnly
|
||||
| PredicateFilter::SelfTraitThatDefines(_)
|
||||
| PredicateFilter::SelfAndAssociatedTypeBounds => {
|
||||
icx.lowerer().add_sizedness_bounds(
|
||||
&mut bounds,
|
||||
item_ty,
|
||||
hir_bounds,
|
||||
None,
|
||||
None,
|
||||
span,
|
||||
);
|
||||
icx.lowerer().add_default_traits(&mut bounds, item_ty, hir_bounds, None, span);
|
||||
}
|
||||
// `ConstIfConst` is only interested in `~const` bounds.
|
||||
@@ -333,6 +341,14 @@ fn opaque_type_bounds<'tcx>(
|
||||
| PredicateFilter::SelfOnly
|
||||
| PredicateFilter::SelfTraitThatDefines(_)
|
||||
| PredicateFilter::SelfAndAssociatedTypeBounds => {
|
||||
icx.lowerer().add_sizedness_bounds(
|
||||
&mut bounds,
|
||||
item_ty,
|
||||
hir_bounds,
|
||||
None,
|
||||
None,
|
||||
span,
|
||||
);
|
||||
icx.lowerer().add_default_traits(&mut bounds, item_ty, hir_bounds, None, span);
|
||||
}
|
||||
//`ConstIfConst` is only interested in `~const` bounds.
|
||||
|
||||
@@ -162,7 +162,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
.map(|t| ty::Binder::dummy(t.instantiate_identity()));
|
||||
}
|
||||
}
|
||||
|
||||
ItemKind::Trait(_, _, _, _, self_bounds, ..)
|
||||
| ItemKind::TraitAlias(_, _, self_bounds) => {
|
||||
is_trait = Some((self_bounds, item.span));
|
||||
@@ -183,21 +182,29 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
// and the explicit where-clauses, but to get the full set of predicates
|
||||
// on a trait we must also consider the bounds that follow the trait's name,
|
||||
// like `trait Foo: A + B + C`.
|
||||
if let Some(self_bounds) = is_trait {
|
||||
if let Some((self_bounds, span)) = is_trait {
|
||||
let mut bounds = Vec::new();
|
||||
icx.lowerer().lower_bounds(
|
||||
tcx.types.self_param,
|
||||
self_bounds.0,
|
||||
self_bounds,
|
||||
&mut bounds,
|
||||
ty::List::empty(),
|
||||
PredicateFilter::All,
|
||||
);
|
||||
icx.lowerer().add_sizedness_bounds(
|
||||
&mut bounds,
|
||||
tcx.types.self_param,
|
||||
self_bounds,
|
||||
None,
|
||||
Some(def_id),
|
||||
span,
|
||||
);
|
||||
icx.lowerer().add_default_super_traits(
|
||||
def_id,
|
||||
&mut bounds,
|
||||
self_bounds.0,
|
||||
self_bounds,
|
||||
hir_generics,
|
||||
self_bounds.1,
|
||||
span,
|
||||
);
|
||||
predicates.extend(bounds);
|
||||
}
|
||||
@@ -224,6 +231,14 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
let param_ty = icx.lowerer().lower_ty_param(param.hir_id);
|
||||
let mut bounds = Vec::new();
|
||||
// Implicit bounds are added to type params unless a `?Trait` bound is found
|
||||
icx.lowerer().add_sizedness_bounds(
|
||||
&mut bounds,
|
||||
param_ty,
|
||||
&[],
|
||||
Some((param.def_id, hir_generics.predicates)),
|
||||
None,
|
||||
param.span,
|
||||
);
|
||||
icx.lowerer().add_default_traits(
|
||||
&mut bounds,
|
||||
param_ty,
|
||||
|
||||
@@ -4,15 +4,15 @@ 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::AmbigArg;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::{AmbigArg, LangItem, PolyTraitRef};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{
|
||||
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||
TypeVisitor, Upcast,
|
||||
};
|
||||
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
|
||||
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw};
|
||||
use rustc_trait_selection::traits;
|
||||
use smallvec::SmallVec;
|
||||
use tracing::{debug, instrument};
|
||||
@@ -23,23 +23,213 @@ use crate::hir_ty_lowering::{
|
||||
AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason,
|
||||
};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct CollectedBound {
|
||||
/// `Trait`
|
||||
positive: bool,
|
||||
/// `?Trait`
|
||||
maybe: bool,
|
||||
/// `!Trait`
|
||||
negative: bool,
|
||||
}
|
||||
|
||||
impl CollectedBound {
|
||||
/// Returns `true` if any of `Trait`, `?Trait` or `!Trait` were encountered.
|
||||
fn any(&self) -> bool {
|
||||
self.positive || self.maybe || self.negative
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CollectedSizednessBounds {
|
||||
// Collected `Sized` bounds
|
||||
sized: CollectedBound,
|
||||
// Collected `MetaSized` bounds
|
||||
meta_sized: CollectedBound,
|
||||
// Collected `PointeeSized` bounds
|
||||
pointee_sized: CollectedBound,
|
||||
}
|
||||
|
||||
impl CollectedSizednessBounds {
|
||||
/// Returns `true` if any of `Trait`, `?Trait` or `!Trait` were encountered for `Sized`,
|
||||
/// `MetaSized` or `PointeeSized`.
|
||||
fn any(&self) -> bool {
|
||||
self.sized.any() || self.meta_sized.any() || self.pointee_sized.any()
|
||||
}
|
||||
}
|
||||
|
||||
fn search_bounds_for<'tcx>(
|
||||
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||
mut f: impl FnMut(&'tcx PolyTraitRef<'tcx>),
|
||||
) {
|
||||
let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| {
|
||||
for hir_bound in hir_bounds {
|
||||
let hir::GenericBound::Trait(ptr) = hir_bound else {
|
||||
continue;
|
||||
};
|
||||
|
||||
f(ptr)
|
||||
}
|
||||
};
|
||||
|
||||
search_bounds(hir_bounds);
|
||||
if let Some((self_ty, where_clause)) = self_ty_where_predicates {
|
||||
for clause in where_clause {
|
||||
if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind
|
||||
&& pred.is_param_bound(self_ty.to_def_id())
|
||||
{
|
||||
search_bounds(pred.bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_unbounds<'tcx>(
|
||||
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||
) -> SmallVec<[&'tcx PolyTraitRef<'tcx>; 1]> {
|
||||
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
|
||||
search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
|
||||
if matches!(ptr.modifiers.polarity, hir::BoundPolarity::Maybe(_)) {
|
||||
unbounds.push(ptr);
|
||||
}
|
||||
});
|
||||
unbounds
|
||||
}
|
||||
|
||||
fn collect_bounds<'a, 'tcx>(
|
||||
hir_bounds: &'a [hir::GenericBound<'tcx>],
|
||||
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||
target_did: DefId,
|
||||
) -> CollectedBound {
|
||||
let mut collect_into = CollectedBound::default();
|
||||
search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
|
||||
if !matches!(ptr.trait_ref.path.res, Res::Def(DefKind::Trait, did) if did == target_did) {
|
||||
return;
|
||||
}
|
||||
|
||||
match ptr.modifiers.polarity {
|
||||
hir::BoundPolarity::Maybe(_) => collect_into.maybe = true,
|
||||
hir::BoundPolarity::Negative(_) => collect_into.negative = true,
|
||||
hir::BoundPolarity::Positive => collect_into.positive = true,
|
||||
}
|
||||
});
|
||||
collect_into
|
||||
}
|
||||
|
||||
fn collect_sizedness_bounds<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||
span: Span,
|
||||
) -> CollectedSizednessBounds {
|
||||
let sized_did = tcx.require_lang_item(LangItem::Sized, span);
|
||||
let sized = collect_bounds(hir_bounds, self_ty_where_predicates, sized_did);
|
||||
|
||||
let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
|
||||
let meta_sized = collect_bounds(hir_bounds, self_ty_where_predicates, meta_sized_did);
|
||||
|
||||
let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
|
||||
let pointee_sized = collect_bounds(hir_bounds, self_ty_where_predicates, pointee_sized_did);
|
||||
|
||||
CollectedSizednessBounds { sized, meta_sized, pointee_sized }
|
||||
}
|
||||
|
||||
/// Add a trait bound for `did`.
|
||||
fn add_trait_bound<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
||||
self_ty: Ty<'tcx>,
|
||||
did: DefId,
|
||||
span: Span,
|
||||
) {
|
||||
let trait_ref = ty::TraitRef::new(tcx, did, [self_ty]);
|
||||
// Preferable to put sizedness obligations first, since we report better errors for `Sized`
|
||||
// ambiguity.
|
||||
bounds.insert(0, (trait_ref.upcast(tcx), span));
|
||||
}
|
||||
|
||||
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
pub(crate) fn add_default_traits(
|
||||
/// Skip `PointeeSized` bounds.
|
||||
///
|
||||
/// `PointeeSized` is a "fake bound" insofar as anywhere a `PointeeSized` bound exists, there
|
||||
/// is actually the absence of any bounds. This avoids limitations around non-global where
|
||||
/// clauses being preferred over item bounds (where `PointeeSized` bounds would be
|
||||
/// proven) - which can result in errors when a `PointeeSized` supertrait/bound/predicate is
|
||||
/// added to some items.
|
||||
pub(crate) fn should_skip_sizedness_bound<'hir>(
|
||||
&self,
|
||||
bound: &'hir hir::GenericBound<'tcx>,
|
||||
) -> bool {
|
||||
bound
|
||||
.trait_ref()
|
||||
.and_then(|tr| tr.trait_def_id())
|
||||
.map(|did| self.tcx().is_lang_item(did, LangItem::PointeeSized))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Adds sizedness bounds to a trait, trait alias, parameter, opaque type or associated type.
|
||||
///
|
||||
/// - On parameters, opaque type and associated types, add default `Sized` bound if no explicit
|
||||
/// sizedness bounds are present.
|
||||
/// - On traits and trait aliases, add default `MetaSized` supertrait if no explicit sizedness
|
||||
/// bounds are present.
|
||||
/// - On parameters, opaque type, associated types and trait aliases, add a `MetaSized` bound if
|
||||
/// a `?Sized` bound is present.
|
||||
pub(crate) fn add_sizedness_bounds(
|
||||
&self,
|
||||
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
||||
self_ty: Ty<'tcx>,
|
||||
hir_bounds: &[hir::GenericBound<'tcx>],
|
||||
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||
trait_did: Option<LocalDefId>,
|
||||
span: Span,
|
||||
) {
|
||||
self.add_default_traits_with_filter(
|
||||
bounds,
|
||||
self_ty,
|
||||
hir_bounds,
|
||||
self_ty_where_predicates,
|
||||
span,
|
||||
|_| true,
|
||||
);
|
||||
let tcx = self.tcx();
|
||||
|
||||
let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
|
||||
let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
|
||||
|
||||
// If adding sizedness bounds to a trait, then there are some relevant early exits
|
||||
if let Some(trait_did) = trait_did {
|
||||
let trait_did = trait_did.to_def_id();
|
||||
// Never add a default supertrait to `PointeeSized`.
|
||||
if trait_did == pointee_sized_did {
|
||||
return;
|
||||
}
|
||||
// Don't add default sizedness supertraits to auto traits because it isn't possible to
|
||||
// relax an automatically added supertrait on the defn itself.
|
||||
if tcx.trait_is_auto(trait_did) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Report invalid unbounds on sizedness-bounded generic parameters.
|
||||
let unbounds = collect_unbounds(hir_bounds, self_ty_where_predicates);
|
||||
self.check_and_report_invalid_unbounds_on_param(unbounds);
|
||||
}
|
||||
|
||||
let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, span);
|
||||
if (collected.sized.maybe || collected.sized.negative)
|
||||
&& !collected.sized.positive
|
||||
&& !collected.meta_sized.any()
|
||||
&& !collected.pointee_sized.any()
|
||||
{
|
||||
// `?Sized` is equivalent to `MetaSized` (but only add the bound if there aren't any
|
||||
// other explicit ones) - this can happen for trait aliases as well as bounds.
|
||||
add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
|
||||
} else if !collected.any() {
|
||||
if trait_did.is_some() {
|
||||
// If there are no explicit sizedness bounds on a trait then add a default
|
||||
// `MetaSized` supertrait.
|
||||
add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
|
||||
} else {
|
||||
// If there are no explicit sizedness bounds on a parameter then add a default
|
||||
// `Sized` bound.
|
||||
let sized_did = tcx.require_lang_item(LangItem::Sized, span);
|
||||
add_trait_bound(tcx, bounds, self_ty, sized_did, span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks whether `Self: DefaultAutoTrait` bounds should be added on trait super bounds
|
||||
@@ -146,13 +336,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
|
||||
if !self.requires_default_supertraits(trait_bounds, trait_generics) {
|
||||
let self_ty_where_predicates = (parent, trait_item.generics.predicates);
|
||||
self.add_default_traits_with_filter(
|
||||
self.add_default_traits(
|
||||
bounds,
|
||||
tcx.types.self_param,
|
||||
&[],
|
||||
Some(self_ty_where_predicates),
|
||||
trait_item.span,
|
||||
|tr| tr != hir::LangItem::Sized,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -174,28 +363,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
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_with_filter(
|
||||
self.add_default_traits(
|
||||
bounds,
|
||||
self.tcx().types.self_param,
|
||||
hir_bounds,
|
||||
Some(self_ty_where_predicates),
|
||||
span,
|
||||
|default_trait| default_trait != hir::LangItem::Sized,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn add_default_traits_with_filter(
|
||||
pub(crate) fn add_default_traits(
|
||||
&self,
|
||||
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
||||
self_ty: Ty<'tcx>,
|
||||
hir_bounds: &[hir::GenericBound<'tcx>],
|
||||
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||
span: Span,
|
||||
f: impl Fn(hir::LangItem) -> bool,
|
||||
) {
|
||||
self.tcx().default_traits().iter().filter(|&&default_trait| f(default_trait)).for_each(
|
||||
|default_trait| {
|
||||
self.tcx().default_traits().iter().for_each(|default_trait| {
|
||||
self.add_default_trait(
|
||||
*default_trait,
|
||||
bounds,
|
||||
@@ -204,11 +390,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
self_ty_where_predicates,
|
||||
span,
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Add a `Sized` or `experimental_default_bounds` bounds to the `bounds` if appropriate.
|
||||
/// Add a `experimental_default_bounds` bound to the `bounds` if appropriate.
|
||||
///
|
||||
/// Doesn't add the bound if the HIR bounds contain any of `Trait`, `?Trait` or `!Trait`.
|
||||
pub(crate) fn add_default_trait(
|
||||
@@ -220,7 +405,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||
span: Span,
|
||||
) {
|
||||
let trait_id = self.tcx().lang_items().get(trait_);
|
||||
let tcx = self.tcx();
|
||||
let trait_id = tcx.lang_items().get(trait_);
|
||||
if let Some(trait_id) = trait_id
|
||||
&& self.do_not_provide_default_trait_bound(
|
||||
trait_id,
|
||||
@@ -228,11 +414,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
self_ty_where_predicates,
|
||||
)
|
||||
{
|
||||
// There was no `?Trait` or `!Trait` bound;
|
||||
// add `Trait` if it's available.
|
||||
let trait_ref = ty::TraitRef::new(self.tcx(), trait_id, [self_ty]);
|
||||
// Preferable to put this obligation first, since we report better errors for sized ambiguity.
|
||||
bounds.insert(0, (trait_ref.upcast(self.tcx()), span));
|
||||
add_trait_bound(tcx, bounds, self_ty, trait_id, span);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,90 +424,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
hir_bounds: &'a [hir::GenericBound<'tcx>],
|
||||
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||
) -> bool {
|
||||
let tcx = self.tcx();
|
||||
let mut seen_negative_bound = false;
|
||||
let mut seen_positive_bound = false;
|
||||
|
||||
// Try to find an unbound in bounds.
|
||||
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
|
||||
let mut search_bounds = |hir_bounds: &'a [hir::GenericBound<'tcx>]| {
|
||||
for hir_bound in hir_bounds {
|
||||
let hir::GenericBound::Trait(ptr) = hir_bound else {
|
||||
continue;
|
||||
};
|
||||
match ptr.modifiers.polarity {
|
||||
hir::BoundPolarity::Maybe(_) => unbounds.push(ptr),
|
||||
hir::BoundPolarity::Negative(_) => {
|
||||
if ptr.trait_ref.path.res == Res::Def(DefKind::Trait, trait_def_id) {
|
||||
seen_negative_bound = true;
|
||||
}
|
||||
}
|
||||
hir::BoundPolarity::Positive => {
|
||||
if ptr.trait_ref.path.res == Res::Def(DefKind::Trait, trait_def_id) {
|
||||
seen_positive_bound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
search_bounds(hir_bounds);
|
||||
if let Some((self_ty, where_clause)) = self_ty_where_predicates {
|
||||
for clause in where_clause {
|
||||
if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind
|
||||
&& pred.is_param_bound(self_ty.to_def_id())
|
||||
{
|
||||
search_bounds(pred.bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut unique_bounds = FxIndexSet::default();
|
||||
let mut seen_repeat = false;
|
||||
for unbound in &unbounds {
|
||||
if let Res::Def(DefKind::Trait, unbound_def_id) = unbound.trait_ref.path.res {
|
||||
seen_repeat |= !unique_bounds.insert(unbound_def_id);
|
||||
}
|
||||
}
|
||||
if unbounds.len() > 1 {
|
||||
let err = errors::MultipleRelaxedDefaultBounds {
|
||||
spans: unbounds.iter().map(|ptr| ptr.span).collect(),
|
||||
};
|
||||
if seen_repeat {
|
||||
self.dcx().emit_err(err);
|
||||
} else if !tcx.features().more_maybe_bounds() {
|
||||
self.tcx().sess.create_feature_err(err, sym::more_maybe_bounds).emit();
|
||||
};
|
||||
}
|
||||
|
||||
let mut seen_unbound = false;
|
||||
for unbound in unbounds {
|
||||
let unbound_def_id = unbound.trait_ref.trait_def_id();
|
||||
if unbound_def_id == Some(trait_def_id) {
|
||||
seen_unbound = true;
|
||||
}
|
||||
let emit_relax_err = || {
|
||||
let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds {
|
||||
true => "`?Sized` and `experimental_default_bounds`",
|
||||
false => "`?Sized`",
|
||||
};
|
||||
// There was a `?Trait` bound, but it was neither `?Sized` nor `experimental_default_bounds`.
|
||||
self.dcx().span_err(
|
||||
unbound.span,
|
||||
format!(
|
||||
"relaxing a default bound only does something for {}; \
|
||||
all other traits are not bound by default",
|
||||
unbound_traits
|
||||
),
|
||||
);
|
||||
};
|
||||
match unbound_def_id {
|
||||
Some(def_id) if !tcx.is_default_trait(def_id) => emit_relax_err(),
|
||||
None => emit_relax_err(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
!(seen_unbound || seen_negative_bound || seen_positive_bound)
|
||||
let collected = collect_bounds(hir_bounds, self_ty_where_predicates, trait_def_id);
|
||||
!collected.any()
|
||||
}
|
||||
|
||||
/// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any.
|
||||
@@ -361,6 +461,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
'tcx: 'hir,
|
||||
{
|
||||
for hir_bound in hir_bounds {
|
||||
if self.should_skip_sizedness_bound(hir_bound) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// In order to avoid cycles, when we're lowering `SelfTraitThatDefines`,
|
||||
// we skip over any traits that don't define the given associated type.
|
||||
if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
|
||||
|
||||
@@ -61,14 +61,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
let ast_bounds: Vec<_> =
|
||||
hir_bounds.iter().map(|&trait_ref| hir::GenericBound::Trait(trait_ref)).collect();
|
||||
|
||||
self.add_default_traits_with_filter(
|
||||
&mut user_written_bounds,
|
||||
dummy_self,
|
||||
&ast_bounds,
|
||||
None,
|
||||
span,
|
||||
|tr| tr != hir::LangItem::Sized,
|
||||
);
|
||||
self.add_default_traits(&mut user_written_bounds, dummy_self, &ast_bounds, None, span);
|
||||
|
||||
let (elaborated_trait_bounds, elaborated_projection_bounds) =
|
||||
traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
|
||||
|
||||
@@ -8,7 +8,7 @@ use rustc_errors::{
|
||||
};
|
||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{self as hir, HirId};
|
||||
use rustc_hir::{self as hir, HirId, LangItem, PolyTraitRef};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
|
||||
use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
|
||||
@@ -34,6 +34,57 @@ use crate::fluent_generated as fluent;
|
||||
use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
|
||||
|
||||
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
/// Check for multiple relaxed default bounds and relaxed bounds of non-sizedness traits.
|
||||
pub(crate) fn check_and_report_invalid_unbounds_on_param(
|
||||
&self,
|
||||
unbounds: SmallVec<[&PolyTraitRef<'_>; 1]>,
|
||||
) {
|
||||
let tcx = self.tcx();
|
||||
|
||||
let sized_did = tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
|
||||
|
||||
let mut unique_bounds = FxIndexSet::default();
|
||||
let mut seen_repeat = false;
|
||||
for unbound in &unbounds {
|
||||
if let Res::Def(DefKind::Trait, unbound_def_id) = unbound.trait_ref.path.res {
|
||||
seen_repeat |= !unique_bounds.insert(unbound_def_id);
|
||||
}
|
||||
}
|
||||
|
||||
if unbounds.len() > 1 {
|
||||
let err = errors::MultipleRelaxedDefaultBounds {
|
||||
spans: unbounds.iter().map(|ptr| ptr.span).collect(),
|
||||
};
|
||||
|
||||
if seen_repeat {
|
||||
tcx.dcx().emit_err(err);
|
||||
} else if !tcx.features().more_maybe_bounds() {
|
||||
tcx.sess.create_feature_err(err, sym::more_maybe_bounds).emit();
|
||||
};
|
||||
}
|
||||
|
||||
for unbound in unbounds {
|
||||
if let Res::Def(DefKind::Trait, did) = unbound.trait_ref.path.res
|
||||
&& ((did == sized_did) || tcx.is_default_trait(did))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds {
|
||||
true => "`?Sized` and `experimental_default_bounds`",
|
||||
false => "`?Sized`",
|
||||
};
|
||||
self.dcx().span_err(
|
||||
unbound.span,
|
||||
format!(
|
||||
"relaxing a default bound only does something for {}; all other traits are \
|
||||
not bound by default",
|
||||
unbound_traits
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
|
||||
/// the type parameter's name as a placeholder.
|
||||
pub(crate) fn report_missing_type_params(
|
||||
|
||||
@@ -22,8 +22,9 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
|
||||
use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
|
||||
use rustc_middle::ty::{
|
||||
self, AdtKind, CanonicalUserType, GenericArgsRef, GenericParamDefKind, IsIdentity, Ty, TyCtxt,
|
||||
TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs, UserSelfTy,
|
||||
self, AdtKind, CanonicalUserType, GenericArgsRef, GenericParamDefKind, IsIdentity,
|
||||
SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs,
|
||||
UserSelfTy,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint;
|
||||
@@ -439,7 +440,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|| {},
|
||||
);
|
||||
// Sized types have static alignment, and so do slices.
|
||||
if tail.is_trivially_sized(self.tcx) || matches!(tail.kind(), ty::Slice(..)) {
|
||||
if tail.has_trivial_sizedness(self.tcx, SizedTraitKind::Sized)
|
||||
|| matches!(tail.kind(), ty::Slice(..))
|
||||
{
|
||||
// Nothing else is required here.
|
||||
} else {
|
||||
// We can't be sure, let's required full `Sized`.
|
||||
|
||||
@@ -46,7 +46,8 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
|
||||
.tcx
|
||||
.explicit_super_predicates_of(def_id)
|
||||
.iter_identity_copied()
|
||||
.filter_map(|(pred, _)| pred.as_trait_clause());
|
||||
.filter_map(|(pred, _)| pred.as_trait_clause())
|
||||
.filter(|pred| !cx.tcx.is_lang_item(pred.def_id(), hir::LangItem::MetaSized));
|
||||
if direct_super_traits_iter.count() > 1 {
|
||||
cx.emit_span_lint(
|
||||
MULTIPLE_SUPERTRAIT_UPCASTABLE,
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(not(bootstrap), feature(sized_hierarchy))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(allocator_api)]
|
||||
|
||||
@@ -328,6 +328,14 @@ impl Key for (DefId, SimplifiedType) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Key for (DefId, ty::SizedTraitKind) {
|
||||
type Cache<V> = DefaultCache<Self, V>;
|
||||
|
||||
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
|
||||
self.0.default_span(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Key for GenericArgsRef<'tcx> {
|
||||
type Cache<V> = DefaultCache<Self, V>;
|
||||
|
||||
|
||||
@@ -137,8 +137,8 @@ use crate::ty::layout::ValidityRequirement;
|
||||
use crate::ty::print::{PrintTraitRefExt, describe_as_module};
|
||||
use crate::ty::util::AlwaysRequiresDrop;
|
||||
use crate::ty::{
|
||||
self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, Ty, TyCtxt,
|
||||
TyCtxtFeed,
|
||||
self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, SizedTraitKind, Ty,
|
||||
TyCtxt, TyCtxtFeed,
|
||||
};
|
||||
use crate::{dep_graph, mir, thir};
|
||||
|
||||
@@ -910,9 +910,10 @@ rustc_queries! {
|
||||
cache_on_disk_if { key.is_local() }
|
||||
separate_provide_extern
|
||||
}
|
||||
|
||||
query adt_sized_constraint(key: DefId) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
||||
desc { |tcx| "computing the `Sized` constraint for `{}`", tcx.def_path_str(key) }
|
||||
query adt_sizedness_constraint(
|
||||
key: (DefId, SizedTraitKind)
|
||||
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
||||
desc { |tcx| "computing the sizedness constraint for `{}`", tcx.def_path_str(key.0) }
|
||||
}
|
||||
|
||||
query adt_dtorck_constraint(
|
||||
|
||||
@@ -229,8 +229,12 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef<TyCtxt<'tcx>> for AdtDef<'tcx> {
|
||||
)
|
||||
}
|
||||
|
||||
fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
||||
self.sized_constraint(tcx)
|
||||
fn sizedness_constraint(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
sizedness: ty::SizedTraitKind,
|
||||
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
||||
self.sizedness_constraint(tcx, sizedness)
|
||||
}
|
||||
|
||||
fn is_fundamental(self) -> bool {
|
||||
@@ -634,10 +638,15 @@ impl<'tcx> AdtDef<'tcx> {
|
||||
tcx.adt_async_destructor(self.did())
|
||||
}
|
||||
|
||||
/// Returns a type such that `Self: Sized` if and only if that type is `Sized`,
|
||||
/// or `None` if the type is always sized.
|
||||
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
||||
if self.is_struct() { tcx.adt_sized_constraint(self.did()) } else { None }
|
||||
/// If this ADT is a struct, returns a type such that `Self: {Meta,Pointee,}Sized` if and only
|
||||
/// if that type is `{Meta,Pointee,}Sized`, or `None` if this ADT is always
|
||||
/// `{Meta,Pointee,}Sized`.
|
||||
pub fn sizedness_constraint(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
sizedness: ty::SizedTraitKind,
|
||||
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
||||
if self.is_struct() { tcx.adt_sizedness_constraint((self.did(), sizedness)) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ use std::marker::DiscriminantKind;
|
||||
use rustc_abi::{FieldIdx, VariantIdx};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_serialize::{Decodable, Encodable};
|
||||
use rustc_serialize::{Decodable, Encodable, PointeeSized};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{Span, SpanDecoder, SpanEncoder};
|
||||
|
||||
@@ -96,7 +96,7 @@ impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for ty::Predicate
|
||||
///
|
||||
/// `Decodable` can still be implemented in cases where `Decodable` is required
|
||||
/// by a trait bound.
|
||||
pub trait RefDecodable<'tcx, D: TyDecoder<'tcx>> {
|
||||
pub trait RefDecodable<'tcx, D: TyDecoder<'tcx>>: PointeeSized {
|
||||
fn decode(d: &mut D) -> &'tcx Self;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable};
|
||||
use rustc_query_system::cache::WithDepNode;
|
||||
use rustc_query_system::dep_graph::DepNodeIndex;
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_serialize::PointeeSized;
|
||||
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
||||
use rustc_session::config::CrateType;
|
||||
use rustc_session::cstore::{CrateStoreDyn, Untracked};
|
||||
@@ -774,7 +775,9 @@ bidirectional_lang_item_map! {
|
||||
FutureOutput,
|
||||
Iterator,
|
||||
Metadata,
|
||||
MetaSized,
|
||||
Option,
|
||||
PointeeSized,
|
||||
PointeeTrait,
|
||||
Poll,
|
||||
Sized,
|
||||
@@ -1616,16 +1619,17 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
self.reserve_and_set_memory_dedup(alloc, salt)
|
||||
}
|
||||
|
||||
/// Traits added on all bounds by default, excluding `Sized` which is treated separately.
|
||||
pub fn default_traits(self) -> &'static [rustc_hir::LangItem] {
|
||||
match self.sess.opts.unstable_opts.experimental_default_bounds {
|
||||
true => &[
|
||||
LangItem::Sized,
|
||||
if self.sess.opts.unstable_opts.experimental_default_bounds {
|
||||
&[
|
||||
LangItem::DefaultTrait1,
|
||||
LangItem::DefaultTrait2,
|
||||
LangItem::DefaultTrait3,
|
||||
LangItem::DefaultTrait4,
|
||||
],
|
||||
false => &[LangItem::Sized],
|
||||
]
|
||||
} else {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2538,17 +2542,17 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
// this type just holds a pointer to it, but it still effectively owns it. It
|
||||
// impls `Borrow` so that it can be looked up using the original
|
||||
// (non-arena-memory-owning) types.
|
||||
struct InternedInSet<'tcx, T: ?Sized>(&'tcx T);
|
||||
struct InternedInSet<'tcx, T: ?Sized + PointeeSized>(&'tcx T);
|
||||
|
||||
impl<'tcx, T: 'tcx + ?Sized> Clone for InternedInSet<'tcx, T> {
|
||||
impl<'tcx, T: 'tcx + ?Sized + PointeeSized> Clone for InternedInSet<'tcx, T> {
|
||||
fn clone(&self) -> Self {
|
||||
InternedInSet(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: 'tcx + ?Sized> Copy for InternedInSet<'tcx, T> {}
|
||||
impl<'tcx, T: 'tcx + ?Sized + PointeeSized> Copy for InternedInSet<'tcx, T> {}
|
||||
|
||||
impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> {
|
||||
impl<'tcx, T: 'tcx + ?Sized + PointeeSized> IntoPointer for InternedInSet<'tcx, T> {
|
||||
fn into_pointer(&self) -> *const () {
|
||||
self.0 as *const _ as *const ()
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ pub use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
||||
)]
|
||||
use rustc_type_ir::inherent;
|
||||
pub use rustc_type_ir::relate::VarianceDiagInfo;
|
||||
pub use rustc_type_ir::solve::SizedTraitKind;
|
||||
pub use rustc_type_ir::*;
|
||||
#[allow(hidden_glob_reexports, unused_imports)]
|
||||
use rustc_type_ir::{InferCtxtLike, Interner};
|
||||
|
||||
@@ -1069,24 +1069,35 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||
|
||||
let mut traits = FxIndexMap::default();
|
||||
let mut fn_traits = FxIndexMap::default();
|
||||
let mut lifetimes = SmallVec::<[ty::Region<'tcx>; 1]>::new();
|
||||
|
||||
let mut has_sized_bound = false;
|
||||
let mut has_negative_sized_bound = false;
|
||||
let mut lifetimes = SmallVec::<[ty::Region<'tcx>; 1]>::new();
|
||||
let mut has_meta_sized_bound = false;
|
||||
|
||||
for (predicate, _) in bounds.iter_instantiated_copied(tcx, args) {
|
||||
let bound_predicate = predicate.kind();
|
||||
|
||||
match bound_predicate.skip_binder() {
|
||||
ty::ClauseKind::Trait(pred) => {
|
||||
// Don't print `+ Sized`, but rather `+ ?Sized` if absent.
|
||||
if tcx.is_lang_item(pred.def_id(), LangItem::Sized) {
|
||||
match pred.polarity {
|
||||
// With `feature(sized_hierarchy)`, don't print `?Sized` as an alias for
|
||||
// `MetaSized`, and skip sizedness bounds to be added at the end.
|
||||
match tcx.as_lang_item(pred.def_id()) {
|
||||
Some(LangItem::Sized) => match pred.polarity {
|
||||
ty::PredicatePolarity::Positive => {
|
||||
has_sized_bound = true;
|
||||
continue;
|
||||
}
|
||||
ty::PredicatePolarity::Negative => has_negative_sized_bound = true,
|
||||
},
|
||||
Some(LangItem::MetaSized) => {
|
||||
has_meta_sized_bound = true;
|
||||
continue;
|
||||
}
|
||||
Some(LangItem::PointeeSized) => {
|
||||
bug!("`PointeeSized` is removed during lowering");
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.insert_trait_and_projection(
|
||||
@@ -1255,8 +1266,13 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||
})?;
|
||||
}
|
||||
|
||||
let using_sized_hierarchy = self.tcx().features().sized_hierarchy();
|
||||
let add_sized = has_sized_bound && (first || has_negative_sized_bound);
|
||||
let add_maybe_sized = !has_sized_bound && !has_negative_sized_bound;
|
||||
let add_maybe_sized =
|
||||
has_meta_sized_bound && !has_negative_sized_bound && !using_sized_hierarchy;
|
||||
// Set `has_pointee_sized_bound` if there were no `Sized` or `MetaSized` bounds.
|
||||
let has_pointee_sized_bound =
|
||||
!has_sized_bound && !has_meta_sized_bound && !has_negative_sized_bound;
|
||||
if add_sized || add_maybe_sized {
|
||||
if !first {
|
||||
write!(self, " + ")?;
|
||||
@@ -1265,6 +1281,16 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||
write!(self, "?")?;
|
||||
}
|
||||
write!(self, "Sized")?;
|
||||
} else if has_meta_sized_bound && using_sized_hierarchy {
|
||||
if !first {
|
||||
write!(self, " + ")?;
|
||||
}
|
||||
write!(self, "MetaSized")?;
|
||||
} else if has_pointee_sized_bound && using_sized_hierarchy {
|
||||
if !first {
|
||||
write!(self, " + ")?;
|
||||
}
|
||||
write!(self, "PointeeSized")?;
|
||||
}
|
||||
|
||||
if !with_forced_trimmed_paths() {
|
||||
|
||||
@@ -15,6 +15,7 @@ use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, extension};
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
||||
use rustc_type_ir::TyKind::*;
|
||||
use rustc_type_ir::solve::SizedTraitKind;
|
||||
use rustc_type_ir::walk::TypeWalker;
|
||||
use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind, TypeVisitableExt, elaborate};
|
||||
use tracing::instrument;
|
||||
@@ -1677,7 +1678,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
let Some(pointee_ty) = self.builtin_deref(true) else {
|
||||
bug!("Type {self:?} is not a pointer or reference type")
|
||||
};
|
||||
if pointee_ty.is_trivially_sized(tcx) {
|
||||
if pointee_ty.has_trivial_sizedness(tcx, SizedTraitKind::Sized) {
|
||||
tcx.types.unit
|
||||
} else {
|
||||
match pointee_ty.ptr_metadata_ty_or_tail(tcx, |x| x) {
|
||||
@@ -1778,17 +1779,17 @@ impl<'tcx> Ty<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Fast path helper for testing if a type is `Sized`.
|
||||
/// Fast path helper for testing if a type is `Sized` or `MetaSized`.
|
||||
///
|
||||
/// Returning true means the type is known to implement `Sized`. Returning `false` means
|
||||
/// nothing -- could be sized, might not be.
|
||||
/// Returning true means the type is known to implement the sizedness trait. Returning `false`
|
||||
/// means nothing -- could be sized, might not be.
|
||||
///
|
||||
/// Note that we could never rely on the fact that a type such as `[_]` is trivially `!Sized`
|
||||
/// because we could be in a type environment with a bound such as `[_]: Copy`. A function with
|
||||
/// such a bound obviously never can be called, but that doesn't mean it shouldn't typecheck.
|
||||
/// This is why this method doesn't return `Option<bool>`.
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
pub fn is_trivially_sized(self, tcx: TyCtxt<'tcx>) -> bool {
|
||||
pub fn has_trivial_sizedness(self, tcx: TyCtxt<'tcx>, sizedness: SizedTraitKind) -> bool {
|
||||
match self.kind() {
|
||||
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||
| ty::Uint(_)
|
||||
@@ -1811,13 +1812,20 @@ impl<'tcx> Ty<'tcx> {
|
||||
| ty::Error(_)
|
||||
| ty::Dynamic(_, _, ty::DynStar) => true,
|
||||
|
||||
ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false,
|
||||
ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) => match sizedness {
|
||||
SizedTraitKind::Sized => false,
|
||||
SizedTraitKind::MetaSized => true,
|
||||
},
|
||||
|
||||
ty::Tuple(tys) => tys.last().is_none_or(|ty| ty.is_trivially_sized(tcx)),
|
||||
ty::Foreign(..) => match sizedness {
|
||||
SizedTraitKind::Sized | SizedTraitKind::MetaSized => false,
|
||||
},
|
||||
|
||||
ty::Tuple(tys) => tys.last().is_none_or(|ty| ty.has_trivial_sizedness(tcx, sizedness)),
|
||||
|
||||
ty::Adt(def, args) => def
|
||||
.sized_constraint(tcx)
|
||||
.is_none_or(|ty| ty.instantiate(tcx, args).is_trivially_sized(tcx)),
|
||||
.sizedness_constraint(tcx, sizedness)
|
||||
.is_none_or(|ty| ty.instantiate(tcx, args).has_trivial_sizedness(tcx, sizedness)),
|
||||
|
||||
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) | ty::Bound(..) => false,
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ use rustc_index::bit_set::GrowableBitSet;
|
||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension};
|
||||
use rustc_session::Limit;
|
||||
use rustc_span::sym;
|
||||
use rustc_type_ir::solve::SizedTraitKind;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
@@ -1132,7 +1133,8 @@ impl<'tcx> Ty<'tcx> {
|
||||
/// strange rules like `<T as Foo<'static>>::Bar: Sized` that
|
||||
/// actually carry lifetime requirements.
|
||||
pub fn is_sized(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool {
|
||||
self.is_trivially_sized(tcx) || tcx.is_sized_raw(typing_env.as_query_input(self))
|
||||
self.has_trivial_sizedness(tcx, SizedTraitKind::Sized)
|
||||
|| tcx.is_sized_raw(typing_env.as_query_input(self))
|
||||
}
|
||||
|
||||
/// Checks whether values of this type `T` implement the `Freeze`
|
||||
|
||||
@@ -8,6 +8,7 @@ use std::ops::ControlFlow;
|
||||
use derive_where::derive_where;
|
||||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||
use rustc_type_ir::solve::SizedTraitKind;
|
||||
use rustc_type_ir::{
|
||||
self as ty, Interner, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt as _,
|
||||
TypeVisitor, TypingMode, Upcast as _, elaborate,
|
||||
@@ -203,13 +204,15 @@ where
|
||||
goal: Goal<I, Self>,
|
||||
) -> Result<Candidate<I>, NoSolution>;
|
||||
|
||||
/// A type is `Sized` if its tail component is `Sized`.
|
||||
/// A type is `Sized` if its tail component is `Sized` and a type is `MetaSized` if its tail
|
||||
/// component is `MetaSized`.
|
||||
///
|
||||
/// These components are given by built-in rules from
|
||||
/// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
|
||||
fn consider_builtin_sized_candidate(
|
||||
/// [`structural_traits::instantiate_constituent_tys_for_sizedness_trait`].
|
||||
fn consider_builtin_sizedness_candidates(
|
||||
ecx: &mut EvalCtxt<'_, D>,
|
||||
goal: Goal<I, Self>,
|
||||
sizedness: SizedTraitKind,
|
||||
) -> Result<Candidate<I>, NoSolution>;
|
||||
|
||||
/// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`.
|
||||
@@ -466,7 +469,15 @@ where
|
||||
G::consider_trait_alias_candidate(self, goal)
|
||||
} else {
|
||||
match cx.as_lang_item(trait_def_id) {
|
||||
Some(TraitSolverLangItem::Sized) => G::consider_builtin_sized_candidate(self, goal),
|
||||
Some(TraitSolverLangItem::Sized) => {
|
||||
G::consider_builtin_sizedness_candidates(self, goal, SizedTraitKind::Sized)
|
||||
}
|
||||
Some(TraitSolverLangItem::MetaSized) => {
|
||||
G::consider_builtin_sizedness_candidates(self, goal, SizedTraitKind::MetaSized)
|
||||
}
|
||||
Some(TraitSolverLangItem::PointeeSized) => {
|
||||
unreachable!("`PointeeSized` is removed during lowering");
|
||||
}
|
||||
Some(TraitSolverLangItem::Copy | TraitSolverLangItem::Clone) => {
|
||||
G::consider_builtin_copy_clone_candidate(self, goal)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ use derive_where::derive_where;
|
||||
use rustc_type_ir::data_structures::HashMap;
|
||||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||
use rustc_type_ir::solve::SizedTraitKind;
|
||||
use rustc_type_ir::solve::inspect::ProbeKind;
|
||||
use rustc_type_ir::{
|
||||
self as ty, FallibleTypeFolder, Interner, Movability, Mutability, TypeFoldable,
|
||||
@@ -104,8 +105,9 @@ where
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(ecx), ret)]
|
||||
pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<D, I>(
|
||||
pub(in crate::solve) fn instantiate_constituent_tys_for_sizedness_trait<D, I>(
|
||||
ecx: &EvalCtxt<'_, D>,
|
||||
sizedness: SizedTraitKind,
|
||||
ty: I::Ty,
|
||||
) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
|
||||
where
|
||||
@@ -113,8 +115,9 @@ where
|
||||
I: Interner,
|
||||
{
|
||||
match ty.kind() {
|
||||
// impl Sized for u*, i*, bool, f*, FnDef, FnPtr, *(const/mut) T, char, &mut? T, [T; N], dyn* Trait, !
|
||||
// impl Sized for Coroutine, CoroutineWitness, Closure, CoroutineClosure
|
||||
// impl {Meta,}Sized for u*, i*, bool, f*, FnDef, FnPtr, *(const/mut) T, char
|
||||
// impl {Meta,}Sized for &mut? T, [T; N], dyn* Trait, !, Coroutine, CoroutineWitness
|
||||
// impl {Meta,}Sized for Closure, CoroutineClosure
|
||||
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||
| ty::Uint(_)
|
||||
| ty::Int(_)
|
||||
@@ -135,13 +138,16 @@ where
|
||||
| ty::Dynamic(_, _, ty::DynStar)
|
||||
| ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
|
||||
|
||||
ty::Str
|
||||
| ty::Slice(_)
|
||||
| ty::Dynamic(..)
|
||||
| ty::Foreign(..)
|
||||
| ty::Alias(..)
|
||||
| ty::Param(_)
|
||||
| ty::Placeholder(..) => Err(NoSolution),
|
||||
// impl {Meta,}Sized for str, [T], dyn Trait
|
||||
ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
|
||||
SizedTraitKind::Sized => Err(NoSolution),
|
||||
SizedTraitKind::MetaSized => Ok(ty::Binder::dummy(vec![])),
|
||||
},
|
||||
|
||||
// impl {} for extern type
|
||||
ty::Foreign(..) => Err(NoSolution),
|
||||
|
||||
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => Err(NoSolution),
|
||||
|
||||
ty::Bound(..)
|
||||
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||
@@ -150,22 +156,27 @@ where
|
||||
|
||||
ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
|
||||
|
||||
// impl Sized for ()
|
||||
// impl Sized for (T1, T2, .., Tn) where Tn: Sized if n >= 1
|
||||
// impl {Meta,}Sized for ()
|
||||
// impl {Meta,}Sized for (T1, T2, .., Tn) where Tn: {Meta,}Sized if n >= 1
|
||||
ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.last().map_or_else(Vec::new, |ty| vec![ty]))),
|
||||
|
||||
// impl Sized for Adt<Args...> where sized_constraint(Adt)<Args...>: Sized
|
||||
// `sized_constraint(Adt)` is the deepest struct trail that can be determined
|
||||
// by the definition of `Adt`, independent of the generic args.
|
||||
// impl Sized for Adt<Args...> if sized_constraint(Adt) == None
|
||||
// As a performance optimization, `sized_constraint(Adt)` can return `None`
|
||||
// if the ADTs definition implies that it is sized by for all possible args.
|
||||
// impl {Meta,}Sized for Adt<Args...>
|
||||
// where {meta,pointee,}sized_constraint(Adt)<Args...>: {Meta,}Sized
|
||||
//
|
||||
// `{meta,pointee,}sized_constraint(Adt)` is the deepest struct trail that can be
|
||||
// determined by the definition of `Adt`, independent of the generic args.
|
||||
//
|
||||
// impl {Meta,}Sized for Adt<Args...>
|
||||
// if {meta,pointee,}sized_constraint(Adt) == None
|
||||
//
|
||||
// As a performance optimization, `{meta,pointee,}sized_constraint(Adt)` can return `None`
|
||||
// if the ADTs definition implies that it is {meta,}sized by for all possible args.
|
||||
// In this case, the builtin impl will have no nested subgoals. This is a
|
||||
// "best effort" optimization and `sized_constraint` may return `Some`, even
|
||||
// if the ADT is sized for all possible args.
|
||||
// "best effort" optimization and `{meta,pointee,}sized_constraint` may return `Some`,
|
||||
// even if the ADT is {meta,pointee,}sized for all possible args.
|
||||
ty::Adt(def, args) => {
|
||||
if let Some(sized_crit) = def.sized_constraint(ecx.cx()) {
|
||||
Ok(ty::Binder::dummy(vec![sized_crit.instantiate(ecx.cx(), args)]))
|
||||
if let Some(crit) = def.sizedness_constraint(ecx.cx(), sizedness) {
|
||||
Ok(ty::Binder::dummy(vec![crit.instantiate(ecx.cx(), args)]))
|
||||
} else {
|
||||
Ok(ty::Binder::dummy(vec![]))
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
||||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||
use rustc_type_ir::solve::SizedTraitKind;
|
||||
use rustc_type_ir::solve::inspect::ProbeKind;
|
||||
use rustc_type_ir::{self as ty, Interner, elaborate};
|
||||
use tracing::instrument;
|
||||
@@ -198,11 +199,12 @@ where
|
||||
unreachable!("trait aliases are never const")
|
||||
}
|
||||
|
||||
fn consider_builtin_sized_candidate(
|
||||
fn consider_builtin_sizedness_candidates(
|
||||
_ecx: &mut EvalCtxt<'_, D>,
|
||||
_goal: Goal<I, Self>,
|
||||
_sizedness: SizedTraitKind,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
unreachable!("Sized is never const")
|
||||
unreachable!("Sized/MetaSized is never const")
|
||||
}
|
||||
|
||||
fn consider_builtin_copy_clone_candidate(
|
||||
|
||||
@@ -6,6 +6,7 @@ mod opaque_types;
|
||||
use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
||||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||
use rustc_type_ir::solve::SizedTraitKind;
|
||||
use rustc_type_ir::{self as ty, Interner, NormalizesTo, PredicateKind, Upcast as _};
|
||||
use tracing::instrument;
|
||||
|
||||
@@ -413,11 +414,12 @@ where
|
||||
panic!("trait aliases do not have associated types: {:?}", goal);
|
||||
}
|
||||
|
||||
fn consider_builtin_sized_candidate(
|
||||
fn consider_builtin_sizedness_candidates(
|
||||
_ecx: &mut EvalCtxt<'_, D>,
|
||||
goal: Goal<I, Self>,
|
||||
_sizedness: SizedTraitKind,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
panic!("`Sized` does not have an associated type: {:?}", goal);
|
||||
panic!("`Sized`/`MetaSized` does not have an associated type: {:?}", goal);
|
||||
}
|
||||
|
||||
fn consider_builtin_copy_clone_candidate(
|
||||
|
||||
@@ -4,9 +4,9 @@ use rustc_type_ir::data_structures::IndexSet;
|
||||
use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
||||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||
use rustc_type_ir::solve::CanonicalResponse;
|
||||
use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind};
|
||||
use rustc_type_ir::{
|
||||
self as ty, Interner, Movability, TraitPredicate, TypeVisitableExt as _, TypingMode,
|
||||
self as ty, Interner, Movability, TraitPredicate, TraitRef, TypeVisitableExt as _, TypingMode,
|
||||
Upcast as _, elaborate,
|
||||
};
|
||||
use tracing::{debug, instrument, trace};
|
||||
@@ -131,9 +131,11 @@ where
|
||||
assumption: I::Clause,
|
||||
) -> Result<(), NoSolution> {
|
||||
if let Some(trait_clause) = assumption.as_trait_clause() {
|
||||
if trait_clause.def_id() == goal.predicate.def_id()
|
||||
&& trait_clause.polarity() == goal.predicate.polarity
|
||||
{
|
||||
if trait_clause.polarity() != goal.predicate.polarity {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
if trait_clause.def_id() == goal.predicate.def_id() {
|
||||
if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
|
||||
goal.predicate.trait_ref.args,
|
||||
trait_clause.skip_binder().trait_ref.args,
|
||||
@@ -141,6 +143,17 @@ where
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
// PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so
|
||||
// check for a `Sized` subtrait when looking for `MetaSized`. `PointeeSized` bounds
|
||||
// are syntactic sugar for a lack of bounds so don't need this.
|
||||
if ecx.cx().is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::MetaSized)
|
||||
&& ecx.cx().is_lang_item(trait_clause.def_id(), TraitSolverLangItem::Sized)
|
||||
{
|
||||
let meta_sized_clause =
|
||||
trait_predicate_with_def_id(ecx.cx(), trait_clause, goal.predicate.def_id());
|
||||
return Self::fast_reject_assumption(ecx, goal, meta_sized_clause);
|
||||
}
|
||||
}
|
||||
|
||||
Err(NoSolution)
|
||||
@@ -154,6 +167,17 @@ where
|
||||
) -> QueryResult<I> {
|
||||
let trait_clause = assumption.as_trait_clause().unwrap();
|
||||
|
||||
// PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so
|
||||
// check for a `Sized` subtrait when looking for `MetaSized`. `PointeeSized` bounds
|
||||
// are syntactic sugar for a lack of bounds so don't need this.
|
||||
if ecx.cx().is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::MetaSized)
|
||||
&& ecx.cx().is_lang_item(trait_clause.def_id(), TraitSolverLangItem::Sized)
|
||||
{
|
||||
let meta_sized_clause =
|
||||
trait_predicate_with_def_id(ecx.cx(), trait_clause, goal.predicate.def_id());
|
||||
return Self::match_assumption(ecx, goal, meta_sized_clause, then);
|
||||
}
|
||||
|
||||
let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
|
||||
ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?;
|
||||
|
||||
@@ -245,9 +269,10 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
fn consider_builtin_sized_candidate(
|
||||
fn consider_builtin_sizedness_candidates(
|
||||
ecx: &mut EvalCtxt<'_, D>,
|
||||
goal: Goal<I, Self>,
|
||||
sizedness: SizedTraitKind,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
return Err(NoSolution);
|
||||
@@ -256,7 +281,11 @@ where
|
||||
ecx.probe_and_evaluate_goal_for_constituent_tys(
|
||||
CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
|
||||
goal,
|
||||
structural_traits::instantiate_constituent_tys_for_sized_trait,
|
||||
|ecx, ty| {
|
||||
structural_traits::instantiate_constituent_tys_for_sizedness_trait(
|
||||
ecx, sizedness, ty,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -812,6 +841,25 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Small helper function to change the `def_id` of a trait predicate - this is not normally
|
||||
/// something that you want to do, as different traits will require different args and so making
|
||||
/// it easy to change the trait is something of a footgun, but it is useful in the narrow
|
||||
/// circumstance of changing from `MetaSized` to `Sized`, which happens as part of the lazy
|
||||
/// elaboration of sizedness candidates.
|
||||
#[inline(always)]
|
||||
fn trait_predicate_with_def_id<I: Interner>(
|
||||
cx: I,
|
||||
clause: ty::Binder<I, ty::TraitPredicate<I>>,
|
||||
did: I::DefId,
|
||||
) -> I::Clause {
|
||||
clause
|
||||
.map_bound(|c| TraitPredicate {
|
||||
trait_ref: TraitRef::new_from_args(cx, did, c.trait_ref.args),
|
||||
polarity: c.polarity,
|
||||
})
|
||||
.upcast(cx)
|
||||
}
|
||||
|
||||
impl<D, I> EvalCtxt<'_, D>
|
||||
where
|
||||
D: SolverDelegate<Interner = I>,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::internal)]
|
||||
#![cfg_attr(not(bootstrap), feature(sized_hierarchy))]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
#![doc(
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
||||
@@ -27,3 +28,19 @@ mod serialize;
|
||||
pub mod int_overflow;
|
||||
pub mod leb128;
|
||||
pub mod opaque;
|
||||
|
||||
// This has nothing to do with `rustc_serialize` but it is convenient to define it in one place
|
||||
// for the rest of the compiler so that `cfg(bootstrap)` doesn't need to be littered throughout
|
||||
// the compiler wherever `PointeeSized` would be used. `rustc_serialize` happens to be the deepest
|
||||
// crate in the crate graph which uses `PointeeSized`.
|
||||
//
|
||||
// When bootstrap bumps, remove both the `cfg(not(bootstrap))` and `cfg(bootstrap)` lines below
|
||||
// and just import `std::marker::PointeeSized` whereever this item was used.
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
pub use std::marker::PointeeSized;
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
pub trait PointeeSized {}
|
||||
#[cfg(bootstrap)]
|
||||
impl<T: ?Sized> PointeeSized for T {}
|
||||
|
||||
@@ -142,7 +142,7 @@ pub trait Decoder {
|
||||
/// `rustc_metadata::rmeta::Lazy`.
|
||||
/// * `TyEncodable` should be used for types that are only serialized in crate
|
||||
/// metadata or the incremental cache. This is most types in `rustc_middle`.
|
||||
pub trait Encodable<S: Encoder> {
|
||||
pub trait Encodable<S: Encoder>: crate::PointeeSized {
|
||||
fn encode(&self, s: &mut S);
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ direct_serialize_impls! {
|
||||
char emit_char read_char
|
||||
}
|
||||
|
||||
impl<S: Encoder, T: ?Sized> Encodable<S> for &T
|
||||
impl<S: Encoder, T: ?Sized + crate::PointeeSized> Encodable<S> for &T
|
||||
where
|
||||
T: Encodable<S>,
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::usage_of_ty_tykind)]
|
||||
#![cfg_attr(not(bootstrap), feature(sized_hierarchy))]
|
||||
#![doc(
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
||||
test(attr(allow(unused_variables), deny(warnings)))
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
use rustc_data_structures::PointeeSized;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::AllocId;
|
||||
@@ -158,7 +159,7 @@ pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind {
|
||||
}
|
||||
|
||||
/// Trait used to convert between an internal MIR type to a Stable MIR type.
|
||||
pub trait Stable<'cx> {
|
||||
pub trait Stable<'cx>: PointeeSized {
|
||||
/// The stable representation of the type implementing Stable.
|
||||
type T;
|
||||
/// Converts an object to the equivalent Stable MIR representation.
|
||||
|
||||
@@ -1355,6 +1355,7 @@ symbols! {
|
||||
memtag,
|
||||
message,
|
||||
meta,
|
||||
meta_sized,
|
||||
metadata_type,
|
||||
min_const_fn,
|
||||
min_const_generics,
|
||||
@@ -1613,6 +1614,7 @@ symbols! {
|
||||
plugin_registrar,
|
||||
plugins,
|
||||
pointee,
|
||||
pointee_sized,
|
||||
pointee_trait,
|
||||
pointer,
|
||||
pointer_like,
|
||||
@@ -2016,6 +2018,7 @@ symbols! {
|
||||
size_of,
|
||||
size_of_val,
|
||||
sized,
|
||||
sized_hierarchy,
|
||||
skip,
|
||||
slice,
|
||||
slice_from_raw_parts,
|
||||
|
||||
@@ -199,7 +199,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
// avoid inundating the user with unnecessary errors, but we now
|
||||
// check upstream for type errors and don't add the obligations to
|
||||
// begin with in those cases.
|
||||
if self.tcx.is_lang_item(trait_pred.def_id(), LangItem::Sized) {
|
||||
if matches!(
|
||||
self.tcx.as_lang_item(trait_pred.def_id()),
|
||||
Some(LangItem::Sized | LangItem::MetaSized)
|
||||
) {
|
||||
match self.tainted_by_errors() {
|
||||
None => {
|
||||
let err = self.emit_inference_failure_err(
|
||||
|
||||
@@ -13,7 +13,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::{Applicability, Diag, E0038, E0276, MultiSpan, struct_span_code_err};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::{self as hir, AmbigArg, LangItem};
|
||||
use rustc_hir::{self as hir, AmbigArg};
|
||||
use rustc_infer::traits::solve::Goal;
|
||||
use rustc_infer::traits::{
|
||||
DynCompatibilityViolation, Obligation, ObligationCause, ObligationCauseCode,
|
||||
@@ -160,17 +160,24 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Ensure `T: Sized` and `T: WF` obligations come last. This lets us display diagnostics
|
||||
// with more relevant type information and hide redundant E0282 errors.
|
||||
errors.sort_by_key(|e| match e.obligation.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
|
||||
if self.tcx.is_lang_item(pred.def_id(), LangItem::Sized) =>
|
||||
{
|
||||
1
|
||||
}
|
||||
ty::PredicateKind::Coerce(_) => 2,
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => 3,
|
||||
// Ensure `T: Sized`, `T: MetaSized`, `T: PointeeSized` and `T: WF` obligations come last.
|
||||
// This lets us display diagnostics with more relevant type information and hide redundant
|
||||
// E0282 errors.
|
||||
errors.sort_by_key(|e| {
|
||||
let maybe_sizedness_did = match e.obligation.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => Some(pred.def_id()),
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(pred)) => Some(pred.def_id()),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
match e.obligation.predicate.kind().skip_binder() {
|
||||
_ if maybe_sizedness_did == self.tcx.lang_items().sized_trait() => 1,
|
||||
_ if maybe_sizedness_did == self.tcx.lang_items().meta_sized_trait() => 2,
|
||||
_ if maybe_sizedness_did == self.tcx.lang_items().pointee_sized_trait() => 3,
|
||||
ty::PredicateKind::Coerce(_) => 4,
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => 5,
|
||||
_ => 0,
|
||||
}
|
||||
});
|
||||
|
||||
for (index, error) in errors.iter().enumerate() {
|
||||
@@ -327,19 +334,26 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
|
||||
let trait_ref = tcx.impl_trait_ref(impl_def_id)?.instantiate_identity();
|
||||
let mut w = "impl".to_owned();
|
||||
|
||||
let args = ty::GenericArgs::identity_for_item(tcx, impl_def_id);
|
||||
#[derive(Debug, Default)]
|
||||
struct SizednessFound {
|
||||
sized: bool,
|
||||
meta_sized: bool,
|
||||
}
|
||||
|
||||
// FIXME: Currently only handles ?Sized.
|
||||
// Needs to support ?Move and ?DynSized when they are implemented.
|
||||
let mut types_without_default_bounds = FxIndexSet::default();
|
||||
let sized_trait = tcx.lang_items().sized_trait();
|
||||
let mut types_with_sizedness_bounds = FxIndexMap::<_, SizednessFound>::default();
|
||||
|
||||
let args = ty::GenericArgs::identity_for_item(tcx, impl_def_id);
|
||||
|
||||
let arg_names = args.iter().map(|k| k.to_string()).filter(|k| k != "'_").collect::<Vec<_>>();
|
||||
if !arg_names.is_empty() {
|
||||
types_without_default_bounds.extend(args.types());
|
||||
w.push('<');
|
||||
w.push_str(&arg_names.join(", "));
|
||||
w.push('>');
|
||||
|
||||
for ty in args.types() {
|
||||
// `PointeeSized` params might have no predicates.
|
||||
types_with_sizedness_bounds.insert(ty, SizednessFound::default());
|
||||
}
|
||||
}
|
||||
|
||||
write!(
|
||||
@@ -351,24 +365,47 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The predicates will contain default bounds like `T: Sized`. We need to
|
||||
// remove these bounds, and add `T: ?Sized` to any untouched type parameters.
|
||||
let predicates = tcx.predicates_of(impl_def_id).predicates;
|
||||
let mut pretty_predicates =
|
||||
Vec::with_capacity(predicates.len() + types_without_default_bounds.len());
|
||||
let mut pretty_predicates = Vec::with_capacity(predicates.len());
|
||||
|
||||
let sized_trait = tcx.lang_items().sized_trait();
|
||||
let meta_sized_trait = tcx.lang_items().meta_sized_trait();
|
||||
|
||||
for (p, _) in predicates {
|
||||
if let Some(poly_trait_ref) = p.as_trait_clause() {
|
||||
if Some(poly_trait_ref.def_id()) == sized_trait {
|
||||
// FIXME(#120456) - is `swap_remove` correct?
|
||||
types_without_default_bounds.swap_remove(&poly_trait_ref.self_ty().skip_binder());
|
||||
// Accumulate the sizedness bounds for each self ty.
|
||||
if let Some(trait_clause) = p.as_trait_clause() {
|
||||
let self_ty = trait_clause.self_ty().skip_binder();
|
||||
let sizedness_of = types_with_sizedness_bounds.entry(self_ty).or_default();
|
||||
if Some(trait_clause.def_id()) == sized_trait {
|
||||
sizedness_of.sized = true;
|
||||
continue;
|
||||
} else if Some(trait_clause.def_id()) == meta_sized_trait {
|
||||
sizedness_of.meta_sized = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
pretty_predicates.push(p.to_string());
|
||||
}
|
||||
|
||||
pretty_predicates.extend(types_without_default_bounds.iter().map(|ty| format!("{ty}: ?Sized")));
|
||||
for (ty, sizedness) in types_with_sizedness_bounds {
|
||||
if !tcx.features().sized_hierarchy() {
|
||||
if sizedness.sized {
|
||||
// Maybe a default bound, don't write anything.
|
||||
} else {
|
||||
pretty_predicates.push(format!("{ty}: ?Sized"));
|
||||
}
|
||||
} else {
|
||||
if sizedness.sized {
|
||||
// Maybe a default bound, don't write anything.
|
||||
pretty_predicates.push(format!("{ty}: Sized"));
|
||||
} else if sizedness.meta_sized {
|
||||
pretty_predicates.push(format!("{ty}: MetaSized"));
|
||||
} else {
|
||||
pretty_predicates.push(format!("{ty}: PointeeSized"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !pretty_predicates.is_empty() {
|
||||
write!(w, "\n where {}", pretty_predicates.join(", ")).unwrap();
|
||||
@@ -519,7 +556,7 @@ fn attempt_dyn_to_enum_suggestion(
|
||||
let Some(impl_type) = tcx.type_of(*impl_id).no_bound_vars() else { return None };
|
||||
|
||||
// Obviously unsized impl types won't be usable in an enum.
|
||||
// Note: this doesn't use `Ty::is_trivially_sized` because that function
|
||||
// Note: this doesn't use `Ty::has_trivial_sizedness` because that function
|
||||
// defaults to assuming that things are *not* sized, whereas we want to
|
||||
// fall back to assuming that things may be sized.
|
||||
match impl_type.kind() {
|
||||
|
||||
@@ -12,7 +12,7 @@ use rustc_infer::traits::solve::Goal;
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::traits::solve::Certainty;
|
||||
use rustc_middle::ty::{
|
||||
self, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt as _, TypingMode,
|
||||
self, SizedTraitKind, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt as _, TypingMode,
|
||||
};
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
|
||||
|
||||
@@ -79,7 +79,14 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
||||
Some(LangItem::Sized)
|
||||
if self
|
||||
.resolve_vars_if_possible(trait_pred.self_ty().skip_binder())
|
||||
.is_trivially_sized(self.0.tcx) =>
|
||||
.has_trivial_sizedness(self.0.tcx, SizedTraitKind::Sized) =>
|
||||
{
|
||||
return Some(Certainty::Yes);
|
||||
}
|
||||
Some(LangItem::MetaSized)
|
||||
if self
|
||||
.resolve_vars_if_possible(trait_pred.self_ty().skip_binder())
|
||||
.has_trivial_sizedness(self.0.tcx, SizedTraitKind::MetaSized) =>
|
||||
{
|
||||
return Some(Certainty::Yes);
|
||||
}
|
||||
|
||||
@@ -462,6 +462,7 @@ fn impl_intersection_has_negative_obligation(
|
||||
let param_env = infcx.resolve_vars_if_possible(param_env);
|
||||
|
||||
util::elaborate(tcx, tcx.predicates_of(impl2_def_id).instantiate(tcx, impl2_header.impl_args))
|
||||
.elaborate_sized()
|
||||
.any(|(clause, _)| try_prove_negated_where_clause(infcx, clause, param_env))
|
||||
}
|
||||
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use rustc_errors::FatalError;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{
|
||||
self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
|
||||
elaborate,
|
||||
};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use smallvec::SmallVec;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
@@ -543,11 +543,11 @@ fn receiver_for_self_ty<'tcx>(
|
||||
/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result in
|
||||
/// a new check that `Trait` is dyn-compatible, creating a cycle.
|
||||
/// Instead, we emulate a placeholder by introducing a new type parameter `U` such that
|
||||
/// `Self: Unsize<U>` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`.
|
||||
/// `Self: Unsize<U>` and `U: Trait + MetaSized`, and use `U` in place of `dyn Trait`.
|
||||
///
|
||||
/// Written as a chalk-style query:
|
||||
/// ```ignore (not-rust)
|
||||
/// forall (U: Trait + ?Sized) {
|
||||
/// forall (U: Trait + MetaSized) {
|
||||
/// if (Self: Unsize<U>) {
|
||||
/// Receiver: DispatchFromDyn<Receiver[Self => U]>
|
||||
/// }
|
||||
@@ -567,9 +567,10 @@ fn receiver_is_dispatchable<'tcx>(
|
||||
) -> bool {
|
||||
debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
|
||||
|
||||
let traits = (tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait());
|
||||
let (Some(unsize_did), Some(dispatch_from_dyn_did)) = traits else {
|
||||
debug!("receiver_is_dispatchable: Missing Unsize or DispatchFromDyn traits");
|
||||
let (Some(unsize_did), Some(dispatch_from_dyn_did)) =
|
||||
(tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait())
|
||||
else {
|
||||
debug!("receiver_is_dispatchable: Missing `Unsize` or `DispatchFromDyn` traits");
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -583,7 +584,7 @@ fn receiver_is_dispatchable<'tcx>(
|
||||
receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
|
||||
|
||||
// create a modified param env, with `Self: Unsize<U>` and `U: Trait` (and all of
|
||||
// its supertraits) added to caller bounds. `U: ?Sized` is already implied here.
|
||||
// its supertraits) added to caller bounds. `U: MetaSized` is already implied here.
|
||||
let param_env = {
|
||||
// N.B. We generally want to emulate the construction of the `unnormalized_param_env`
|
||||
// in the param-env query here. The fact that we don't just start with the clauses
|
||||
@@ -612,6 +613,12 @@ fn receiver_is_dispatchable<'tcx>(
|
||||
let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args);
|
||||
predicates.push(trait_predicate.upcast(tcx));
|
||||
|
||||
let meta_sized_predicate = {
|
||||
let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, DUMMY_SP);
|
||||
ty::TraitRef::new(tcx, meta_sized_did, [unsized_self_ty]).upcast(tcx)
|
||||
};
|
||||
predicates.push(meta_sized_predicate);
|
||||
|
||||
normalize_param_env_or_error(
|
||||
tcx,
|
||||
ty::ParamEnv::new(tcx.mk_clauses(&predicates)),
|
||||
|
||||
@@ -14,7 +14,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
|
||||
use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind};
|
||||
use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
|
||||
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
|
||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode, elaborate};
|
||||
use rustc_middle::ty::{self, SizedTraitKind, Ty, TypeVisitableExt, TypingMode, elaborate};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
@@ -87,7 +87,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
candidates.vec.push(BuiltinCandidate { has_nested: false });
|
||||
}
|
||||
Some(LangItem::Sized) => {
|
||||
self.assemble_builtin_sized_candidate(obligation, &mut candidates);
|
||||
self.assemble_builtin_sized_candidate(
|
||||
obligation,
|
||||
&mut candidates,
|
||||
SizedTraitKind::Sized,
|
||||
);
|
||||
}
|
||||
Some(LangItem::MetaSized) => {
|
||||
self.assemble_builtin_sized_candidate(
|
||||
obligation,
|
||||
&mut candidates,
|
||||
SizedTraitKind::MetaSized,
|
||||
);
|
||||
}
|
||||
Some(LangItem::PointeeSized) => {
|
||||
bug!("`PointeeSized` is removed during lowering");
|
||||
}
|
||||
Some(LangItem::Unsize) => {
|
||||
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
|
||||
@@ -201,6 +215,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
selcx.infcx.probe(|_| {
|
||||
let bound = util::lazily_elaborate_sizedness_candidate(
|
||||
selcx.infcx,
|
||||
obligation,
|
||||
bound,
|
||||
);
|
||||
|
||||
// We checked the polarity already
|
||||
match selcx.match_normalize_trait_ref(
|
||||
obligation,
|
||||
@@ -245,14 +265,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
.caller_bounds()
|
||||
.iter()
|
||||
.filter_map(|p| p.as_trait_clause())
|
||||
// Micro-optimization: filter out predicates relating to different traits.
|
||||
.filter(|p| p.def_id() == stack.obligation.predicate.def_id())
|
||||
// Micro-optimization: filter out predicates with different polarities.
|
||||
.filter(|p| p.polarity() == stack.obligation.predicate.polarity());
|
||||
|
||||
let drcx = DeepRejectCtxt::relate_rigid_rigid(self.tcx());
|
||||
let obligation_args = stack.obligation.predicate.skip_binder().trait_ref.args;
|
||||
// Keep only those bounds which may apply, and propagate overflow if it occurs.
|
||||
for bound in bounds {
|
||||
let bound =
|
||||
util::lazily_elaborate_sizedness_candidate(self.infcx, stack.obligation, bound);
|
||||
|
||||
// Micro-optimization: filter out predicates relating to different traits.
|
||||
if bound.def_id() != stack.obligation.predicate.def_id() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let bound_trait_ref = bound.map_bound(|t| t.trait_ref);
|
||||
if !drcx.args_may_unify(obligation_args, bound_trait_ref.skip_binder().args) {
|
||||
continue;
|
||||
@@ -1086,15 +1113,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Assembles the trait which are built-in to the language itself:
|
||||
/// `Copy`, `Clone` and `Sized`.
|
||||
/// Assembles the `Sized` and `MetaSized` traits which are built-in to the language itself.
|
||||
#[instrument(level = "debug", skip(self, candidates))]
|
||||
fn assemble_builtin_sized_candidate(
|
||||
&mut self,
|
||||
obligation: &PolyTraitObligation<'tcx>,
|
||||
candidates: &mut SelectionCandidateSet<'tcx>,
|
||||
sizedness: SizedTraitKind,
|
||||
) {
|
||||
match self.sized_conditions(obligation) {
|
||||
match self.sizedness_conditions(obligation, sizedness) {
|
||||
BuiltinImplConditions::Where(nested) => {
|
||||
candidates
|
||||
.vec
|
||||
|
||||
@@ -14,7 +14,9 @@ use rustc_hir::lang_items::LangItem;
|
||||
use rustc_infer::infer::{DefineOpaqueTypes, HigherRankedType, InferOk};
|
||||
use rustc_infer::traits::ObligationCauseCode;
|
||||
use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData};
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, Upcast, elaborate};
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgsRef, Region, SizedTraitKind, Ty, TyCtxt, Upcast, elaborate,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::def_id::DefId;
|
||||
use thin_vec::thin_vec;
|
||||
@@ -164,10 +166,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
)
|
||||
.break_value()
|
||||
.expect("expected to index into clause that exists");
|
||||
let candidate = candidate_predicate
|
||||
let candidate_predicate = candidate_predicate
|
||||
.as_trait_clause()
|
||||
.expect("projection candidate is not a trait predicate")
|
||||
.map_bound(|t| t.trait_ref);
|
||||
.expect("projection candidate is not a trait predicate");
|
||||
let candidate_predicate =
|
||||
util::lazily_elaborate_sizedness_candidate(self.infcx, obligation, candidate_predicate);
|
||||
|
||||
let candidate = candidate_predicate.map_bound(|t| t.trait_ref);
|
||||
|
||||
let candidate = self.infcx.instantiate_binder_with_fresh_vars(
|
||||
obligation.cause.span,
|
||||
@@ -224,6 +229,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
) -> PredicateObligations<'tcx> {
|
||||
debug!(?obligation, ?param, "confirm_param_candidate");
|
||||
|
||||
let param = util::lazily_elaborate_sizedness_candidate(
|
||||
self.infcx,
|
||||
obligation,
|
||||
param.upcast(self.infcx.tcx),
|
||||
)
|
||||
.map_bound(|p| p.trait_ref);
|
||||
|
||||
// During evaluation, we already checked that this
|
||||
// where-clause trait-ref could be unified with the obligation
|
||||
// trait-ref. Repeat that unification now without any
|
||||
@@ -251,7 +263,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
let obligations = if has_nested {
|
||||
let trait_def = obligation.predicate.def_id();
|
||||
let conditions = match tcx.as_lang_item(trait_def) {
|
||||
Some(LangItem::Sized) => self.sized_conditions(obligation),
|
||||
Some(LangItem::Sized) => {
|
||||
self.sizedness_conditions(obligation, SizedTraitKind::Sized)
|
||||
}
|
||||
Some(LangItem::MetaSized) => {
|
||||
self.sizedness_conditions(obligation, SizedTraitKind::MetaSized)
|
||||
}
|
||||
Some(LangItem::PointeeSized) => {
|
||||
bug!("`PointeeSized` is removing during lowering");
|
||||
}
|
||||
Some(LangItem::Copy | LangItem::Clone) => self.copy_clone_conditions(obligation),
|
||||
Some(LangItem::FusedIterator) => self.fused_iterator_conditions(obligation),
|
||||
other => bug!("unexpected builtin trait {trait_def:?} ({other:?})"),
|
||||
|
||||
@@ -27,8 +27,8 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||
use rustc_middle::ty::error::TypeErrorToStringExt;
|
||||
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
|
||||
use rustc_middle::ty::{
|
||||
self, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable,
|
||||
TypeVisitableExt, TypingMode, Upcast, elaborate,
|
||||
self, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate, SizedTraitKind, Ty, TyCtxt,
|
||||
TypeFoldable, TypeVisitableExt, TypingMode, Upcast, elaborate,
|
||||
};
|
||||
use rustc_span::{Symbol, sym};
|
||||
use tracing::{debug, instrument, trace};
|
||||
@@ -2094,9 +2094,10 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
fn sized_conditions(
|
||||
fn sizedness_conditions(
|
||||
&mut self,
|
||||
obligation: &PolyTraitObligation<'tcx>,
|
||||
sizedness: SizedTraitKind,
|
||||
) -> BuiltinImplConditions<'tcx> {
|
||||
use self::BuiltinImplConditions::{Ambiguous, None, Where};
|
||||
|
||||
@@ -2126,7 +2127,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
Where(ty::Binder::dummy(Vec::new()))
|
||||
}
|
||||
|
||||
ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => None,
|
||||
ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
|
||||
SizedTraitKind::Sized => None,
|
||||
SizedTraitKind::MetaSized => Where(ty::Binder::dummy(Vec::new())),
|
||||
},
|
||||
|
||||
ty::Foreign(..) => None,
|
||||
|
||||
ty::Tuple(tys) => Where(
|
||||
obligation.predicate.rebind(tys.last().map_or_else(Vec::new, |&last| vec![last])),
|
||||
@@ -2135,11 +2141,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
ty::Pat(ty, _) => Where(obligation.predicate.rebind(vec![*ty])),
|
||||
|
||||
ty::Adt(def, args) => {
|
||||
if let Some(sized_crit) = def.sized_constraint(self.tcx()) {
|
||||
if let Some(crit) = def.sizedness_constraint(self.tcx(), sizedness) {
|
||||
// (*) binder moved here
|
||||
Where(
|
||||
obligation.predicate.rebind(vec![sized_crit.instantiate(self.tcx(), args)]),
|
||||
)
|
||||
Where(obligation.predicate.rebind(vec![crit.instantiate(self.tcx(), args)]))
|
||||
} else {
|
||||
Where(ty::Binder::dummy(Vec::new()))
|
||||
}
|
||||
|
||||
@@ -4,10 +4,13 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::traits::PolyTraitObligation;
|
||||
pub use rustc_infer::traits::util::*;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
|
||||
use rustc_middle::ty::{
|
||||
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
|
||||
self, PolyTraitPredicate, SizedTraitKind, TraitPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
|
||||
TypeFolder, TypeSuperFoldable, TypeVisitableExt,
|
||||
};
|
||||
pub use rustc_next_trait_solver::placeholder::BoundVarReplacer;
|
||||
use rustc_span::Span;
|
||||
@@ -362,15 +365,19 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>) -> bool {
|
||||
// Proving `Sized` very often on "obviously sized" types like `&T`, accounts for about 60%
|
||||
// percentage of the predicates we have to prove. No need to canonicalize and all that for
|
||||
// such cases.
|
||||
// Proving `Sized`/`MetaSized`, very often on "obviously sized" types like
|
||||
// `&T`, accounts for about 60% percentage of the predicates we have to prove. No need to
|
||||
// canonicalize and all that for such cases.
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) =
|
||||
predicate.kind().skip_binder()
|
||||
{
|
||||
if tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized)
|
||||
&& trait_ref.self_ty().is_trivially_sized(tcx)
|
||||
{
|
||||
let sizedness = match tcx.as_lang_item(trait_ref.def_id()) {
|
||||
Some(LangItem::Sized) => SizedTraitKind::Sized,
|
||||
Some(LangItem::MetaSized) => SizedTraitKind::MetaSized,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
if trait_ref.self_ty().has_trivial_sizedness(tcx, sizedness) {
|
||||
debug!("fast path -- trivial sizedness");
|
||||
return true;
|
||||
}
|
||||
@@ -378,3 +385,39 @@ pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
/// To improve performance, sizedness traits are not elaborated and so special-casing is required
|
||||
/// in the trait solver to find a `Sized` candidate for a `MetaSized` obligation. Returns the
|
||||
/// predicate to used in the candidate for such a `obligation`, given a `candidate`.
|
||||
pub(crate) fn lazily_elaborate_sizedness_candidate<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
obligation: &PolyTraitObligation<'tcx>,
|
||||
candidate: PolyTraitPredicate<'tcx>,
|
||||
) -> PolyTraitPredicate<'tcx> {
|
||||
if !infcx.tcx.is_lang_item(obligation.predicate.def_id(), LangItem::MetaSized)
|
||||
|| !infcx.tcx.is_lang_item(candidate.def_id(), LangItem::Sized)
|
||||
{
|
||||
return candidate;
|
||||
}
|
||||
|
||||
if obligation.predicate.polarity() != candidate.polarity() {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
let drcx = DeepRejectCtxt::relate_rigid_rigid(infcx.tcx);
|
||||
if !drcx.args_may_unify(
|
||||
obligation.predicate.skip_binder().trait_ref.args,
|
||||
candidate.skip_binder().trait_ref.args,
|
||||
) {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
candidate.map_bound(|c| TraitPredicate {
|
||||
trait_ref: TraitRef::new_from_args(
|
||||
infcx.tcx,
|
||||
obligation.predicate.def_id(),
|
||||
c.trait_ref.args,
|
||||
),
|
||||
polarity: c.polarity,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -567,6 +567,14 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||
def_id: DefId,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
) -> PredicateObligations<'tcx> {
|
||||
// PERF: `Sized`'s predicates include `MetaSized`, but both are compiler implemented marker
|
||||
// traits, so `MetaSized` will always be WF if `Sized` is WF and vice-versa. Determining
|
||||
// the nominal obligations of `Sized` would in-effect just elaborate `MetaSized` and make
|
||||
// the compiler do a bunch of work needlessly.
|
||||
if self.tcx().is_lang_item(def_id, LangItem::Sized) {
|
||||
return Default::default();
|
||||
}
|
||||
|
||||
let predicates = self.tcx().predicates_of(def_id);
|
||||
let mut origins = vec![def_id; predicates.predicates.len()];
|
||||
let mut head = predicates;
|
||||
|
||||
@@ -1,23 +1,29 @@
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_index::bit_set::DenseBitSet;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{
|
||||
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast, fold_regions,
|
||||
self, SizedTraitKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast,
|
||||
fold_regions,
|
||||
};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
|
||||
use rustc_trait_selection::traits;
|
||||
use tracing::instrument;
|
||||
|
||||
/// If `ty` implements the given `sizedness` trait, returns `None`. Otherwise, returns the type
|
||||
/// that must implement the given `sizedness` for `ty` to implement it.
|
||||
#[instrument(level = "debug", skip(tcx), ret)]
|
||||
fn sized_constraint_for_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
|
||||
fn sizedness_constraint_for_ty<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
sizedness: SizedTraitKind,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Option<Ty<'tcx>> {
|
||||
match ty.kind() {
|
||||
// these are always sized
|
||||
// Always `Sized` or `MetaSized`
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Int(..)
|
||||
@@ -35,31 +41,40 @@ fn sized_constraint_for_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'
|
||||
| ty::Never
|
||||
| ty::Dynamic(_, _, ty::DynStar) => None,
|
||||
|
||||
// these are never sized
|
||||
ty::Str | ty::Slice(..) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => Some(ty),
|
||||
ty::Str | ty::Slice(..) | ty::Dynamic(_, _, ty::Dyn) => match sizedness {
|
||||
// Never `Sized`
|
||||
SizedTraitKind::Sized => Some(ty),
|
||||
// Always `MetaSized`
|
||||
SizedTraitKind::MetaSized => None,
|
||||
},
|
||||
|
||||
ty::Pat(ty, _) => sized_constraint_for_ty(tcx, *ty),
|
||||
|
||||
ty::Tuple(tys) => tys.last().and_then(|&ty| sized_constraint_for_ty(tcx, ty)),
|
||||
|
||||
// recursive case
|
||||
ty::Adt(adt, args) => adt.sized_constraint(tcx).and_then(|intermediate| {
|
||||
let ty = intermediate.instantiate(tcx, args);
|
||||
sized_constraint_for_ty(tcx, ty)
|
||||
}),
|
||||
|
||||
// these can be sized or unsized.
|
||||
// Maybe `Sized` or `MetaSized`
|
||||
ty::Param(..) | ty::Alias(..) | ty::Error(_) => Some(ty),
|
||||
|
||||
// We cannot instantiate the binder, so just return the *original* type back,
|
||||
// but only if the inner type has a sized constraint. Thus we skip the binder,
|
||||
// but don't actually use the result from `sized_constraint_for_ty`.
|
||||
ty::UnsafeBinder(inner_ty) => {
|
||||
sized_constraint_for_ty(tcx, inner_ty.skip_binder()).map(|_| ty)
|
||||
sizedness_constraint_for_ty(tcx, sizedness, inner_ty.skip_binder()).map(|_| ty)
|
||||
}
|
||||
|
||||
// Never `MetaSized` or `Sized`
|
||||
ty::Foreign(..) => Some(ty),
|
||||
|
||||
// Recursive cases
|
||||
ty::Pat(ty, _) => sizedness_constraint_for_ty(tcx, sizedness, *ty),
|
||||
|
||||
ty::Tuple(tys) => {
|
||||
tys.last().and_then(|&ty| sizedness_constraint_for_ty(tcx, sizedness, ty))
|
||||
}
|
||||
|
||||
ty::Adt(adt, args) => adt.sizedness_constraint(tcx, sizedness).and_then(|intermediate| {
|
||||
let ty = intermediate.instantiate(tcx, args);
|
||||
sizedness_constraint_for_ty(tcx, sizedness, ty)
|
||||
}),
|
||||
|
||||
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) => {
|
||||
bug!("unexpected type `{ty:?}` in sized_constraint_for_ty")
|
||||
bug!("unexpected type `{ty:?}` in `sizedness_constraint_for_ty`")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,15 +90,22 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness {
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates the `Sized` constraint.
|
||||
/// Returns the type of the last field of a struct ("the constraint") which must implement the
|
||||
/// `sizedness` trait for the whole ADT to be considered to implement that `sizedness` trait.
|
||||
/// `def_id` is assumed to be the `AdtDef` of a struct and will panic otherwise.
|
||||
///
|
||||
/// In fact, there are only a few options for the types in the constraint:
|
||||
/// - an obviously-unsized type
|
||||
/// For `Sized`, there are only a few options for the types in the constraint:
|
||||
/// - an meta-sized type (str, slices, trait objects, etc)
|
||||
/// - an pointee-sized type (extern types)
|
||||
/// - a type parameter or projection whose sizedness can't be known
|
||||
///
|
||||
/// For `MetaSized`, there are only a few options for the types in the constraint:
|
||||
/// - an pointee-sized type (extern types)
|
||||
/// - a type parameter or projection whose sizedness can't be known
|
||||
#[instrument(level = "debug", skip(tcx), ret)]
|
||||
fn adt_sized_constraint<'tcx>(
|
||||
fn adt_sizedness_constraint<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
(def_id, sizedness): (DefId, SizedTraitKind),
|
||||
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
||||
if let Some(def_id) = def_id.as_local() {
|
||||
if let ty::Representability::Infinite(_) = tcx.representability(def_id) {
|
||||
@@ -93,21 +115,21 @@ fn adt_sized_constraint<'tcx>(
|
||||
let def = tcx.adt_def(def_id);
|
||||
|
||||
if !def.is_struct() {
|
||||
bug!("`adt_sized_constraint` called on non-struct type: {def:?}");
|
||||
bug!("`adt_sizedness_constraint` called on non-struct type: {def:?}");
|
||||
}
|
||||
|
||||
let tail_def = def.non_enum_variant().tail_opt()?;
|
||||
let tail_ty = tcx.type_of(tail_def.did).instantiate_identity();
|
||||
|
||||
let constraint_ty = sized_constraint_for_ty(tcx, tail_ty)?;
|
||||
let constraint_ty = sizedness_constraint_for_ty(tcx, sizedness, tail_ty)?;
|
||||
|
||||
// perf hack: if there is a `constraint_ty: Sized` bound, then we know
|
||||
// perf hack: if there is a `constraint_ty: {Meta,}Sized` bound, then we know
|
||||
// that the type is sized and do not need to check it on the impl.
|
||||
let sized_trait_def_id = tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
|
||||
let sizedness_trait_def_id = sizedness.require_lang_item(tcx);
|
||||
let predicates = tcx.predicates_of(def.did()).predicates;
|
||||
if predicates.iter().any(|(p, _)| {
|
||||
p.as_trait_clause().is_some_and(|trait_pred| {
|
||||
trait_pred.def_id() == sized_trait_def_id
|
||||
trait_pred.def_id() == sizedness_trait_def_id
|
||||
&& trait_pred.self_ty().skip_binder() == constraint_ty
|
||||
})
|
||||
}) {
|
||||
@@ -369,7 +391,7 @@ fn impl_self_is_guaranteed_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_def_id: DefId)
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
asyncness,
|
||||
adt_sized_constraint,
|
||||
adt_sizedness_constraint,
|
||||
param_env,
|
||||
typing_env_normalized_for_post_analysis,
|
||||
defaultness,
|
||||
|
||||
@@ -4,6 +4,7 @@ use smallvec::smallvec;
|
||||
|
||||
use crate::data_structures::HashSet;
|
||||
use crate::inherent::*;
|
||||
use crate::lang_items::TraitSolverLangItem;
|
||||
use crate::outlives::{Component, push_outlives_components};
|
||||
use crate::{self as ty, Interner, Upcast as _};
|
||||
|
||||
@@ -18,6 +19,7 @@ pub struct Elaborator<I: Interner, O> {
|
||||
stack: Vec<O>,
|
||||
visited: HashSet<ty::Binder<I, ty::PredicateKind<I>>>,
|
||||
mode: Filter,
|
||||
elaborate_sized: ElaborateSized,
|
||||
}
|
||||
|
||||
enum Filter {
|
||||
@@ -25,6 +27,12 @@ enum Filter {
|
||||
OnlySelf,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
enum ElaborateSized {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
/// Describes how to elaborate an obligation into a sub-obligation.
|
||||
pub trait Elaboratable<I: Interner> {
|
||||
fn predicate(&self) -> I::Predicate;
|
||||
@@ -77,13 +85,19 @@ pub fn elaborate<I: Interner, O: Elaboratable<I>>(
|
||||
cx: I,
|
||||
obligations: impl IntoIterator<Item = O>,
|
||||
) -> Elaborator<I, O> {
|
||||
let mut elaborator =
|
||||
Elaborator { cx, stack: Vec::new(), visited: HashSet::default(), mode: Filter::All };
|
||||
let mut elaborator = Elaborator {
|
||||
cx,
|
||||
stack: Vec::new(),
|
||||
visited: HashSet::default(),
|
||||
mode: Filter::All,
|
||||
elaborate_sized: ElaborateSized::No,
|
||||
};
|
||||
elaborator.extend_deduped(obligations);
|
||||
elaborator
|
||||
}
|
||||
|
||||
impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
|
||||
/// Adds `obligations` to the stack.
|
||||
fn extend_deduped(&mut self, obligations: impl IntoIterator<Item = O>) {
|
||||
// Only keep those bounds that we haven't already seen.
|
||||
// This is necessary to prevent infinite recursion in some
|
||||
@@ -103,6 +117,13 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Start elaborating `Sized` - reqd during coherence checking, normally skipped to improve
|
||||
/// compiler performance.
|
||||
pub fn elaborate_sized(mut self) -> Self {
|
||||
self.elaborate_sized = ElaborateSized::Yes;
|
||||
self
|
||||
}
|
||||
|
||||
fn elaborate(&mut self, elaboratable: &O) {
|
||||
let cx = self.cx;
|
||||
|
||||
@@ -111,6 +132,19 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
|
||||
return;
|
||||
};
|
||||
|
||||
// PERF(sized-hierarchy): To avoid iterating over sizedness supertraits in
|
||||
// parameter environments, as an optimisation, sizedness supertraits aren't
|
||||
// elaborated, so check if a `Sized` obligation is being elaborated to a
|
||||
// `MetaSized` obligation and emit it. Candidate assembly and confirmation
|
||||
// are modified to check for the `Sized` subtrait when a `MetaSized` obligation
|
||||
// is present.
|
||||
if self.elaborate_sized == ElaborateSized::No
|
||||
&& let Some(did) = clause.as_trait_clause().map(|c| c.def_id())
|
||||
&& self.cx.is_lang_item(did, TraitSolverLangItem::Sized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let bound_clause = clause.kind();
|
||||
match bound_clause.skip_binder() {
|
||||
ty::ClauseKind::Trait(data) => {
|
||||
|
||||
@@ -11,7 +11,7 @@ use rustc_ast_ir::Mutability;
|
||||
use crate::elaborate::Elaboratable;
|
||||
use crate::fold::{TypeFoldable, TypeSuperFoldable};
|
||||
use crate::relate::Relate;
|
||||
use crate::solve::AdtDestructorKind;
|
||||
use crate::solve::{AdtDestructorKind, SizedTraitKind};
|
||||
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
|
||||
use crate::{self as ty, CollectAndApply, Interner, UpcastFrom};
|
||||
|
||||
@@ -571,7 +571,11 @@ pub trait AdtDef<I: Interner>: Copy + Debug + Hash + Eq {
|
||||
// FIXME: perhaps use `all_fields` and expose `FieldDef`.
|
||||
fn all_field_tys(self, interner: I) -> ty::EarlyBinder<I, impl IntoIterator<Item = I::Ty>>;
|
||||
|
||||
fn sized_constraint(self, interner: I) -> Option<ty::EarlyBinder<I, I::Ty>>;
|
||||
fn sizedness_constraint(
|
||||
self,
|
||||
interner: I,
|
||||
sizedness: SizedTraitKind,
|
||||
) -> Option<ty::EarlyBinder<I, I::Ty>>;
|
||||
|
||||
fn is_fundamental(self) -> bool;
|
||||
|
||||
|
||||
@@ -30,7 +30,9 @@ pub enum TraitSolverLangItem {
|
||||
FutureOutput,
|
||||
Iterator,
|
||||
Metadata,
|
||||
MetaSized,
|
||||
Option,
|
||||
PointeeSized,
|
||||
PointeeTrait,
|
||||
Poll,
|
||||
Sized,
|
||||
|
||||
@@ -8,6 +8,7 @@ use derive_where::derive_where;
|
||||
use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
|
||||
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
|
||||
use crate::lang_items::TraitSolverLangItem;
|
||||
use crate::search_graph::PathKind;
|
||||
use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Upcast};
|
||||
|
||||
@@ -366,3 +367,24 @@ pub enum AdtDestructorKind {
|
||||
NotConst,
|
||||
Const,
|
||||
}
|
||||
|
||||
/// Which sizedness trait - `Sized`, `MetaSized`? `PointeeSized` is omitted as it is removed during
|
||||
/// lowering.
|
||||
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||
pub enum SizedTraitKind {
|
||||
/// `Sized` trait
|
||||
Sized,
|
||||
/// `MetaSized` trait
|
||||
MetaSized,
|
||||
}
|
||||
|
||||
impl SizedTraitKind {
|
||||
/// Returns `DefId` of corresponding language item.
|
||||
pub fn require_lang_item<I: Interner>(self, cx: I) -> I::DefId {
|
||||
cx.require_lang_item(match self {
|
||||
SizedTraitKind::Sized => TraitSolverLangItem::Sized,
|
||||
SizedTraitKind::MetaSized => TraitSolverLangItem::MetaSized,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::marker::PointeeSized;
|
||||
|
||||
mod uninit;
|
||||
|
||||
/// A common trait that allows explicit creation of a duplicate value.
|
||||
@@ -283,7 +285,7 @@ impl_use_cloned! {
|
||||
reason = "deriving hack, should not be public",
|
||||
issue = "none"
|
||||
)]
|
||||
pub struct AssertParamIsClone<T: Clone + ?Sized> {
|
||||
pub struct AssertParamIsClone<T: Clone + PointeeSized> {
|
||||
_field: crate::marker::PhantomData<T>,
|
||||
}
|
||||
#[doc(hidden)]
|
||||
@@ -293,7 +295,7 @@ pub struct AssertParamIsClone<T: Clone + ?Sized> {
|
||||
reason = "deriving hack, should not be public",
|
||||
issue = "none"
|
||||
)]
|
||||
pub struct AssertParamIsCopy<T: Copy + ?Sized> {
|
||||
pub struct AssertParamIsCopy<T: Copy + PointeeSized> {
|
||||
_field: crate::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
@@ -530,6 +532,8 @@ unsafe impl CloneToUninit for crate::bstr::ByteStr {
|
||||
/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
|
||||
/// in `rustc_trait_selection`.
|
||||
mod impls {
|
||||
use crate::marker::PointeeSized;
|
||||
|
||||
macro_rules! impl_clone {
|
||||
($($t:ty)*) => {
|
||||
$(
|
||||
@@ -560,7 +564,7 @@ mod impls {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Clone for *const T {
|
||||
impl<T: PointeeSized> Clone for *const T {
|
||||
#[inline(always)]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
@@ -568,7 +572,7 @@ mod impls {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Clone for *mut T {
|
||||
impl<T: PointeeSized> Clone for *mut T {
|
||||
#[inline(always)]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
@@ -577,7 +581,7 @@ mod impls {
|
||||
|
||||
/// Shared references can be cloned, but mutable references *cannot*!
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Clone for &T {
|
||||
impl<T: PointeeSized> Clone for &T {
|
||||
#[inline(always)]
|
||||
#[rustc_diagnostic_item = "noop_method_clone"]
|
||||
fn clone(&self) -> Self {
|
||||
@@ -587,5 +591,5 @@ mod impls {
|
||||
|
||||
/// Shared references can be cloned, but mutable references *cannot*!
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> !Clone for &mut T {}
|
||||
impl<T: PointeeSized> !Clone for &mut T {}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ mod bytewise;
|
||||
pub(crate) use bytewise::BytewiseEq;
|
||||
|
||||
use self::Ordering::*;
|
||||
use crate::marker::PointeeSized;
|
||||
use crate::ops::ControlFlow;
|
||||
|
||||
/// Trait for comparisons using the equality operator.
|
||||
@@ -246,7 +247,7 @@ use crate::ops::ControlFlow;
|
||||
append_const_msg
|
||||
)]
|
||||
#[rustc_diagnostic_item = "PartialEq"]
|
||||
pub trait PartialEq<Rhs: ?Sized = Self> {
|
||||
pub trait PartialEq<Rhs: PointeeSized = Self>: PointeeSized {
|
||||
/// Tests for `self` and `other` values to be equal, and is used by `==`.
|
||||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@@ -332,7 +333,7 @@ pub macro PartialEq($item:item) {
|
||||
#[doc(alias = "!=")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "Eq"]
|
||||
pub trait Eq: PartialEq<Self> {
|
||||
pub trait Eq: PartialEq<Self> + PointeeSized {
|
||||
// this method is used solely by `impl Eq or #[derive(Eq)]` to assert that every component of a
|
||||
// type implements `Eq` itself. The current deriving infrastructure means doing this assertion
|
||||
// without using a method on this trait is nearly impossible.
|
||||
@@ -361,7 +362,7 @@ pub macro Eq($item:item) {
|
||||
#[doc(hidden)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[unstable(feature = "derive_eq", reason = "deriving hack, should not be public", issue = "none")]
|
||||
pub struct AssertParamIsEq<T: Eq + ?Sized> {
|
||||
pub struct AssertParamIsEq<T: Eq + PointeeSized> {
|
||||
_field: crate::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
@@ -954,7 +955,7 @@ impl<T: Clone> Clone for Reverse<T> {
|
||||
#[doc(alias = ">=")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "Ord"]
|
||||
pub trait Ord: Eq + PartialOrd<Self> {
|
||||
pub trait Ord: Eq + PartialOrd<Self> + PointeeSized {
|
||||
/// This method returns an [`Ordering`] between `self` and `other`.
|
||||
///
|
||||
/// By convention, `self.cmp(&other)` returns the ordering matching the expression
|
||||
@@ -1337,7 +1338,8 @@ pub macro Ord($item:item) {
|
||||
append_const_msg
|
||||
)]
|
||||
#[rustc_diagnostic_item = "PartialOrd"]
|
||||
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
||||
#[allow(multiple_supertrait_upcastable)] // FIXME(sized_hierarchy): remove this
|
||||
pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
|
||||
/// This method returns an ordering between `self` and `other` values if one exists.
|
||||
///
|
||||
/// # Examples
|
||||
@@ -1481,7 +1483,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
||||
}
|
||||
}
|
||||
|
||||
fn default_chaining_impl<T: ?Sized, U: ?Sized>(
|
||||
fn default_chaining_impl<T: PointeeSized, U: PointeeSized>(
|
||||
lhs: &T,
|
||||
rhs: &U,
|
||||
p: impl FnOnce(Ordering) -> bool,
|
||||
@@ -1803,6 +1805,7 @@ where
|
||||
mod impls {
|
||||
use crate::cmp::Ordering::{self, Equal, Greater, Less};
|
||||
use crate::hint::unreachable_unchecked;
|
||||
use crate::marker::PointeeSized;
|
||||
use crate::ops::ControlFlow::{self, Break, Continue};
|
||||
|
||||
macro_rules! partial_eq_impl {
|
||||
@@ -2015,7 +2018,7 @@ mod impls {
|
||||
// & pointers
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &A
|
||||
impl<A: PointeeSized, B: PointeeSized> PartialEq<&B> for &A
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
{
|
||||
@@ -2029,7 +2032,7 @@ mod impls {
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized, B: ?Sized> PartialOrd<&B> for &A
|
||||
impl<A: PointeeSized, B: PointeeSized> PartialOrd<&B> for &A
|
||||
where
|
||||
A: PartialOrd<B>,
|
||||
{
|
||||
@@ -2071,7 +2074,7 @@ mod impls {
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized> Ord for &A
|
||||
impl<A: PointeeSized> Ord for &A
|
||||
where
|
||||
A: Ord,
|
||||
{
|
||||
@@ -2081,12 +2084,12 @@ mod impls {
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized> Eq for &A where A: Eq {}
|
||||
impl<A: PointeeSized> Eq for &A where A: Eq {}
|
||||
|
||||
// &mut pointers
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &mut A
|
||||
impl<A: PointeeSized, B: PointeeSized> PartialEq<&mut B> for &mut A
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
{
|
||||
@@ -2100,7 +2103,7 @@ mod impls {
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized, B: ?Sized> PartialOrd<&mut B> for &mut A
|
||||
impl<A: PointeeSized, B: PointeeSized> PartialOrd<&mut B> for &mut A
|
||||
where
|
||||
A: PartialOrd<B>,
|
||||
{
|
||||
@@ -2142,7 +2145,7 @@ mod impls {
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized> Ord for &mut A
|
||||
impl<A: PointeeSized> Ord for &mut A
|
||||
where
|
||||
A: Ord,
|
||||
{
|
||||
@@ -2152,10 +2155,10 @@ mod impls {
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized> Eq for &mut A where A: Eq {}
|
||||
impl<A: PointeeSized> Eq for &mut A where A: Eq {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &A
|
||||
impl<A: PointeeSized, B: PointeeSized> PartialEq<&mut B> for &A
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
{
|
||||
@@ -2170,7 +2173,7 @@ mod impls {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &mut A
|
||||
impl<A: PointeeSized, B: PointeeSized> PartialEq<&B> for &mut A
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
{
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
use crate::error::Error;
|
||||
use crate::fmt;
|
||||
use crate::hash::{Hash, Hasher};
|
||||
use crate::marker::PointeeSized;
|
||||
|
||||
mod num;
|
||||
|
||||
@@ -215,7 +216,7 @@ pub const fn identity<T>(x: T) -> T {
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "AsRef"]
|
||||
pub trait AsRef<T: ?Sized> {
|
||||
pub trait AsRef<T: PointeeSized>: PointeeSized {
|
||||
/// Converts this type into a shared reference of the (usually inferred) input type.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn as_ref(&self) -> &T;
|
||||
@@ -366,7 +367,7 @@ pub trait AsRef<T: ?Sized> {
|
||||
/// `&mut Vec<u8>`, for example, is the better choice (callers need to pass the correct type then).
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "AsMut"]
|
||||
pub trait AsMut<T: ?Sized> {
|
||||
pub trait AsMut<T: PointeeSized>: PointeeSized {
|
||||
/// Converts this type into a mutable reference of the (usually inferred) input type.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn as_mut(&mut self) -> &mut T;
|
||||
@@ -701,7 +702,7 @@ pub trait TryFrom<T>: Sized {
|
||||
|
||||
// As lifts over &
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized, U: ?Sized> AsRef<U> for &T
|
||||
impl<T: PointeeSized, U: PointeeSized> AsRef<U> for &T
|
||||
where
|
||||
T: AsRef<U>,
|
||||
{
|
||||
@@ -713,7 +714,7 @@ where
|
||||
|
||||
// As lifts over &mut
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized, U: ?Sized> AsRef<U> for &mut T
|
||||
impl<T: PointeeSized, U: PointeeSized> AsRef<U> for &mut T
|
||||
where
|
||||
T: AsRef<U>,
|
||||
{
|
||||
@@ -733,7 +734,7 @@ where
|
||||
|
||||
// AsMut lifts over &mut
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized, U: ?Sized> AsMut<U> for &mut T
|
||||
impl<T: PointeeSized, U: PointeeSized> AsMut<U> for &mut T
|
||||
where
|
||||
T: AsMut<U>,
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
use crate::cell::{Cell, Ref, RefCell, RefMut, SyncUnsafeCell, UnsafeCell};
|
||||
use crate::char::{EscapeDebugExtArgs, MAX_LEN_UTF8};
|
||||
use crate::marker::PhantomData;
|
||||
use crate::marker::{PhantomData, PointeeSized};
|
||||
use crate::num::fmt as numfmt;
|
||||
use crate::ops::Deref;
|
||||
use crate::{iter, result, str};
|
||||
@@ -864,7 +864,7 @@ impl Display for Arguments<'_> {
|
||||
#[doc(alias = "{:?}")]
|
||||
#[rustc_diagnostic_item = "Debug"]
|
||||
#[rustc_trivial_field_reads]
|
||||
pub trait Debug {
|
||||
pub trait Debug: PointeeSized {
|
||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||
///
|
||||
/// # Examples
|
||||
@@ -995,7 +995,7 @@ pub use macros::Debug;
|
||||
#[doc(alias = "{}")]
|
||||
#[rustc_diagnostic_item = "Display"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Display {
|
||||
pub trait Display: PointeeSized {
|
||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||
///
|
||||
/// # Examples
|
||||
@@ -1071,7 +1071,7 @@ pub trait Display {
|
||||
/// assert_eq!(format!("l as octal is: {l:#06o}"), "l as octal is: 0o0011");
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Octal {
|
||||
pub trait Octal: PointeeSized {
|
||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
||||
@@ -1130,7 +1130,7 @@ pub trait Octal {
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Binary {
|
||||
pub trait Binary: PointeeSized {
|
||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
||||
@@ -1185,7 +1185,7 @@ pub trait Binary {
|
||||
/// assert_eq!(format!("l as hex is: {l:#010x}"), "l as hex is: 0x00000009");
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait LowerHex {
|
||||
pub trait LowerHex: PointeeSized {
|
||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
||||
@@ -1240,7 +1240,7 @@ pub trait LowerHex {
|
||||
/// assert_eq!(format!("l as hex is: {l:#010X}"), "l as hex is: 0x7FFFFFFF");
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait UpperHex {
|
||||
pub trait UpperHex: PointeeSized {
|
||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
||||
@@ -1299,7 +1299,7 @@ pub trait UpperHex {
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "Pointer"]
|
||||
pub trait Pointer {
|
||||
pub trait Pointer: PointeeSized {
|
||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
||||
@@ -1350,7 +1350,7 @@ pub trait Pointer {
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait LowerExp {
|
||||
pub trait LowerExp: PointeeSized {
|
||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
||||
@@ -1401,7 +1401,7 @@ pub trait LowerExp {
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait UpperExp {
|
||||
pub trait UpperExp: PointeeSized {
|
||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
||||
@@ -2646,11 +2646,11 @@ macro_rules! fmt_refs {
|
||||
($($tr:ident),*) => {
|
||||
$(
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized + $tr> $tr for &T {
|
||||
impl<T: PointeeSized + $tr> $tr for &T {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result { $tr::fmt(&**self, f) }
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized + $tr> $tr for &mut T {
|
||||
impl<T: PointeeSized + $tr> $tr for &mut T {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result { $tr::fmt(&**self, f) }
|
||||
}
|
||||
)*
|
||||
@@ -2772,7 +2772,7 @@ impl Display for char {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Pointer for *const T {
|
||||
impl<T: PointeeSized> Pointer for *const T {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
if <<T as core::ptr::Pointee>::Metadata as core::unit::IsUnit>::is_unit() {
|
||||
pointer_fmt_inner(self.expose_provenance(), f)
|
||||
@@ -2817,21 +2817,21 @@ pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Resul
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Pointer for *mut T {
|
||||
impl<T: PointeeSized> Pointer for *mut T {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
Pointer::fmt(&(*self as *const T), f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Pointer for &T {
|
||||
impl<T: PointeeSized> Pointer for &T {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
Pointer::fmt(&(*self as *const T), f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Pointer for &mut T {
|
||||
impl<T: PointeeSized> Pointer for &mut T {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
Pointer::fmt(&(&**self as *const T), f)
|
||||
}
|
||||
@@ -2840,13 +2840,13 @@ impl<T: ?Sized> Pointer for &mut T {
|
||||
// Implementation of Display/Debug for various core types
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Debug for *const T {
|
||||
impl<T: PointeeSized> Debug for *const T {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
Pointer::fmt(self, f)
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Debug for *mut T {
|
||||
impl<T: PointeeSized> Debug for *mut T {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
Pointer::fmt(self, f)
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ mod sip;
|
||||
/// [impl]: ../../std/primitive.str.html#impl-Hash-for-str
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "Hash"]
|
||||
pub trait Hash {
|
||||
pub trait Hash: marker::PointeeSized {
|
||||
/// Feeds this value into the given [`Hasher`].
|
||||
///
|
||||
/// # Examples
|
||||
@@ -941,7 +941,7 @@ mod impls {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized + Hash> Hash for &T {
|
||||
impl<T: ?Sized + marker::PointeeSized + Hash> Hash for &T {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
(**self).hash(state);
|
||||
@@ -949,7 +949,7 @@ mod impls {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized + Hash> Hash for &mut T {
|
||||
impl<T: ?Sized + marker::PointeeSized + Hash> Hash for &mut T {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
(**self).hash(state);
|
||||
@@ -957,7 +957,7 @@ mod impls {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Hash for *const T {
|
||||
impl<T: ?Sized + marker::PointeeSized> Hash for *const T {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
let (address, metadata) = self.to_raw_parts();
|
||||
@@ -967,7 +967,7 @@ mod impls {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Hash for *mut T {
|
||||
impl<T: ?Sized + marker::PointeeSized> Hash for *mut T {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
let (address, metadata) = self.to_raw_parts();
|
||||
|
||||
@@ -1,39 +1,41 @@
|
||||
//! Various traits used to restrict intrinsics to not-completely-wrong types.
|
||||
|
||||
use crate::marker::PointeeSized;
|
||||
|
||||
/// Types with a built-in dereference operator in runtime MIR,
|
||||
/// aka references and raw pointers.
|
||||
///
|
||||
/// # Safety
|
||||
/// Must actually *be* such a type.
|
||||
pub unsafe trait BuiltinDeref: Sized {
|
||||
type Pointee: ?Sized;
|
||||
type Pointee: PointeeSized;
|
||||
}
|
||||
|
||||
unsafe impl<T: ?Sized> BuiltinDeref for &mut T {
|
||||
unsafe impl<T: PointeeSized> BuiltinDeref for &mut T {
|
||||
type Pointee = T;
|
||||
}
|
||||
unsafe impl<T: ?Sized> BuiltinDeref for &T {
|
||||
unsafe impl<T: PointeeSized> BuiltinDeref for &T {
|
||||
type Pointee = T;
|
||||
}
|
||||
unsafe impl<T: ?Sized> BuiltinDeref for *mut T {
|
||||
unsafe impl<T: PointeeSized> BuiltinDeref for *mut T {
|
||||
type Pointee = T;
|
||||
}
|
||||
unsafe impl<T: ?Sized> BuiltinDeref for *const T {
|
||||
unsafe impl<T: PointeeSized> BuiltinDeref for *const T {
|
||||
type Pointee = T;
|
||||
}
|
||||
|
||||
pub trait ChangePointee<U: ?Sized>: BuiltinDeref {
|
||||
pub trait ChangePointee<U: PointeeSized>: BuiltinDeref {
|
||||
type Output;
|
||||
}
|
||||
impl<'a, T: ?Sized + 'a, U: ?Sized + 'a> ChangePointee<U> for &'a mut T {
|
||||
impl<'a, T: PointeeSized + 'a, U: PointeeSized + 'a> ChangePointee<U> for &'a mut T {
|
||||
type Output = &'a mut U;
|
||||
}
|
||||
impl<'a, T: ?Sized + 'a, U: ?Sized + 'a> ChangePointee<U> for &'a T {
|
||||
impl<'a, T: PointeeSized + 'a, U: PointeeSized + 'a> ChangePointee<U> for &'a T {
|
||||
type Output = &'a U;
|
||||
}
|
||||
impl<T: ?Sized, U: ?Sized> ChangePointee<U> for *mut T {
|
||||
impl<T: PointeeSized, U: PointeeSized> ChangePointee<U> for *mut T {
|
||||
type Output = *mut U;
|
||||
}
|
||||
impl<T: ?Sized, U: ?Sized> ChangePointee<U> for *const T {
|
||||
impl<T: PointeeSized, U: PointeeSized> ChangePointee<U> for *const T {
|
||||
type Output = *const U;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use crate::marker::{ConstParamTy, DiscriminantKind, Tuple};
|
||||
use crate::marker::{ConstParamTy, DiscriminantKind, PointeeSized, Tuple};
|
||||
use crate::ptr;
|
||||
|
||||
mod bounds;
|
||||
@@ -2740,7 +2740,7 @@ where
|
||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||
#[rustc_intrinsic_const_stable_indirect]
|
||||
#[rustc_intrinsic]
|
||||
pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(ptr: *const P) -> M;
|
||||
pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + PointeeSized, M>(ptr: *const P) -> M;
|
||||
|
||||
/// This is an accidentally-stable alias to [`ptr::copy_nonoverlapping`]; use that instead.
|
||||
// Note (intentionally not in the doc comment): `ptr::copy_nonoverlapping` adds some extra
|
||||
|
||||
@@ -93,15 +93,15 @@ pub unsafe auto trait Send {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> !Send for *const T {}
|
||||
impl<T: PointeeSized> !Send for *const T {}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> !Send for *mut T {}
|
||||
impl<T: PointeeSized> !Send for *mut T {}
|
||||
|
||||
// Most instances arise automatically, but this instance is needed to link up `T: Sync` with
|
||||
// `&T: Send` (and it also removes the unsound default instance `T Send` -> `&T: Send` that would
|
||||
// otherwise exist).
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
unsafe impl<T: Sync + ?Sized> Send for &T {}
|
||||
unsafe impl<T: Sync + PointeeSized> Send for &T {}
|
||||
|
||||
/// Types with a constant size known at compile time.
|
||||
///
|
||||
@@ -151,11 +151,48 @@ unsafe impl<T: Sync + ?Sized> Send for &T {}
|
||||
#[rustc_specialization_trait]
|
||||
#[rustc_deny_explicit_impl]
|
||||
#[rustc_do_not_implement_via_object]
|
||||
// `Sized` being coinductive, despite having supertraits, is okay as there are no user-written impls,
|
||||
// and we know that the supertraits are always implemented if the subtrait is just by looking at
|
||||
// the builtin impls.
|
||||
#[rustc_coinductive]
|
||||
pub trait Sized {
|
||||
pub trait Sized: MetaSized {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
/// Types with a size that can be determined from pointer metadata.
|
||||
#[unstable(feature = "sized_hierarchy", issue = "none")]
|
||||
#[lang = "meta_sized"]
|
||||
#[diagnostic::on_unimplemented(
|
||||
message = "the size for values of type `{Self}` cannot be known",
|
||||
label = "doesn't have a known size"
|
||||
)]
|
||||
#[fundamental]
|
||||
#[rustc_specialization_trait]
|
||||
#[rustc_deny_explicit_impl]
|
||||
#[rustc_do_not_implement_via_object]
|
||||
// `MetaSized` being coinductive, despite having supertraits, is okay for the same reasons as
|
||||
// `Sized` above.
|
||||
#[rustc_coinductive]
|
||||
pub trait MetaSized: PointeeSized {
|
||||
// Empty
|
||||
}
|
||||
|
||||
/// Types that may or may not have a size.
|
||||
#[unstable(feature = "sized_hierarchy", issue = "none")]
|
||||
#[lang = "pointee_sized"]
|
||||
#[diagnostic::on_unimplemented(
|
||||
message = "values of type `{Self}` may or may not have a size",
|
||||
label = "may or may not have a known size"
|
||||
)]
|
||||
#[fundamental]
|
||||
#[rustc_specialization_trait]
|
||||
#[rustc_deny_explicit_impl]
|
||||
#[rustc_do_not_implement_via_object]
|
||||
#[rustc_coinductive]
|
||||
pub trait PointeeSized {
|
||||
// Empty
|
||||
}
|
||||
|
||||
/// Types that can be "unsized" to a dynamically-sized type.
|
||||
///
|
||||
/// For example, the sized array type `[i8; 2]` implements `Unsize<[i8]>` and
|
||||
@@ -192,7 +229,7 @@ pub trait Sized {
|
||||
#[lang = "unsize"]
|
||||
#[rustc_deny_explicit_impl]
|
||||
#[rustc_do_not_implement_via_object]
|
||||
pub trait Unsize<T: ?Sized> {
|
||||
pub trait Unsize<T: PointeeSized>: PointeeSized {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
@@ -229,7 +266,7 @@ marker_impls! {
|
||||
(),
|
||||
{T, const N: usize} [T; N],
|
||||
{T} [T],
|
||||
{T: ?Sized} &T,
|
||||
{T: PointeeSized} &T,
|
||||
}
|
||||
|
||||
/// Types whose values can be duplicated simply by copying bits.
|
||||
@@ -442,8 +479,8 @@ marker_impls! {
|
||||
isize, i8, i16, i32, i64, i128,
|
||||
f16, f32, f64, f128,
|
||||
bool, char,
|
||||
{T: ?Sized} *const T,
|
||||
{T: ?Sized} *mut T,
|
||||
{T: PointeeSized} *const T,
|
||||
{T: PointeeSized} *mut T,
|
||||
|
||||
}
|
||||
|
||||
@@ -452,7 +489,7 @@ impl Copy for ! {}
|
||||
|
||||
/// Shared references can be copied, but mutable references *cannot*!
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Copy for &T {}
|
||||
impl<T: PointeeSized> Copy for &T {}
|
||||
|
||||
/// Marker trait for the types that are allowed in union fields and unsafe
|
||||
/// binder types.
|
||||
@@ -636,9 +673,9 @@ pub unsafe auto trait Sync {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> !Sync for *const T {}
|
||||
impl<T: PointeeSized> !Sync for *const T {}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> !Sync for *mut T {}
|
||||
impl<T: PointeeSized> !Sync for *mut T {}
|
||||
|
||||
/// Zero-sized type used to mark things that "act like" they own a `T`.
|
||||
///
|
||||
@@ -775,57 +812,57 @@ impl<T: ?Sized> !Sync for *mut T {}
|
||||
/// [drop check]: Drop#drop-check
|
||||
#[lang = "phantom_data"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct PhantomData<T: ?Sized>;
|
||||
pub struct PhantomData<T: PointeeSized>;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Hash for PhantomData<T> {
|
||||
impl<T: PointeeSized> Hash for PhantomData<T> {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, _: &mut H) {}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> cmp::PartialEq for PhantomData<T> {
|
||||
impl<T: PointeeSized> cmp::PartialEq for PhantomData<T> {
|
||||
fn eq(&self, _other: &PhantomData<T>) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> cmp::Eq for PhantomData<T> {}
|
||||
impl<T: PointeeSized> cmp::Eq for PhantomData<T> {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> cmp::PartialOrd for PhantomData<T> {
|
||||
impl<T: PointeeSized> cmp::PartialOrd for PhantomData<T> {
|
||||
fn partial_cmp(&self, _other: &PhantomData<T>) -> Option<cmp::Ordering> {
|
||||
Option::Some(cmp::Ordering::Equal)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> cmp::Ord for PhantomData<T> {
|
||||
impl<T: PointeeSized> cmp::Ord for PhantomData<T> {
|
||||
fn cmp(&self, _other: &PhantomData<T>) -> cmp::Ordering {
|
||||
cmp::Ordering::Equal
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Copy for PhantomData<T> {}
|
||||
impl<T: PointeeSized> Copy for PhantomData<T> {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Clone for PhantomData<T> {
|
||||
impl<T: PointeeSized> Clone for PhantomData<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Default for PhantomData<T> {
|
||||
impl<T: PointeeSized> Default for PhantomData<T> {
|
||||
fn default() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "structural_match", issue = "31434")]
|
||||
impl<T: ?Sized> StructuralPartialEq for PhantomData<T> {}
|
||||
impl<T: PointeeSized> StructuralPartialEq for PhantomData<T> {}
|
||||
|
||||
/// Compiler-internal trait used to indicate the type of enum discriminants.
|
||||
///
|
||||
@@ -868,15 +905,15 @@ pub trait DiscriminantKind {
|
||||
pub unsafe auto trait Freeze {}
|
||||
|
||||
#[unstable(feature = "freeze", issue = "121675")]
|
||||
impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
|
||||
impl<T: PointeeSized> !Freeze for UnsafeCell<T> {}
|
||||
marker_impls! {
|
||||
#[unstable(feature = "freeze", issue = "121675")]
|
||||
unsafe Freeze for
|
||||
{T: ?Sized} PhantomData<T>,
|
||||
{T: ?Sized} *const T,
|
||||
{T: ?Sized} *mut T,
|
||||
{T: ?Sized} &T,
|
||||
{T: ?Sized} &mut T,
|
||||
{T: PointeeSized} PhantomData<T>,
|
||||
{T: PointeeSized} *const T,
|
||||
{T: PointeeSized} *mut T,
|
||||
{T: PointeeSized} &T,
|
||||
{T: PointeeSized} &mut T,
|
||||
}
|
||||
|
||||
/// Used to determine whether a type contains any `UnsafePinned` (or `PhantomPinned`) internally,
|
||||
@@ -991,15 +1028,15 @@ impl !UnsafeUnpin for PhantomPinned {}
|
||||
marker_impls! {
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
Unpin for
|
||||
{T: ?Sized} &T,
|
||||
{T: ?Sized} &mut T,
|
||||
{T: PointeeSized} &T,
|
||||
{T: PointeeSized} &mut T,
|
||||
}
|
||||
|
||||
marker_impls! {
|
||||
#[stable(feature = "pin_raw", since = "1.38.0")]
|
||||
Unpin for
|
||||
{T: ?Sized} *const T,
|
||||
{T: ?Sized} *mut T,
|
||||
{T: PointeeSized} *const T,
|
||||
{T: PointeeSized} *mut T,
|
||||
}
|
||||
|
||||
/// A marker for types that can be dropped.
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use crate::marker::PointeeSized;
|
||||
|
||||
/// Used for immutable dereferencing operations, like `*v`.
|
||||
///
|
||||
/// In addition to being used for explicit dereferencing operations with the
|
||||
@@ -135,7 +137,7 @@
|
||||
#[rustc_diagnostic_item = "Deref"]
|
||||
#[const_trait]
|
||||
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
|
||||
pub trait Deref {
|
||||
pub trait Deref: PointeeSized {
|
||||
/// The resulting type after dereferencing.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "deref_target"]
|
||||
@@ -267,7 +269,7 @@ impl<T: ?Sized> const Deref for &mut T {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[const_trait]
|
||||
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
|
||||
pub trait DerefMut: ~const Deref {
|
||||
pub trait DerefMut: ~const Deref + PointeeSized {
|
||||
/// Mutably dereferences the value.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "deref_mut_method"]
|
||||
@@ -293,7 +295,7 @@ impl<T: ?Sized> const DerefMut for &mut T {
|
||||
/// unchanged.
|
||||
#[unstable(feature = "deref_pure_trait", issue = "87121")]
|
||||
#[lang = "deref_pure"]
|
||||
pub unsafe trait DerefPure {}
|
||||
pub unsafe trait DerefPure: PointeeSized {}
|
||||
|
||||
#[unstable(feature = "deref_pure_trait", issue = "87121")]
|
||||
unsafe impl<T: ?Sized> DerefPure for &T {}
|
||||
@@ -366,7 +368,7 @@ unsafe impl<T: ?Sized> DerefPure for &mut T {}
|
||||
/// ```
|
||||
#[lang = "receiver"]
|
||||
#[unstable(feature = "arbitrary_self_types", issue = "44874")]
|
||||
pub trait Receiver {
|
||||
pub trait Receiver: PointeeSized {
|
||||
/// The target type on which the method may be called.
|
||||
#[rustc_diagnostic_item = "receiver_target"]
|
||||
#[lang = "receiver_target"]
|
||||
@@ -393,12 +395,12 @@ where
|
||||
#[lang = "legacy_receiver"]
|
||||
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
|
||||
#[doc(hidden)]
|
||||
pub trait LegacyReceiver {
|
||||
pub trait LegacyReceiver: PointeeSized {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
|
||||
impl<T: ?Sized> LegacyReceiver for &T {}
|
||||
impl<T: PointeeSized> LegacyReceiver for &T {}
|
||||
|
||||
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
|
||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
||||
impl<T: PointeeSized> LegacyReceiver for &mut T {}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::marker::Unsize;
|
||||
use crate::marker::{PointeeSized, Unsize};
|
||||
|
||||
/// Trait that indicates that this is a pointer or a wrapper for one,
|
||||
/// where unsizing can be performed on the pointee.
|
||||
@@ -33,40 +33,40 @@ use crate::marker::Unsize;
|
||||
/// [nomicon-coerce]: ../../nomicon/coercions.html
|
||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T: ?Sized> {
|
||||
pub trait CoerceUnsized<T: PointeeSized> {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
// &mut T -> &mut U
|
||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
|
||||
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a mut U> for &'a mut T {}
|
||||
// &mut T -> &U
|
||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
||||
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {}
|
||||
impl<'a, 'b: 'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a U> for &'b mut T {}
|
||||
// &mut T -> *mut U
|
||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {}
|
||||
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*mut U> for &'a mut T {}
|
||||
// &mut T -> *const U
|
||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {}
|
||||
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for &'a mut T {}
|
||||
|
||||
// &T -> &U
|
||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
||||
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
|
||||
impl<'a, 'b: 'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a U> for &'b T {}
|
||||
// &T -> *const U
|
||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a T {}
|
||||
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for &'a T {}
|
||||
|
||||
// *mut T -> *mut U
|
||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
|
||||
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*mut U> for *mut T {}
|
||||
// *mut T -> *const U
|
||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
|
||||
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for *mut T {}
|
||||
|
||||
// *const T -> *const U
|
||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
|
||||
impl<T: PointeeSized + Unsize<U>, 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.
|
||||
@@ -122,13 +122,13 @@ pub trait DispatchFromDyn<T> {
|
||||
|
||||
// &T -> &U
|
||||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
|
||||
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<&'a U> for &'a T {}
|
||||
// &mut T -> &mut U
|
||||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
|
||||
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<&'a mut U> for &'a mut T {}
|
||||
// *const T -> *const U
|
||||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
|
||||
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<*const U> for *const T {}
|
||||
// *mut T -> *mut U
|
||||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
|
||||
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<*mut U> for *mut T {}
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::intrinsics::const_eval_select;
|
||||
use crate::mem::{self, SizedTypeProperties};
|
||||
use crate::slice::{self, SliceIndex};
|
||||
|
||||
impl<T: ?Sized> *const T {
|
||||
impl<T: PointeeSized> *const T {
|
||||
#[doc = include_str!("docs/is_null.md")]
|
||||
///
|
||||
/// # Examples
|
||||
@@ -129,7 +129,7 @@ impl<T: ?Sized> *const T {
|
||||
#[inline]
|
||||
pub const fn with_metadata_of<U>(self, meta: *const U) -> *const U
|
||||
where
|
||||
U: ?Sized,
|
||||
U: PointeeSized,
|
||||
{
|
||||
from_raw_parts::<U>(self as *const (), metadata(meta))
|
||||
}
|
||||
@@ -1586,7 +1586,7 @@ impl<T, const N: usize> *const [T; N] {
|
||||
|
||||
/// Pointer equality is by address, as produced by the [`<*const T>::addr`](pointer::addr) method.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> PartialEq for *const T {
|
||||
impl<T: PointeeSized> PartialEq for *const T {
|
||||
#[inline]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
fn eq(&self, other: &*const T) -> bool {
|
||||
@@ -1596,11 +1596,11 @@ impl<T: ?Sized> PartialEq for *const T {
|
||||
|
||||
/// Pointer equality is an equivalence relation.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Eq for *const T {}
|
||||
impl<T: PointeeSized> Eq for *const T {}
|
||||
|
||||
/// Pointer comparison is by address, as produced by the `[`<*const T>::addr`](pointer::addr)` method.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Ord for *const T {
|
||||
impl<T: PointeeSized> Ord for *const T {
|
||||
#[inline]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
fn cmp(&self, other: &*const T) -> Ordering {
|
||||
@@ -1616,7 +1616,7 @@ impl<T: ?Sized> Ord for *const T {
|
||||
|
||||
/// Pointer comparison is by address, as produced by the `[`<*const T>::addr`](pointer::addr)` method.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> PartialOrd for *const T {
|
||||
impl<T: PointeeSized> PartialOrd for *const T {
|
||||
#[inline]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
fn partial_cmp(&self, other: &*const T) -> Option<Ordering> {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use crate::fmt;
|
||||
use crate::hash::{Hash, Hasher};
|
||||
use crate::intrinsics::{aggregate_raw_ptr, ptr_metadata};
|
||||
use crate::marker::Freeze;
|
||||
use crate::marker::{Freeze, PointeeSized};
|
||||
use crate::ptr::NonNull;
|
||||
|
||||
/// Provides the pointer metadata type of any pointed-to type.
|
||||
@@ -55,7 +55,7 @@ use crate::ptr::NonNull;
|
||||
#[lang = "pointee_trait"]
|
||||
#[rustc_deny_explicit_impl]
|
||||
#[rustc_do_not_implement_via_object]
|
||||
pub trait Pointee {
|
||||
pub trait Pointee: PointeeSized {
|
||||
/// The type for metadata in pointers and references to `Self`.
|
||||
#[lang = "metadata_type"]
|
||||
// NOTE: Keep trait bounds in `static_assert_expected_bounds_for_metadata`
|
||||
@@ -81,7 +81,7 @@ pub trait Pointee {
|
||||
/// ```
|
||||
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
||||
// NOTE: don’t stabilize this before trait aliases are stable in the language?
|
||||
pub trait Thin = Pointee<Metadata = ()>;
|
||||
pub trait Thin = Pointee<Metadata = ()> + PointeeSized;
|
||||
|
||||
/// Extracts the metadata component of a pointer.
|
||||
///
|
||||
@@ -96,7 +96,7 @@ pub trait Thin = Pointee<Metadata = ()>;
|
||||
/// assert_eq!(std::ptr::metadata("foo"), 3_usize);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub const fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata {
|
||||
pub const fn metadata<T: PointeeSized>(ptr: *const T) -> <T as Pointee>::Metadata {
|
||||
ptr_metadata(ptr)
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ pub const fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata {
|
||||
/// [`slice::from_raw_parts`]: crate::slice::from_raw_parts
|
||||
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
||||
#[inline]
|
||||
pub const fn from_raw_parts<T: ?Sized>(
|
||||
pub const fn from_raw_parts<T: PointeeSized>(
|
||||
data_pointer: *const impl Thin,
|
||||
metadata: <T as Pointee>::Metadata,
|
||||
) -> *const T {
|
||||
@@ -122,7 +122,7 @@ pub const fn from_raw_parts<T: ?Sized>(
|
||||
/// See the documentation of [`from_raw_parts`] for more details.
|
||||
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
||||
#[inline]
|
||||
pub const fn from_raw_parts_mut<T: ?Sized>(
|
||||
pub const fn from_raw_parts_mut<T: PointeeSized>(
|
||||
data_pointer: *mut impl Thin,
|
||||
metadata: <T as Pointee>::Metadata,
|
||||
) -> *mut T {
|
||||
@@ -152,7 +152,7 @@ pub const fn from_raw_parts_mut<T: ?Sized>(
|
||||
/// duplicated in multiple codegen units), and pointers to vtables of *different* types/traits can
|
||||
/// compare equal (since identical vtables can be deduplicated within a codegen unit).
|
||||
#[lang = "dyn_metadata"]
|
||||
pub struct DynMetadata<Dyn: ?Sized> {
|
||||
pub struct DynMetadata<Dyn: PointeeSized> {
|
||||
_vtable_ptr: NonNull<VTable>,
|
||||
_phantom: crate::marker::PhantomData<Dyn>,
|
||||
}
|
||||
@@ -165,7 +165,7 @@ unsafe extern "C" {
|
||||
type VTable;
|
||||
}
|
||||
|
||||
impl<Dyn: ?Sized> DynMetadata<Dyn> {
|
||||
impl<Dyn: PointeeSized> DynMetadata<Dyn> {
|
||||
/// When `DynMetadata` appears as the metadata field of a wide pointer, the rustc_middle layout
|
||||
/// computation does magic and the resulting layout is *not* a `FieldsShape::Aggregate`, instead
|
||||
/// it is a `FieldsShape::Primitive`. This means that the same type can have different layout
|
||||
@@ -206,10 +206,10 @@ impl<Dyn: ?Sized> DynMetadata<Dyn> {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<Dyn: ?Sized> Send for DynMetadata<Dyn> {}
|
||||
unsafe impl<Dyn: ?Sized> Sync for DynMetadata<Dyn> {}
|
||||
unsafe impl<Dyn: PointeeSized> Send for DynMetadata<Dyn> {}
|
||||
unsafe impl<Dyn: PointeeSized> Sync for DynMetadata<Dyn> {}
|
||||
|
||||
impl<Dyn: ?Sized> fmt::Debug for DynMetadata<Dyn> {
|
||||
impl<Dyn: PointeeSized> fmt::Debug for DynMetadata<Dyn> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("DynMetadata").field(&self.vtable_ptr()).finish()
|
||||
}
|
||||
@@ -217,27 +217,27 @@ impl<Dyn: ?Sized> fmt::Debug for DynMetadata<Dyn> {
|
||||
|
||||
// Manual impls needed to avoid `Dyn: $Trait` bounds.
|
||||
|
||||
impl<Dyn: ?Sized> Unpin for DynMetadata<Dyn> {}
|
||||
impl<Dyn: PointeeSized> Unpin for DynMetadata<Dyn> {}
|
||||
|
||||
impl<Dyn: ?Sized> Copy for DynMetadata<Dyn> {}
|
||||
impl<Dyn: PointeeSized> Copy for DynMetadata<Dyn> {}
|
||||
|
||||
impl<Dyn: ?Sized> Clone for DynMetadata<Dyn> {
|
||||
impl<Dyn: PointeeSized> Clone for DynMetadata<Dyn> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<Dyn: ?Sized> Eq for DynMetadata<Dyn> {}
|
||||
impl<Dyn: PointeeSized> Eq for DynMetadata<Dyn> {}
|
||||
|
||||
impl<Dyn: ?Sized> PartialEq for DynMetadata<Dyn> {
|
||||
impl<Dyn: PointeeSized> PartialEq for DynMetadata<Dyn> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
crate::ptr::eq::<VTable>(self.vtable_ptr(), other.vtable_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Dyn: ?Sized> Ord for DynMetadata<Dyn> {
|
||||
impl<Dyn: PointeeSized> Ord for DynMetadata<Dyn> {
|
||||
#[inline]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
fn cmp(&self, other: &Self) -> crate::cmp::Ordering {
|
||||
@@ -245,14 +245,14 @@ impl<Dyn: ?Sized> Ord for DynMetadata<Dyn> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Dyn: ?Sized> PartialOrd for DynMetadata<Dyn> {
|
||||
impl<Dyn: PointeeSized> PartialOrd for DynMetadata<Dyn> {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &Self) -> Option<crate::cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Dyn: ?Sized> Hash for DynMetadata<Dyn> {
|
||||
impl<Dyn: PointeeSized> Hash for DynMetadata<Dyn> {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
||||
crate::ptr::hash::<VTable, _>(self.vtable_ptr(), hasher)
|
||||
|
||||
@@ -398,7 +398,7 @@
|
||||
|
||||
use crate::cmp::Ordering;
|
||||
use crate::intrinsics::const_eval_select;
|
||||
use crate::marker::FnPtr;
|
||||
use crate::marker::{FnPtr, PointeeSized};
|
||||
use crate::mem::{self, MaybeUninit, SizedTypeProperties};
|
||||
use crate::num::NonZero;
|
||||
use crate::{fmt, hash, intrinsics, ub_checks};
|
||||
@@ -796,7 +796,7 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
|
||||
#[lang = "drop_in_place"]
|
||||
#[allow(unconditional_recursion)]
|
||||
#[rustc_diagnostic_item = "ptr_drop_in_place"]
|
||||
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||
pub unsafe fn drop_in_place<T: PointeeSized>(to_drop: *mut T) {
|
||||
// Code here does not matter - this is replaced by the
|
||||
// real drop glue by the compiler.
|
||||
|
||||
@@ -825,7 +825,7 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||
#[rustc_promotable]
|
||||
#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
|
||||
#[rustc_diagnostic_item = "ptr_null"]
|
||||
pub const fn null<T: ?Sized + Thin>() -> *const T {
|
||||
pub const fn null<T: PointeeSized + Thin>() -> *const T {
|
||||
from_raw_parts(without_provenance::<()>(0), ())
|
||||
}
|
||||
|
||||
@@ -850,7 +850,7 @@ pub const fn null<T: ?Sized + Thin>() -> *const T {
|
||||
#[rustc_promotable]
|
||||
#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
|
||||
#[rustc_diagnostic_item = "ptr_null_mut"]
|
||||
pub const fn null_mut<T: ?Sized + Thin>() -> *mut T {
|
||||
pub const fn null_mut<T: PointeeSized + Thin>() -> *mut T {
|
||||
from_raw_parts_mut(without_provenance_mut::<()>(0), ())
|
||||
}
|
||||
|
||||
@@ -1068,7 +1068,7 @@ pub fn with_exposed_provenance_mut<T>(addr: usize) -> *mut T {
|
||||
#[rustc_const_stable(feature = "ptr_from_ref", since = "1.76.0")]
|
||||
#[rustc_never_returns_null_ptr]
|
||||
#[rustc_diagnostic_item = "ptr_from_ref"]
|
||||
pub const fn from_ref<T: ?Sized>(r: &T) -> *const T {
|
||||
pub const fn from_ref<T: PointeeSized>(r: &T) -> *const T {
|
||||
r
|
||||
}
|
||||
|
||||
@@ -1118,7 +1118,7 @@ pub const fn from_ref<T: ?Sized>(r: &T) -> *const T {
|
||||
#[stable(feature = "ptr_from_ref", since = "1.76.0")]
|
||||
#[rustc_const_stable(feature = "ptr_from_ref", since = "1.76.0")]
|
||||
#[rustc_never_returns_null_ptr]
|
||||
pub const fn from_mut<T: ?Sized>(r: &mut T) -> *mut T {
|
||||
pub const fn from_mut<T: PointeeSized>(r: &mut T) -> *mut T {
|
||||
r
|
||||
}
|
||||
|
||||
@@ -2419,7 +2419,7 @@ pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
|
||||
#[must_use = "pointer comparison produces a value"]
|
||||
#[rustc_diagnostic_item = "ptr_eq"]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)] // it's actually clear here
|
||||
pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
|
||||
pub fn eq<T: PointeeSized>(a: *const T, b: *const T) -> bool {
|
||||
a == b
|
||||
}
|
||||
|
||||
@@ -2443,7 +2443,7 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
|
||||
#[stable(feature = "ptr_addr_eq", since = "1.76.0")]
|
||||
#[inline(always)]
|
||||
#[must_use = "pointer comparison produces a value"]
|
||||
pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool {
|
||||
pub fn addr_eq<T: PointeeSized, U: PointeeSized>(p: *const T, q: *const U) -> bool {
|
||||
(p as *const ()) == (q as *const ())
|
||||
}
|
||||
|
||||
@@ -2526,7 +2526,7 @@ pub fn fn_addr_eq<T: FnPtr, U: FnPtr>(f: T, g: U) -> bool {
|
||||
/// assert_eq!(actual, expected);
|
||||
/// ```
|
||||
#[stable(feature = "ptr_hash", since = "1.35.0")]
|
||||
pub fn hash<T: ?Sized, S: hash::Hasher>(hashee: *const T, into: &mut S) {
|
||||
pub fn hash<T: PointeeSized, S: hash::Hasher>(hashee: *const T, into: &mut S) {
|
||||
use crate::hash::Hash;
|
||||
hashee.hash(into);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use super::*;
|
||||
use crate::cmp::Ordering::{Equal, Greater, Less};
|
||||
use crate::intrinsics::const_eval_select;
|
||||
use crate::marker::PointeeSized;
|
||||
use crate::mem::{self, SizedTypeProperties};
|
||||
use crate::slice::{self, SliceIndex};
|
||||
|
||||
impl<T: ?Sized> *mut T {
|
||||
impl<T: PointeeSized> *mut T {
|
||||
#[doc = include_str!("docs/is_null.md")]
|
||||
///
|
||||
/// # Examples
|
||||
@@ -110,7 +111,7 @@ impl<T: ?Sized> *mut T {
|
||||
#[inline]
|
||||
pub const fn with_metadata_of<U>(self, meta: *const U) -> *mut U
|
||||
where
|
||||
U: ?Sized,
|
||||
U: PointeeSized,
|
||||
{
|
||||
from_raw_parts_mut::<U>(self as *mut (), metadata(meta))
|
||||
}
|
||||
@@ -2006,7 +2007,7 @@ impl<T, const N: usize> *mut [T; N] {
|
||||
|
||||
/// Pointer equality is by address, as produced by the [`<*mut T>::addr`](pointer::addr) method.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> PartialEq for *mut T {
|
||||
impl<T: PointeeSized> PartialEq for *mut T {
|
||||
#[inline(always)]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
fn eq(&self, other: &*mut T) -> bool {
|
||||
@@ -2016,11 +2017,11 @@ impl<T: ?Sized> PartialEq for *mut T {
|
||||
|
||||
/// Pointer equality is an equivalence relation.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Eq for *mut T {}
|
||||
impl<T: PointeeSized> Eq for *mut T {}
|
||||
|
||||
/// Pointer comparison is by address, as produced by the [`<*mut T>::addr`](pointer::addr) method.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Ord for *mut T {
|
||||
impl<T: PointeeSized> Ord for *mut T {
|
||||
#[inline]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
fn cmp(&self, other: &*mut T) -> Ordering {
|
||||
@@ -2036,7 +2037,7 @@ impl<T: ?Sized> Ord for *mut T {
|
||||
|
||||
/// Pointer comparison is by address, as produced by the [`<*mut T>::addr`](pointer::addr) method.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> PartialOrd for *mut T {
|
||||
impl<T: PointeeSized> PartialOrd for *mut T {
|
||||
#[inline(always)]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
fn partial_cmp(&self, other: &*mut T) -> Option<Ordering> {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::cmp::Ordering;
|
||||
use crate::marker::Unsize;
|
||||
use crate::marker::{PointeeSized, Unsize};
|
||||
use crate::mem::{MaybeUninit, SizedTypeProperties};
|
||||
use crate::num::NonZero;
|
||||
use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
||||
@@ -67,7 +67,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<T: ?Sized> {
|
||||
pub struct NonNull<T: PointeeSized> {
|
||||
// Remember to use `.as_ptr()` instead of `.pointer`, as field projecting to
|
||||
// this is banned by <https://github.com/rust-lang/compiler-team/issues/807>.
|
||||
pointer: *const T,
|
||||
@@ -76,12 +76,12 @@ pub struct NonNull<T: ?Sized> {
|
||||
/// `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<T: ?Sized> !Send for NonNull<T> {}
|
||||
impl<T: PointeeSized> !Send for NonNull<T> {}
|
||||
|
||||
/// `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<T: ?Sized> !Sync for NonNull<T> {}
|
||||
impl<T: PointeeSized> !Sync for NonNull<T> {}
|
||||
|
||||
impl<T: Sized> NonNull<T> {
|
||||
/// Creates a pointer with the given address and no [provenance][crate::ptr#provenance].
|
||||
@@ -190,7 +190,7 @@ impl<T: Sized> NonNull<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> NonNull<T> {
|
||||
impl<T: PointeeSized> NonNull<T> {
|
||||
/// Creates a new `NonNull`.
|
||||
///
|
||||
/// # Safety
|
||||
@@ -1604,7 +1604,7 @@ impl<T> NonNull<[T]> {
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> Clone for NonNull<T> {
|
||||
impl<T: PointeeSized> Clone for NonNull<T> {
|
||||
#[inline(always)]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
@@ -1612,39 +1612,39 @@ impl<T: ?Sized> Clone for NonNull<T> {
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> Copy for NonNull<T> {}
|
||||
impl<T: PointeeSized> Copy for NonNull<T> {}
|
||||
|
||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
||||
impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
|
||||
impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
|
||||
|
||||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
||||
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
|
||||
impl<T: PointeeSized, U: PointeeSized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
|
||||
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
unsafe impl<T: ?Sized> PinCoerceUnsized for NonNull<T> {}
|
||||
unsafe impl<T: PointeeSized> PinCoerceUnsized for NonNull<T> {}
|
||||
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
impl<T> core::marker::PointerLike for NonNull<T> {}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> fmt::Debug for NonNull<T> {
|
||||
impl<T: PointeeSized> fmt::Debug for NonNull<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Pointer::fmt(&self.as_ptr(), f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> fmt::Pointer for NonNull<T> {
|
||||
impl<T: PointeeSized> fmt::Pointer for NonNull<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Pointer::fmt(&self.as_ptr(), f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> Eq for NonNull<T> {}
|
||||
impl<T: PointeeSized> Eq for NonNull<T> {}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> PartialEq for NonNull<T> {
|
||||
impl<T: PointeeSized> PartialEq for NonNull<T> {
|
||||
#[inline]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
@@ -1653,7 +1653,7 @@ impl<T: ?Sized> PartialEq for NonNull<T> {
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> Ord for NonNull<T> {
|
||||
impl<T: PointeeSized> Ord for NonNull<T> {
|
||||
#[inline]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
@@ -1662,7 +1662,7 @@ impl<T: ?Sized> Ord for NonNull<T> {
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> PartialOrd for NonNull<T> {
|
||||
impl<T: PointeeSized> PartialOrd for NonNull<T> {
|
||||
#[inline]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
@@ -1671,7 +1671,7 @@ impl<T: ?Sized> PartialOrd for NonNull<T> {
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> hash::Hash for NonNull<T> {
|
||||
impl<T: PointeeSized> hash::Hash for NonNull<T> {
|
||||
#[inline]
|
||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||
self.as_ptr().hash(state)
|
||||
@@ -1679,7 +1679,7 @@ impl<T: ?Sized> hash::Hash for NonNull<T> {
|
||||
}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
|
||||
impl<T: PointeeSized> From<Unique<T>> for NonNull<T> {
|
||||
#[inline]
|
||||
fn from(unique: Unique<T>) -> Self {
|
||||
unique.as_non_null_ptr()
|
||||
@@ -1687,7 +1687,7 @@ impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> From<&mut T> for NonNull<T> {
|
||||
impl<T: PointeeSized> From<&mut T> for NonNull<T> {
|
||||
/// Converts a `&mut T` to a `NonNull<T>`.
|
||||
///
|
||||
/// This conversion is safe and infallible since references cannot be null.
|
||||
@@ -1698,7 +1698,7 @@ impl<T: ?Sized> From<&mut T> for NonNull<T> {
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> From<&T> for NonNull<T> {
|
||||
impl<T: PointeeSized> From<&T> for NonNull<T> {
|
||||
/// Converts a `&T` to a `NonNull<T>`.
|
||||
///
|
||||
/// This conversion is safe and infallible since references cannot be null.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::fmt;
|
||||
use crate::marker::{PhantomData, Unsize};
|
||||
use crate::marker::{PhantomData, PointeeSized, Unsize};
|
||||
use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
||||
use crate::pin::PinCoerceUnsized;
|
||||
use crate::ptr::NonNull;
|
||||
@@ -34,7 +34,7 @@ use crate::ptr::NonNull;
|
||||
#[repr(transparent)]
|
||||
// Lang item used experimentally by Miri to define the semantics of `Unique`.
|
||||
#[lang = "ptr_unique"]
|
||||
pub struct Unique<T: ?Sized> {
|
||||
pub struct Unique<T: PointeeSized> {
|
||||
pointer: NonNull<T>,
|
||||
// NOTE: this marker has no consequences for variance, but is necessary
|
||||
// for dropck to understand that we logically own a `T`.
|
||||
@@ -49,14 +49,14 @@ pub struct Unique<T: ?Sized> {
|
||||
/// unenforced by the type system; the abstraction using the
|
||||
/// `Unique` must enforce it.
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
unsafe impl<T: Send + ?Sized> Send for Unique<T> {}
|
||||
unsafe impl<T: Send + PointeeSized> Send for Unique<T> {}
|
||||
|
||||
/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
|
||||
/// reference is unaliased. Note that this aliasing invariant is
|
||||
/// unenforced by the type system; the abstraction using the
|
||||
/// `Unique` must enforce it.
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> {}
|
||||
unsafe impl<T: Sync + PointeeSized> Sync for Unique<T> {}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: Sized> Unique<T> {
|
||||
@@ -78,7 +78,7 @@ impl<T: Sized> Unique<T> {
|
||||
}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: ?Sized> Unique<T> {
|
||||
impl<T: PointeeSized> Unique<T> {
|
||||
/// Creates a new `Unique`.
|
||||
///
|
||||
/// # Safety
|
||||
@@ -157,7 +157,7 @@ impl<T: ?Sized> Unique<T> {
|
||||
}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: ?Sized> Clone for Unique<T> {
|
||||
impl<T: PointeeSized> Clone for Unique<T> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
@@ -165,33 +165,33 @@ impl<T: ?Sized> Clone for Unique<T> {
|
||||
}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: ?Sized> Copy for Unique<T> {}
|
||||
impl<T: PointeeSized> Copy for Unique<T> {}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
impl<T: PointeeSized, U: PointeeSized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
|
||||
|
||||
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
|
||||
unsafe impl<T: ?Sized> PinCoerceUnsized for Unique<T> {}
|
||||
unsafe impl<T: PointeeSized> PinCoerceUnsized for Unique<T> {}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: ?Sized> fmt::Debug for Unique<T> {
|
||||
impl<T: PointeeSized> fmt::Debug for Unique<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Pointer::fmt(&self.as_ptr(), f)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: ?Sized> fmt::Pointer for Unique<T> {
|
||||
impl<T: PointeeSized> fmt::Pointer for Unique<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Pointer::fmt(&self.as_ptr(), f)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: ?Sized> From<&mut T> for Unique<T> {
|
||||
impl<T: PointeeSized> From<&mut T> for Unique<T> {
|
||||
/// Converts a `&mut T` to a `Unique<T>`.
|
||||
///
|
||||
/// This conversion is infallible since references cannot be null.
|
||||
@@ -202,7 +202,7 @@ impl<T: ?Sized> From<&mut T> for Unique<T> {
|
||||
}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: ?Sized> From<NonNull<T>> for Unique<T> {
|
||||
impl<T: PointeeSized> From<NonNull<T>> for Unique<T> {
|
||||
/// Converts a `NonNull<T>` to a `Unique<T>`.
|
||||
///
|
||||
/// This conversion is infallible since `NonNull` cannot be null.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// See core/src/primitive_docs.rs for documentation.
|
||||
|
||||
use crate::cmp::Ordering::{self, *};
|
||||
use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy};
|
||||
use crate::marker::{ConstParamTy_, PointeeSized, StructuralPartialEq, UnsizedConstParamTy};
|
||||
use crate::ops::ControlFlow::{self, Break, Continue};
|
||||
|
||||
// Recursive macro for implementing n-ary tuple functions and operations
|
||||
@@ -25,7 +25,7 @@ macro_rules! tuple_impls {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<$($T: PartialEq),+> PartialEq for ($($T,)+)
|
||||
where
|
||||
last_type!($($T,)+): ?Sized
|
||||
last_type!($($T,)+): PointeeSized
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &($($T,)+)) -> bool {
|
||||
@@ -43,7 +43,7 @@ macro_rules! tuple_impls {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<$($T: Eq),+> Eq for ($($T,)+)
|
||||
where
|
||||
last_type!($($T,)+): ?Sized
|
||||
last_type!($($T,)+): PointeeSized
|
||||
{}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ macro_rules! tuple_impls {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<$($T: PartialOrd),+> PartialOrd for ($($T,)+)
|
||||
where
|
||||
last_type!($($T,)+): ?Sized
|
||||
last_type!($($T,)+): PointeeSized
|
||||
{
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
|
||||
@@ -119,7 +119,7 @@ macro_rules! tuple_impls {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<$($T: Ord),+> Ord for ($($T,)+)
|
||||
where
|
||||
last_type!($($T,)+): ?Sized
|
||||
last_type!($($T,)+): PointeeSized
|
||||
{
|
||||
#[inline]
|
||||
fn cmp(&self, other: &($($T,)+)) -> Ordering {
|
||||
|
||||
@@ -21,8 +21,21 @@
|
||||
#![allow(internal_features)]
|
||||
#![warn(unreachable_pub)]
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
pub trait Sized {}
|
||||
#[cfg(not(bootstrap))]
|
||||
#[lang = "sized"]
|
||||
pub trait Sized: MetaSized {}
|
||||
|
||||
#[lang = "sync"]
|
||||
auto trait Sync {}
|
||||
#[lang = "copy"]
|
||||
@@ -30,14 +43,25 @@ trait Copy {}
|
||||
#[lang = "freeze"]
|
||||
auto trait Freeze {}
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
impl<T: ?Sized> Copy for *mut T {}
|
||||
#[cfg(not(bootstrap))]
|
||||
impl<T: PointeeSized> Copy for *mut T {}
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
#[lang = "drop_in_place"]
|
||||
#[inline]
|
||||
#[allow(unconditional_recursion)]
|
||||
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||
drop_in_place(to_drop);
|
||||
}
|
||||
#[cfg(not(bootstrap))]
|
||||
#[lang = "drop_in_place"]
|
||||
#[inline]
|
||||
#[allow(unconditional_recursion)]
|
||||
pub unsafe fn drop_in_place<T: PointeeSized>(to_drop: *mut T) {
|
||||
drop_in_place(to_drop);
|
||||
}
|
||||
|
||||
// Frame unwind info registration
|
||||
//
|
||||
|
||||
@@ -8,8 +8,21 @@
|
||||
#![allow(internal_features)]
|
||||
#![warn(unreachable_pub)]
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
pub trait Sized {}
|
||||
#[cfg(not(bootstrap))]
|
||||
#[lang = "sized"]
|
||||
pub trait Sized: MetaSized {}
|
||||
|
||||
#[lang = "sync"]
|
||||
trait Sync {}
|
||||
impl<T> Sync for T {}
|
||||
@@ -18,14 +31,25 @@ trait Copy {}
|
||||
#[lang = "freeze"]
|
||||
auto trait Freeze {}
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
impl<T: ?Sized> Copy for *mut T {}
|
||||
#[cfg(not(bootstrap))]
|
||||
impl<T: PointeeSized> Copy for *mut T {}
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
#[lang = "drop_in_place"]
|
||||
#[inline]
|
||||
#[allow(unconditional_recursion)]
|
||||
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||
drop_in_place(to_drop);
|
||||
}
|
||||
#[cfg(not(bootstrap))]
|
||||
#[lang = "drop_in_place"]
|
||||
#[inline]
|
||||
#[allow(unconditional_recursion)]
|
||||
pub unsafe fn drop_in_place<T: PointeeSized>(to_drop: *mut T) {
|
||||
drop_in_place(to_drop);
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "windows", target_arch = "x86", target_env = "gnu"))]
|
||||
pub mod eh_frames {
|
||||
|
||||
@@ -2574,7 +2574,7 @@ fn prepare_cargo_test(
|
||||
// by `Cargo::new` and that actually makes things go wrong.
|
||||
if builder.kind != Kind::Miri {
|
||||
let mut dylib_paths = builder.rustc_lib_paths(compiler);
|
||||
dylib_paths.push(PathBuf::from(&builder.sysroot_target_libdir(compiler, target)));
|
||||
dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
|
||||
helpers::add_dylib_path(dylib_paths, &mut cargo);
|
||||
}
|
||||
|
||||
|
||||
@@ -589,7 +589,7 @@ impl ErrorIndex {
|
||||
let compiler = builder.compiler_for(builder.top_stage, host, host);
|
||||
let mut cmd = command(builder.ensure(ErrorIndex { compiler }).tool_path);
|
||||
let mut dylib_paths = builder.rustc_lib_paths(compiler);
|
||||
dylib_paths.push(PathBuf::from(&builder.sysroot_target_libdir(compiler, compiler.host)));
|
||||
dylib_paths.push(builder.sysroot_target_libdir(compiler, compiler.host));
|
||||
add_dylib_path(dylib_paths, &mut cmd);
|
||||
cmd
|
||||
}
|
||||
|
||||
@@ -265,13 +265,27 @@ pub(crate) fn build_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Trait {
|
||||
.collect();
|
||||
|
||||
let generics = clean_ty_generics(cx, did);
|
||||
let (generics, supertrait_bounds) = separate_self_bounds(generics);
|
||||
let (generics, mut supertrait_bounds) = separate_self_bounds(generics);
|
||||
|
||||
supertrait_bounds.retain(|b| {
|
||||
// FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized`
|
||||
// is shown and none of the new sizedness traits leak into documentation.
|
||||
!b.is_meta_sized_bound(cx)
|
||||
});
|
||||
|
||||
clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds }
|
||||
}
|
||||
|
||||
fn build_trait_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::TraitAlias {
|
||||
let generics = clean_ty_generics(cx, did);
|
||||
let (generics, bounds) = separate_self_bounds(generics);
|
||||
let (generics, mut bounds) = separate_self_bounds(generics);
|
||||
|
||||
bounds.retain(|b| {
|
||||
// FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized`
|
||||
// is shown and none of the new sizedness traits leak into documentation.
|
||||
!b.is_meta_sized_bound(cx)
|
||||
});
|
||||
|
||||
clean::TraitAlias { generics, bounds }
|
||||
}
|
||||
|
||||
|
||||
@@ -39,9 +39,9 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry};
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{FatalError, struct_span_code_err};
|
||||
use rustc_hir::PredicateOrigin;
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::{LangItem, PredicateOrigin};
|
||||
use rustc_hir_analysis::hir_ty_lowering::FeedConstTy;
|
||||
use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty};
|
||||
use rustc_middle::metadata::Reexport;
|
||||
@@ -886,6 +886,10 @@ fn clean_ty_generics_inner<'tcx>(
|
||||
if b.is_sized_bound(cx) {
|
||||
has_sized = true;
|
||||
false
|
||||
} else if b.is_meta_sized_bound(cx) {
|
||||
// FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized`
|
||||
// is shown and none of the new sizedness traits leak into documentation.
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
@@ -1448,6 +1452,13 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
|
||||
}
|
||||
_ => true,
|
||||
});
|
||||
|
||||
bounds.retain(|b| {
|
||||
// FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized`
|
||||
// is shown and none of the new sizedness traits leak into documentation.
|
||||
!b.is_meta_sized_bound(cx)
|
||||
});
|
||||
|
||||
// Our Sized/?Sized bound didn't get handled when creating the generics
|
||||
// because we didn't actually get our whole set of bounds until just now
|
||||
// (some of them may have come from the trait). If we do have a sized
|
||||
@@ -2276,6 +2287,12 @@ fn clean_middle_opaque_bounds<'tcx>(
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
// FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized`
|
||||
// is shown and none of the new sizedness traits leak into documentation.
|
||||
if cx.tcx.is_lang_item(trait_ref.def_id(), LangItem::MetaSized) {
|
||||
return None;
|
||||
}
|
||||
|
||||
if let Some(sized) = cx.tcx.lang_items().sized_trait()
|
||||
&& trait_ref.def_id() == sized
|
||||
{
|
||||
|
||||
@@ -135,11 +135,17 @@ pub(crate) fn sized_bounds(cx: &mut DocContext<'_>, generics: &mut clean::Generi
|
||||
// don't actually know the set of associated types right here so that
|
||||
// should be handled when cleaning associated types.
|
||||
generics.where_predicates.retain(|pred| {
|
||||
if let WP::BoundPredicate { ty: clean::Generic(param), bounds, .. } = pred
|
||||
&& bounds.iter().any(|b| b.is_sized_bound(cx))
|
||||
{
|
||||
let WP::BoundPredicate { ty: clean::Generic(param), bounds, .. } = pred else {
|
||||
return true;
|
||||
};
|
||||
|
||||
if bounds.iter().any(|b| b.is_sized_bound(cx)) {
|
||||
sized_params.insert(*param);
|
||||
false
|
||||
} else if bounds.iter().any(|b| b.is_meta_sized_bound(cx)) {
|
||||
// FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized`
|
||||
// is shown and none of the new sizedness traits leak into documentation.
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
||||
@@ -1289,11 +1289,19 @@ impl GenericBound {
|
||||
}
|
||||
|
||||
pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
|
||||
self.is_bounded_by_lang_item(cx, LangItem::Sized)
|
||||
}
|
||||
|
||||
pub(crate) fn is_meta_sized_bound(&self, cx: &DocContext<'_>) -> bool {
|
||||
self.is_bounded_by_lang_item(cx, LangItem::MetaSized)
|
||||
}
|
||||
|
||||
fn is_bounded_by_lang_item(&self, cx: &DocContext<'_>, lang_item: LangItem) -> bool {
|
||||
if let GenericBound::TraitBound(
|
||||
PolyTrait { ref trait_, .. },
|
||||
rustc_hir::TraitBoundModifiers::NONE,
|
||||
) = *self
|
||||
&& Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait()
|
||||
&& cx.tcx.is_lang_item(trait_.def_id(), lang_item)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -388,9 +388,11 @@ fn check_other_call_arg<'tcx>(
|
||||
&& let (input, n_refs) = peel_middle_ty_refs(*input)
|
||||
&& let (trait_predicates, _) = get_input_traits_and_projections(cx, callee_def_id, input)
|
||||
&& let Some(sized_def_id) = cx.tcx.lang_items().sized_trait()
|
||||
&& let Some(meta_sized_def_id) = cx.tcx.lang_items().meta_sized_trait()
|
||||
&& let [trait_predicate] = trait_predicates
|
||||
.iter()
|
||||
.filter(|trait_predicate| trait_predicate.def_id() != sized_def_id)
|
||||
.filter(|trait_predicate| trait_predicate.def_id() != meta_sized_def_id)
|
||||
.collect::<Vec<_>>()[..]
|
||||
&& let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref)
|
||||
&& let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef)
|
||||
|
||||
@@ -174,6 +174,7 @@ fn needless_borrow_count<'tcx>(
|
||||
) -> usize {
|
||||
let destruct_trait_def_id = cx.tcx.lang_items().destruct_trait();
|
||||
let sized_trait_def_id = cx.tcx.lang_items().sized_trait();
|
||||
let meta_sized_trait_def_id = cx.tcx.lang_items().meta_sized_trait();
|
||||
let drop_trait_def_id = cx.tcx.lang_items().drop_trait();
|
||||
|
||||
let fn_sig = cx.tcx.fn_sig(fn_id).instantiate_identity().skip_binder();
|
||||
@@ -209,6 +210,7 @@ fn needless_borrow_count<'tcx>(
|
||||
.all(|trait_def_id| {
|
||||
Some(trait_def_id) == destruct_trait_def_id
|
||||
|| Some(trait_def_id) == sized_trait_def_id
|
||||
|| Some(trait_def_id) == meta_sized_trait_def_id
|
||||
|| cx.tcx.is_diagnostic_item(sym::Any, trait_def_id)
|
||||
})
|
||||
{
|
||||
|
||||
@@ -116,13 +116,16 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
||||
];
|
||||
|
||||
let sized_trait = need!(cx.tcx.lang_items().sized_trait());
|
||||
let meta_sized_trait = need!(cx.tcx.lang_items().meta_sized_trait());
|
||||
|
||||
let preds = traits::elaborate(cx.tcx, cx.param_env.caller_bounds().iter())
|
||||
.filter(|p| !p.is_global())
|
||||
.filter_map(|pred| {
|
||||
// Note that we do not want to deal with qualified predicates here.
|
||||
match pred.kind().no_bound_vars() {
|
||||
Some(ty::ClauseKind::Trait(pred)) if pred.def_id() != sized_trait => Some(pred),
|
||||
Some(ty::ClauseKind::Trait(pred))
|
||||
if pred.def_id() != sized_trait && pred.def_id() != meta_sized_trait
|
||||
=> Some(pred),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -7,8 +7,14 @@
|
||||
#[link(name = "c")]
|
||||
unsafe extern "C" {}
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
pub trait Sized: MetaSized {}
|
||||
#[lang = "copy"]
|
||||
pub trait Copy {}
|
||||
#[lang = "freeze"]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
|
||||
--> tests/ui/def_id_nocore.rs:27:19
|
||||
--> tests/ui/def_id_nocore.rs:33:19
|
||||
|
|
||||
LL | pub fn as_ref(self) -> &'static str {
|
||||
| ^^^^
|
||||
|
||||
@@ -72,7 +72,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||
}
|
||||
// Functions with no declared return type (i.e., the default return)
|
||||
// have the output_type `Tuple([])`.
|
||||
ty::Tuple(t_list) if t_list.is_empty() => {
|
||||
ty::Tuple(t_list) if (*t_list).deref().is_empty() => {
|
||||
unsafe { ffi::call::<()>(ptr, libffi_args.as_slice()) };
|
||||
return interp_ok(ImmTy::uninit(dest.layout));
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: trying to retag from <TAG> for Unique permission at ALLOC[0x0], but that tag only grants SharedReadOnly permission for this location
|
||||
--> RUSTLIB/core/src/ptr/mod.rs:LL:CC
|
||||
|
|
||||
LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this error occurs as part of retag at ALLOC[0x0..0x1]
|
||||
LL | pub unsafe fn drop_in_place<T: PointeeSized>(to_drop: *mut T) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this error occurs as part of retag at ALLOC[0x0..0x1]
|
||||
|
|
||||
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
||||
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: constructing invalid value: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN)
|
||||
--> RUSTLIB/core/src/ptr/mod.rs:LL:CC
|
||||
|
|
||||
LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
||||
LL | pub unsafe fn drop_in_place<T: PointeeSized>(to_drop: *mut T) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
||||
@@ -10,8 +10,12 @@
|
||||
#![feature(abi_ptx, lang_items, no_core)]
|
||||
#![no_core]
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
trait PointeeSized {}
|
||||
#[lang = "meta_sized"]
|
||||
trait MetaSized: PointeeSized {}
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
trait Sized: MetaSized {}
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
|
||||
@@ -10,8 +10,12 @@
|
||||
#![feature(abi_ptx, lang_items, no_core)]
|
||||
#![no_core]
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
trait PointeeSized {}
|
||||
#[lang = "meta_sized"]
|
||||
trait MetaSized: PointeeSized {}
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
trait Sized: MetaSized {}
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
|
||||
@@ -20,8 +20,12 @@
|
||||
#![feature(abi_ptx, lang_items, no_core)]
|
||||
#![no_core]
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
trait PointeeSized {}
|
||||
#[lang = "meta_sized"]
|
||||
trait MetaSized: PointeeSized {}
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
trait Sized: MetaSized {}
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
|
||||
@@ -13,12 +13,16 @@
|
||||
#![crate_type = "lib"]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
// FIXME: Migrate these code after PR #130693 is landed.
|
||||
// vvvvv core
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
pub trait Sized: MetaSized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
@@ -15,12 +15,17 @@
|
||||
#![no_core]
|
||||
#![crate_type = "lib"]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
// Cases where vector feature is disabled are rejected.
|
||||
// See tests/ui/simd-abi-checks-s390x.rs for test for them.
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
pub trait Sized: MetaSized {}
|
||||
#[lang = "copy"]
|
||||
pub trait Copy {}
|
||||
#[lang = "freeze"]
|
||||
|
||||
@@ -19,8 +19,14 @@
|
||||
#![no_core]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
pub trait Sized: MetaSized {}
|
||||
|
||||
#[lang = "drop_in_place"]
|
||||
fn drop_in_place<T>(_: *mut T) {}
|
||||
|
||||
@@ -39,13 +39,19 @@ macro_rules! impl_marker_trait {
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
pub trait Sized: MetaSized {}
|
||||
|
||||
#[lang = "legacy_receiver"]
|
||||
pub trait LegacyReceiver {}
|
||||
impl<T: ?Sized> LegacyReceiver for &T {}
|
||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
||||
impl<T: PointeeSized> LegacyReceiver for &T {}
|
||||
impl<T: PointeeSized> LegacyReceiver for &mut T {}
|
||||
|
||||
#[lang = "copy"]
|
||||
pub trait Copy: Sized {}
|
||||
@@ -67,14 +73,14 @@ impl_marker_trait!(
|
||||
f16, f32, f64, f128,
|
||||
]
|
||||
);
|
||||
impl<'a, T: ?Sized> Copy for &'a T {}
|
||||
impl<T: ?Sized> Copy for *const T {}
|
||||
impl<T: ?Sized> Copy for *mut T {}
|
||||
impl<'a, T: PointeeSized> Copy for &'a T {}
|
||||
impl<T: PointeeSized> Copy for *const T {}
|
||||
impl<T: PointeeSized> Copy for *mut T {}
|
||||
impl<T: Copy, const N: usize> Copy for [T; N] {}
|
||||
|
||||
#[lang = "phantom_data"]
|
||||
pub struct PhantomData<T: ?Sized>;
|
||||
impl<T: ?Sized> Copy for PhantomData<T> {}
|
||||
pub struct PhantomData<T: PointeeSized>;
|
||||
impl<T: PointeeSized> Copy for PhantomData<T> {}
|
||||
|
||||
pub enum Option<T> {
|
||||
None,
|
||||
@@ -90,17 +96,17 @@ impl<T: Copy, E: Copy> Copy for Result<T, E> {}
|
||||
|
||||
#[lang = "manually_drop"]
|
||||
#[repr(transparent)]
|
||||
pub struct ManuallyDrop<T: ?Sized> {
|
||||
pub struct ManuallyDrop<T: PointeeSized> {
|
||||
value: T,
|
||||
}
|
||||
impl<T: Copy + ?Sized> Copy for ManuallyDrop<T> {}
|
||||
impl<T: Copy + PointeeSized> Copy for ManuallyDrop<T> {}
|
||||
|
||||
#[lang = "unsafe_cell"]
|
||||
#[repr(transparent)]
|
||||
pub struct UnsafeCell<T: ?Sized> {
|
||||
pub struct UnsafeCell<T: PointeeSized> {
|
||||
value: T,
|
||||
}
|
||||
impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
|
||||
impl<T: PointeeSized> !Freeze for UnsafeCell<T> {}
|
||||
|
||||
#[lang = "tuple_trait"]
|
||||
pub trait Tuple {}
|
||||
@@ -176,15 +182,15 @@ pub trait Fn<Args: Tuple>: FnMut<Args> {
|
||||
#[lang = "dispatch_from_dyn"]
|
||||
trait DispatchFromDyn<T> {}
|
||||
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
|
||||
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<&'a U> for &'a T {}
|
||||
|
||||
#[lang = "unsize"]
|
||||
trait Unsize<T: ?Sized> {}
|
||||
trait Unsize<T: PointeeSized>: PointeeSized {}
|
||||
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T: ?Sized> {}
|
||||
pub trait CoerceUnsized<T: PointeeSized> {}
|
||||
|
||||
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
|
||||
impl<'a, 'b: 'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a U> for &'b T {}
|
||||
|
||||
#[lang = "drop"]
|
||||
trait Drop {
|
||||
|
||||
@@ -28,8 +28,14 @@ fn panic_div_overflow() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
pub trait Sized: MetaSized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
@@ -17,7 +17,13 @@
|
||||
#![crate_type = "lib"]
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
trait Sized: MetaSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
trait PointeeSized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
//@ compile-flags: -C no-prepopulate-passes -Copt-level=0
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(extern_types)]
|
||||
#![feature(extern_types, sized_hierarchy)]
|
||||
|
||||
use std::marker::PointeeSized;
|
||||
use std::ptr::addr_of;
|
||||
|
||||
// Hack to get the correct type for usize
|
||||
@@ -12,7 +13,7 @@ use std::ptr::addr_of;
|
||||
#[no_mangle]
|
||||
pub fn helper(_: usize) {}
|
||||
|
||||
struct Dst<T: ?Sized> {
|
||||
struct Dst<T: PointeeSized> {
|
||||
x: u32,
|
||||
y: u8,
|
||||
z: T,
|
||||
|
||||
@@ -9,8 +9,14 @@
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
pub trait Sized: MetaSized {}
|
||||
#[lang = "freeze"]
|
||||
trait Freeze {}
|
||||
#[lang = "copy"]
|
||||
|
||||
@@ -8,8 +8,14 @@
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
pub trait Sized: MetaSized {}
|
||||
#[lang = "freeze"]
|
||||
trait Freeze {}
|
||||
#[lang = "copy"]
|
||||
|
||||
@@ -15,8 +15,14 @@
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
pub trait Sized: MetaSized {}
|
||||
|
||||
unsafe extern "C-unwind" {
|
||||
safe fn unwinds();
|
||||
|
||||
@@ -2,8 +2,15 @@
|
||||
//@ compile-flags: --target=armv7-unknown-linux-gnueabihf --crate-type=rlib -Cno-prepopulate-passes
|
||||
#![no_core]
|
||||
#![feature(no_core, lang_items)]
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
pub trait Sized: MetaSized {}
|
||||
|
||||
// Test that `nounwind` attributes are correctly applied to exported `aapcs` and
|
||||
// `aapcs-unwind` extern functions. `aapcs-unwind` functions MUST NOT have this attribute. We
|
||||
|
||||
@@ -2,8 +2,15 @@
|
||||
//@ compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
|
||||
#![no_core]
|
||||
#![feature(no_core, lang_items)]
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
pub trait Sized: MetaSized {}
|
||||
|
||||
// Test that `nounwind` attributes are correctly applied to exported `fastcall` and
|
||||
// `fastcall-unwind` extern functions. `fastcall-unwind` functions MUST NOT have this attribute. We
|
||||
|
||||
@@ -2,8 +2,15 @@
|
||||
//@ compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
|
||||
#![no_core]
|
||||
#![feature(no_core, lang_items)]
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
pub trait Sized: MetaSized {}
|
||||
|
||||
// Test that `nounwind` attributes are correctly applied to exported `stdcall` and `stdcall-unwind`
|
||||
// extern functions. `stdcall-unwind` functions MUST NOT have this attribute. We disable
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user