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]
|
#![no_core]
|
||||||
#![allow(dead_code, internal_features, ambiguous_wide_pointer_comparisons)]
|
#![allow(dead_code, internal_features, ambiguous_wide_pointer_comparisons)]
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
pub trait PointeeSized {}
|
||||||
|
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
pub trait MetaSized: PointeeSized {}
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
pub trait Sized {}
|
pub trait Sized: MetaSized {}
|
||||||
|
|
||||||
#[lang = "destruct"]
|
#[lang = "destruct"]
|
||||||
pub trait Destruct {}
|
pub trait Destruct {}
|
||||||
@@ -24,35 +30,35 @@ pub trait Destruct {}
|
|||||||
pub trait Tuple {}
|
pub trait Tuple {}
|
||||||
|
|
||||||
#[lang = "unsize"]
|
#[lang = "unsize"]
|
||||||
pub trait Unsize<T: ?Sized> {}
|
pub trait Unsize<T: PointeeSized>: PointeeSized {}
|
||||||
|
|
||||||
#[lang = "coerce_unsized"]
|
#[lang = "coerce_unsized"]
|
||||||
pub trait CoerceUnsized<T> {}
|
pub trait CoerceUnsized<T> {}
|
||||||
|
|
||||||
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 {}
|
||||||
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 {}
|
||||||
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 {}
|
||||||
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 {}
|
||||||
|
|
||||||
#[lang = "dispatch_from_dyn"]
|
#[lang = "dispatch_from_dyn"]
|
||||||
pub trait DispatchFromDyn<T> {}
|
pub trait DispatchFromDyn<T> {}
|
||||||
|
|
||||||
// &T -> &U
|
// &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
|
// &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
|
// *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
|
// *mut T -> *mut U
|
||||||
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 {}
|
||||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T> {}
|
impl<T: MetaSized + Unsize<U>, U: MetaSized> DispatchFromDyn<Box<U>> for Box<T> {}
|
||||||
|
|
||||||
#[lang = "legacy_receiver"]
|
#[lang = "legacy_receiver"]
|
||||||
pub trait LegacyReceiver {}
|
pub trait LegacyReceiver {}
|
||||||
|
|
||||||
impl<T: ?Sized> LegacyReceiver for &T {}
|
impl<T: PointeeSized> LegacyReceiver for &T {}
|
||||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
impl<T: PointeeSized> LegacyReceiver for &mut T {}
|
||||||
impl<T: ?Sized> LegacyReceiver for Box<T> {}
|
impl<T: MetaSized> LegacyReceiver for Box<T> {}
|
||||||
|
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
pub trait Copy {}
|
pub trait Copy {}
|
||||||
@@ -74,9 +80,9 @@ impl Copy for isize {}
|
|||||||
impl Copy for f32 {}
|
impl Copy for f32 {}
|
||||||
impl Copy for f64 {}
|
impl Copy for f64 {}
|
||||||
impl Copy for char {}
|
impl Copy for char {}
|
||||||
impl<'a, T: ?Sized> Copy for &'a T {}
|
impl<'a, T: PointeeSized> Copy for &'a T {}
|
||||||
impl<T: ?Sized> Copy for *const T {}
|
impl<T: PointeeSized> Copy for *const T {}
|
||||||
impl<T: ?Sized> Copy for *mut T {}
|
impl<T: PointeeSized> Copy for *mut T {}
|
||||||
impl<T: Copy> Copy for Option<T> {}
|
impl<T: Copy> Copy for Option<T> {}
|
||||||
|
|
||||||
#[lang = "sync"]
|
#[lang = "sync"]
|
||||||
@@ -94,17 +100,17 @@ unsafe impl Sync for i32 {}
|
|||||||
unsafe impl Sync for isize {}
|
unsafe impl Sync for isize {}
|
||||||
unsafe impl Sync for char {}
|
unsafe impl Sync for char {}
|
||||||
unsafe impl Sync for f32 {}
|
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] {}
|
unsafe impl<T: Sync, const N: usize> Sync for [T; N] {}
|
||||||
|
|
||||||
#[lang = "freeze"]
|
#[lang = "freeze"]
|
||||||
unsafe auto trait Freeze {}
|
unsafe auto trait Freeze {}
|
||||||
|
|
||||||
unsafe impl<T: ?Sized> Freeze for PhantomData<T> {}
|
unsafe impl<T: PointeeSized> Freeze for PhantomData<T> {}
|
||||||
unsafe impl<T: ?Sized> Freeze for *const T {}
|
unsafe impl<T: PointeeSized> Freeze for *const T {}
|
||||||
unsafe impl<T: ?Sized> Freeze for *mut T {}
|
unsafe impl<T: PointeeSized> Freeze for *mut T {}
|
||||||
unsafe impl<T: ?Sized> Freeze for &T {}
|
unsafe impl<T: PointeeSized> Freeze for &T {}
|
||||||
unsafe impl<T: ?Sized> Freeze for &mut T {}
|
unsafe impl<T: PointeeSized> Freeze for &mut T {}
|
||||||
|
|
||||||
#[lang = "structural_peq"]
|
#[lang = "structural_peq"]
|
||||||
pub trait StructuralPartialEq {}
|
pub trait StructuralPartialEq {}
|
||||||
@@ -443,7 +449,7 @@ pub enum Option<T> {
|
|||||||
pub use Option::*;
|
pub use Option::*;
|
||||||
|
|
||||||
#[lang = "phantom_data"]
|
#[lang = "phantom_data"]
|
||||||
pub struct PhantomData<T: ?Sized>;
|
pub struct PhantomData<T: PointeeSized>;
|
||||||
|
|
||||||
#[lang = "fn_once"]
|
#[lang = "fn_once"]
|
||||||
#[rustc_paren_sugar]
|
#[rustc_paren_sugar]
|
||||||
@@ -564,18 +570,18 @@ pub trait Deref {
|
|||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[rustc_layout_scalar_valid_range_start(1)]
|
#[rustc_layout_scalar_valid_range_start(1)]
|
||||||
#[rustc_nonnull_optimization_guaranteed]
|
#[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: PointeeSized, U: PointeeSized> 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> 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 pointer: NonNull<T>,
|
||||||
pub _marker: PhantomData<T>,
|
pub _marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
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> {}
|
||||||
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> {}
|
||||||
|
|
||||||
#[lang = "global_alloc_ty"]
|
#[lang = "global_alloc_ty"]
|
||||||
pub struct Global;
|
pub struct Global;
|
||||||
|
|||||||
@@ -19,8 +19,14 @@ unsafe extern "C" fn _Unwind_Resume() {
|
|||||||
intrinsics::unreachable();
|
intrinsics::unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
pub trait PointeeSized {}
|
||||||
|
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
pub trait MetaSized: PointeeSized {}
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
pub trait Sized {}
|
pub trait Sized: MetaSized {}
|
||||||
|
|
||||||
#[lang = "destruct"]
|
#[lang = "destruct"]
|
||||||
pub trait Destruct {}
|
pub trait Destruct {}
|
||||||
@@ -29,35 +35,35 @@ pub trait Destruct {}
|
|||||||
pub trait Tuple {}
|
pub trait Tuple {}
|
||||||
|
|
||||||
#[lang = "unsize"]
|
#[lang = "unsize"]
|
||||||
pub trait Unsize<T: ?Sized> {}
|
pub trait Unsize<T: PointeeSized>: PointeeSized {}
|
||||||
|
|
||||||
#[lang = "coerce_unsized"]
|
#[lang = "coerce_unsized"]
|
||||||
pub trait CoerceUnsized<T> {}
|
pub trait CoerceUnsized<T> {}
|
||||||
|
|
||||||
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 {}
|
||||||
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 {}
|
||||||
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 {}
|
||||||
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 {}
|
||||||
|
|
||||||
#[lang = "dispatch_from_dyn"]
|
#[lang = "dispatch_from_dyn"]
|
||||||
pub trait DispatchFromDyn<T> {}
|
pub trait DispatchFromDyn<T> {}
|
||||||
|
|
||||||
// &T -> &U
|
// &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
|
// &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
|
// *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
|
// *mut T -> *mut U
|
||||||
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 {}
|
||||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U, ()>> for Box<T, ()> {}
|
impl<T: MetaSized + Unsize<U>, U: MetaSized> DispatchFromDyn<Box<U, ()>> for Box<T, ()> {}
|
||||||
|
|
||||||
#[lang = "legacy_receiver"]
|
#[lang = "legacy_receiver"]
|
||||||
pub trait LegacyReceiver {}
|
pub trait LegacyReceiver {}
|
||||||
|
|
||||||
impl<T: ?Sized> LegacyReceiver for &T {}
|
impl<T: PointeeSized> LegacyReceiver for &T {}
|
||||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
impl<T: PointeeSized> LegacyReceiver for &mut T {}
|
||||||
impl<T: ?Sized, A: Allocator> LegacyReceiver for Box<T, A> {}
|
impl<T: MetaSized> LegacyReceiver for Box<T> {}
|
||||||
|
|
||||||
#[lang = "receiver"]
|
#[lang = "receiver"]
|
||||||
trait Receiver {}
|
trait Receiver {}
|
||||||
@@ -84,9 +90,9 @@ impl Copy for i128 {}
|
|||||||
impl Copy for f32 {}
|
impl Copy for f32 {}
|
||||||
impl Copy for f64 {}
|
impl Copy for f64 {}
|
||||||
impl Copy for char {}
|
impl Copy for char {}
|
||||||
impl<'a, T: ?Sized> Copy for &'a T {}
|
impl<'a, T: PointeeSized> Copy for &'a T {}
|
||||||
impl<T: ?Sized> Copy for *const T {}
|
impl<T: PointeeSized> Copy for *const T {}
|
||||||
impl<T: ?Sized> Copy for *mut T {}
|
impl<T: PointeeSized> Copy for *mut T {}
|
||||||
|
|
||||||
#[lang = "sync"]
|
#[lang = "sync"]
|
||||||
pub unsafe trait Sync {}
|
pub unsafe trait Sync {}
|
||||||
@@ -102,17 +108,17 @@ unsafe impl Sync for i16 {}
|
|||||||
unsafe impl Sync for i32 {}
|
unsafe impl Sync for i32 {}
|
||||||
unsafe impl Sync for isize {}
|
unsafe impl Sync for isize {}
|
||||||
unsafe impl Sync for char {}
|
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] {}
|
unsafe impl Sync for [u8; 16] {}
|
||||||
|
|
||||||
#[lang = "freeze"]
|
#[lang = "freeze"]
|
||||||
unsafe auto trait Freeze {}
|
unsafe auto trait Freeze {}
|
||||||
|
|
||||||
unsafe impl<T: ?Sized> Freeze for PhantomData<T> {}
|
unsafe impl<T: PointeeSized> Freeze for PhantomData<T> {}
|
||||||
unsafe impl<T: ?Sized> Freeze for *const T {}
|
unsafe impl<T: PointeeSized> Freeze for *const T {}
|
||||||
unsafe impl<T: ?Sized> Freeze for *mut T {}
|
unsafe impl<T: PointeeSized> Freeze for *mut T {}
|
||||||
unsafe impl<T: ?Sized> Freeze for &T {}
|
unsafe impl<T: PointeeSized> Freeze for &T {}
|
||||||
unsafe impl<T: ?Sized> Freeze for &mut T {}
|
unsafe impl<T: PointeeSized> Freeze for &mut T {}
|
||||||
|
|
||||||
#[lang = "structural_peq"]
|
#[lang = "structural_peq"]
|
||||||
pub trait StructuralPartialEq {}
|
pub trait StructuralPartialEq {}
|
||||||
@@ -456,7 +462,7 @@ pub enum Option<T> {
|
|||||||
pub use Option::*;
|
pub use Option::*;
|
||||||
|
|
||||||
#[lang = "phantom_data"]
|
#[lang = "phantom_data"]
|
||||||
pub struct PhantomData<T: ?Sized>;
|
pub struct PhantomData<T: PointeeSized>;
|
||||||
|
|
||||||
#[lang = "fn_once"]
|
#[lang = "fn_once"]
|
||||||
#[rustc_paren_sugar]
|
#[rustc_paren_sugar]
|
||||||
@@ -576,18 +582,18 @@ impl Allocator for Global {}
|
|||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[rustc_layout_scalar_valid_range_start(1)]
|
#[rustc_layout_scalar_valid_range_start(1)]
|
||||||
#[rustc_nonnull_optimization_guaranteed]
|
#[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: PointeeSized, U: PointeeSized> 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> 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 pointer: NonNull<T>,
|
||||||
pub _marker: PhantomData<T>,
|
pub _marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
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> {}
|
||||||
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> {}
|
||||||
|
|
||||||
#[lang = "owned_box"]
|
#[lang = "owned_box"]
|
||||||
pub struct Box<T: ?Sized, A: Allocator = Global>(Unique<T>, A);
|
pub struct Box<T: ?Sized, A: Allocator = Global>(Unique<T>, A);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
use std::ptr::Alignment;
|
use std::ptr::Alignment;
|
||||||
|
|
||||||
|
use rustc_serialize::PointeeSized;
|
||||||
|
|
||||||
/// Returns the ABI-required minimum alignment of a type in bytes.
|
/// Returns the ABI-required minimum alignment of a type in bytes.
|
||||||
///
|
///
|
||||||
/// This is equivalent to [`align_of`], but also works for some unsized
|
/// 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`.
|
/// example `[T]` has alignment of `T`.
|
||||||
///
|
///
|
||||||
/// [`align_of::<Self>()`]: align_of
|
/// [`align_of::<Self>()`]: align_of
|
||||||
pub unsafe trait Aligned {
|
pub unsafe trait Aligned: PointeeSized {
|
||||||
/// Alignment of `Self`.
|
/// Alignment of `Self`.
|
||||||
const ALIGN: Alignment;
|
const ALIGN: Alignment;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#![allow(rustc::potential_query_instability)]
|
#![allow(rustc::potential_query_instability)]
|
||||||
#![cfg_attr(bootstrap, feature(cfg_match))]
|
#![cfg_attr(bootstrap, feature(cfg_match))]
|
||||||
#![cfg_attr(not(bootstrap), feature(cfg_select))]
|
#![cfg_attr(not(bootstrap), feature(cfg_select))]
|
||||||
|
#![cfg_attr(not(bootstrap), feature(sized_hierarchy))]
|
||||||
#![deny(unsafe_op_in_unsafe_fn)]
|
#![deny(unsafe_op_in_unsafe_fn)]
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||||
#![doc(rust_logo)]
|
#![doc(rust_logo)]
|
||||||
@@ -43,6 +44,9 @@ use std::fmt;
|
|||||||
pub use atomic_ref::AtomicRef;
|
pub use atomic_ref::AtomicRef;
|
||||||
pub use ena::{snapshot_vec, undo_log, unify};
|
pub use ena::{snapshot_vec, undo_log, unify};
|
||||||
pub use rustc_index::static_assert_size;
|
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 aligned;
|
||||||
pub mod base_n;
|
pub mod base_n;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
use std::alloc::Allocator;
|
use std::alloc::Allocator;
|
||||||
|
|
||||||
|
use rustc_serialize::PointeeSized;
|
||||||
|
|
||||||
#[diagnostic::on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \
|
#[diagnostic::on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \
|
||||||
Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`")]
|
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()`
|
// 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 {}
|
pub unsafe auto trait DynSync {}
|
||||||
|
|
||||||
// Same with `Sync` and `Send`.
|
// 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 {
|
macro_rules! impls_dyn_send_neg {
|
||||||
($([$t1: ty $(where $($generics1: tt)*)?])*) => {
|
($([$t1: ty $(where $($generics1: tt)*)?])*) => {
|
||||||
@@ -27,9 +29,9 @@ macro_rules! impls_dyn_send_neg {
|
|||||||
impls_dyn_send_neg!(
|
impls_dyn_send_neg!(
|
||||||
[std::env::Args]
|
[std::env::Args]
|
||||||
[std::env::ArgsOs]
|
[std::env::ArgsOs]
|
||||||
[*const T where T: ?Sized]
|
[*const T where T: ?Sized + PointeeSized]
|
||||||
[*mut T where T: ?Sized]
|
[*mut T where T: ?Sized + PointeeSized]
|
||||||
[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::Rc<T, A> where T: ?Sized, A: Allocator]
|
||||||
[std::rc::Weak<T, A> where T: ?Sized, A: Allocator]
|
[std::rc::Weak<T, A> where T: ?Sized, A: Allocator]
|
||||||
[std::sync::MutexGuard<'_, T> where T: ?Sized]
|
[std::sync::MutexGuard<'_, T> where T: ?Sized]
|
||||||
@@ -100,12 +102,12 @@ macro_rules! impls_dyn_sync_neg {
|
|||||||
impls_dyn_sync_neg!(
|
impls_dyn_sync_neg!(
|
||||||
[std::env::Args]
|
[std::env::Args]
|
||||||
[std::env::ArgsOs]
|
[std::env::ArgsOs]
|
||||||
[*const T where T: ?Sized]
|
[*const T where T: ?Sized + PointeeSized]
|
||||||
[*mut T where T: ?Sized]
|
[*mut T where T: ?Sized + PointeeSized]
|
||||||
[std::cell::Cell<T> where T: ?Sized]
|
[std::cell::Cell<T> where T: ?Sized]
|
||||||
[std::cell::RefCell<T> where T: ?Sized]
|
[std::cell::RefCell<T> where T: ?Sized]
|
||||||
[std::cell::UnsafeCell<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::Rc<T, A> where T: ?Sized, A: Allocator]
|
||||||
[std::rc::Weak<T, A> where T: ?Sized, A: Allocator]
|
[std::rc::Weak<T, A> where T: ?Sized, A: Allocator]
|
||||||
[std::cell::OnceCell<T> where T]
|
[std::cell::OnceCell<T> where T]
|
||||||
@@ -175,10 +177,10 @@ impl_dyn_sync!(
|
|||||||
[thin_vec::ThinVec<T> where T: DynSync]
|
[thin_vec::ThinVec<T> where T: DynSync]
|
||||||
);
|
);
|
||||||
|
|
||||||
pub fn assert_dyn_sync<T: ?Sized + DynSync>() {}
|
pub fn assert_dyn_sync<T: ?Sized + PointeeSized + DynSync>() {}
|
||||||
pub fn assert_dyn_send<T: ?Sized + DynSend>() {}
|
pub fn assert_dyn_send<T: ?Sized + PointeeSized + DynSend>() {}
|
||||||
pub fn assert_dyn_send_val<T: ?Sized + DynSend>(_t: &T) {}
|
pub fn assert_dyn_send_val<T: ?Sized + PointeeSized + DynSend>(_t: &T) {}
|
||||||
pub fn assert_dyn_send_sync_val<T: ?Sized + DynSync + DynSend>(_t: &T) {}
|
pub fn assert_dyn_send_sync_val<T: ?Sized + PointeeSized + DynSync + DynSend>(_t: &T) {}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct FromDyn<T>(T);
|
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
|
// an instance of `DynSend` and `DynSync`, since the compiler cannot infer
|
||||||
// it automatically in some cases. (e.g. Box<dyn Send / Sync>)
|
// it automatically in some cases. (e.g. Box<dyn Send / Sync>)
|
||||||
#[derive(Copy, Clone)]
|
#[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 + PointeeSized + Send> DynSend for IntoDynSyncSend<T> {}
|
||||||
unsafe impl<T: ?Sized + Sync> DynSync for IntoDynSyncSend<T> {}
|
unsafe impl<T: ?Sized + PointeeSized + Sync> DynSync for IntoDynSyncSend<T> {}
|
||||||
|
|
||||||
impl<T> std::ops::Deref for IntoDynSyncSend<T> {
|
impl<T> std::ops::Deref for IntoDynSyncSend<T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|||||||
@@ -237,6 +237,8 @@ declare_features! (
|
|||||||
(internal, profiler_runtime, "1.18.0", None),
|
(internal, profiler_runtime, "1.18.0", None),
|
||||||
/// Allows using `rustc_*` attributes (RFC 572).
|
/// Allows using `rustc_*` attributes (RFC 572).
|
||||||
(internal, rustc_attrs, "1.0.0", None),
|
(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.
|
/// Allows using the `#[stable]` and `#[unstable]` attributes.
|
||||||
(internal, staged_api, "1.0.0", None),
|
(internal, staged_api, "1.0.0", None),
|
||||||
/// Added for testing unstable lints; perma-unstable.
|
/// Added for testing unstable lints; perma-unstable.
|
||||||
|
|||||||
@@ -165,6 +165,8 @@ pub fn extract(attrs: &[impl AttributeExt]) -> Option<(Symbol, Span)> {
|
|||||||
language_item_table! {
|
language_item_table! {
|
||||||
// Variant name, Name, Getter method name, Target Generic requirements;
|
// Variant name, Name, Getter method name, Target Generic requirements;
|
||||||
Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
|
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);
|
Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
|
||||||
/// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
|
/// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
|
||||||
StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None;
|
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_abi::{ExternAbi, VariantIdx};
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||||
use rustc_errors::{Diag, ErrorGuaranteed, pluralize, struct_span_code_err};
|
use rustc_errors::{Diag, ErrorGuaranteed, pluralize, struct_span_code_err};
|
||||||
|
use rustc_hir::LangItem;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_index::bit_set::DenseBitSet;
|
use rustc_index::bit_set::DenseBitSet;
|
||||||
@@ -331,7 +332,7 @@ fn bounds_from_generic_predicates<'tcx>(
|
|||||||
ty::ClauseKind::Trait(trait_predicate) => {
|
ty::ClauseKind::Trait(trait_predicate) => {
|
||||||
let entry = types.entry(trait_predicate.self_ty()).or_default();
|
let entry = types.entry(trait_predicate.self_ty()).or_default();
|
||||||
let def_id = trait_predicate.def_id();
|
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.
|
// Do not add that restriction to the list if it is a positive requirement.
|
||||||
entry.push(trait_predicate.def_id());
|
entry.push(trait_predicate.def_id());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1258,6 +1258,11 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuarant
|
|||||||
debug!(?item.owner_id);
|
debug!(?item.owner_id);
|
||||||
|
|
||||||
let def_id = item.owner_id.def_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);
|
let trait_def = tcx.trait_def(def_id);
|
||||||
if trait_def.is_marker
|
if trait_def.is_marker
|
||||||
|| matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker)
|
|| matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker)
|
||||||
|
|||||||
@@ -44,6 +44,14 @@ fn associated_type_bounds<'tcx>(
|
|||||||
| PredicateFilter::SelfOnly
|
| PredicateFilter::SelfOnly
|
||||||
| PredicateFilter::SelfTraitThatDefines(_)
|
| PredicateFilter::SelfTraitThatDefines(_)
|
||||||
| PredicateFilter::SelfAndAssociatedTypeBounds => {
|
| 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);
|
icx.lowerer().add_default_traits(&mut bounds, item_ty, hir_bounds, None, span);
|
||||||
}
|
}
|
||||||
// `ConstIfConst` is only interested in `~const` bounds.
|
// `ConstIfConst` is only interested in `~const` bounds.
|
||||||
@@ -333,6 +341,14 @@ fn opaque_type_bounds<'tcx>(
|
|||||||
| PredicateFilter::SelfOnly
|
| PredicateFilter::SelfOnly
|
||||||
| PredicateFilter::SelfTraitThatDefines(_)
|
| PredicateFilter::SelfTraitThatDefines(_)
|
||||||
| PredicateFilter::SelfAndAssociatedTypeBounds => {
|
| 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);
|
icx.lowerer().add_default_traits(&mut bounds, item_ty, hir_bounds, None, span);
|
||||||
}
|
}
|
||||||
//`ConstIfConst` is only interested in `~const` bounds.
|
//`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()));
|
.map(|t| ty::Binder::dummy(t.instantiate_identity()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKind::Trait(_, _, _, _, self_bounds, ..)
|
ItemKind::Trait(_, _, _, _, self_bounds, ..)
|
||||||
| ItemKind::TraitAlias(_, _, self_bounds) => {
|
| ItemKind::TraitAlias(_, _, self_bounds) => {
|
||||||
is_trait = Some((self_bounds, item.span));
|
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
|
// 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,
|
// on a trait we must also consider the bounds that follow the trait's name,
|
||||||
// like `trait Foo: A + B + C`.
|
// 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();
|
let mut bounds = Vec::new();
|
||||||
icx.lowerer().lower_bounds(
|
icx.lowerer().lower_bounds(
|
||||||
tcx.types.self_param,
|
tcx.types.self_param,
|
||||||
self_bounds.0,
|
self_bounds,
|
||||||
&mut bounds,
|
&mut bounds,
|
||||||
ty::List::empty(),
|
ty::List::empty(),
|
||||||
PredicateFilter::All,
|
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(
|
icx.lowerer().add_default_super_traits(
|
||||||
def_id,
|
def_id,
|
||||||
&mut bounds,
|
&mut bounds,
|
||||||
self_bounds.0,
|
self_bounds,
|
||||||
hir_generics,
|
hir_generics,
|
||||||
self_bounds.1,
|
span,
|
||||||
);
|
);
|
||||||
predicates.extend(bounds);
|
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 param_ty = icx.lowerer().lower_ty_param(param.hir_id);
|
||||||
let mut bounds = Vec::new();
|
let mut bounds = Vec::new();
|
||||||
// Implicit bounds are added to type params unless a `?Trait` bound is found
|
// 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(
|
icx.lowerer().add_default_traits(
|
||||||
&mut bounds,
|
&mut bounds,
|
||||||
param_ty,
|
param_ty,
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
|||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::struct_span_code_err;
|
use rustc_errors::struct_span_code_err;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::AmbigArg;
|
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
|
use rustc_hir::{AmbigArg, LangItem, PolyTraitRef};
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||||
TypeVisitor, Upcast,
|
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 rustc_trait_selection::traits;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
@@ -23,23 +23,213 @@ use crate::hir_ty_lowering::{
|
|||||||
AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason,
|
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> + '_ {
|
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,
|
&self,
|
||||||
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
||||||
self_ty: Ty<'tcx>,
|
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>])>,
|
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||||
|
trait_did: Option<LocalDefId>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) {
|
) {
|
||||||
self.add_default_traits_with_filter(
|
let tcx = self.tcx();
|
||||||
bounds,
|
|
||||||
self_ty,
|
let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
|
||||||
hir_bounds,
|
let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
|
||||||
self_ty_where_predicates,
|
|
||||||
span,
|
// If adding sizedness bounds to a trait, then there are some relevant early exits
|
||||||
|_| true,
|
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
|
/// 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) {
|
if !self.requires_default_supertraits(trait_bounds, trait_generics) {
|
||||||
let self_ty_where_predicates = (parent, trait_item.generics.predicates);
|
let self_ty_where_predicates = (parent, trait_item.generics.predicates);
|
||||||
self.add_default_traits_with_filter(
|
self.add_default_traits(
|
||||||
bounds,
|
bounds,
|
||||||
tcx.types.self_param,
|
tcx.types.self_param,
|
||||||
&[],
|
&[],
|
||||||
Some(self_ty_where_predicates),
|
Some(self_ty_where_predicates),
|
||||||
trait_item.span,
|
trait_item.span,
|
||||||
|tr| tr != hir::LangItem::Sized,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,41 +363,37 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias));
|
assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias));
|
||||||
if self.requires_default_supertraits(hir_bounds, hir_generics) {
|
if self.requires_default_supertraits(hir_bounds, hir_generics) {
|
||||||
let self_ty_where_predicates = (trait_def_id, hir_generics.predicates);
|
let self_ty_where_predicates = (trait_def_id, hir_generics.predicates);
|
||||||
self.add_default_traits_with_filter(
|
self.add_default_traits(
|
||||||
bounds,
|
bounds,
|
||||||
self.tcx().types.self_param,
|
self.tcx().types.self_param,
|
||||||
hir_bounds,
|
hir_bounds,
|
||||||
Some(self_ty_where_predicates),
|
Some(self_ty_where_predicates),
|
||||||
span,
|
span,
|
||||||
|default_trait| default_trait != hir::LangItem::Sized,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_default_traits_with_filter(
|
pub(crate) fn add_default_traits(
|
||||||
&self,
|
&self,
|
||||||
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
hir_bounds: &[hir::GenericBound<'tcx>],
|
hir_bounds: &[hir::GenericBound<'tcx>],
|
||||||
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||||
span: Span,
|
span: Span,
|
||||||
f: impl Fn(hir::LangItem) -> bool,
|
|
||||||
) {
|
) {
|
||||||
self.tcx().default_traits().iter().filter(|&&default_trait| f(default_trait)).for_each(
|
self.tcx().default_traits().iter().for_each(|default_trait| {
|
||||||
|default_trait| {
|
self.add_default_trait(
|
||||||
self.add_default_trait(
|
*default_trait,
|
||||||
*default_trait,
|
bounds,
|
||||||
bounds,
|
self_ty,
|
||||||
self_ty,
|
hir_bounds,
|
||||||
hir_bounds,
|
self_ty_where_predicates,
|
||||||
self_ty_where_predicates,
|
span,
|
||||||
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`.
|
/// Doesn't add the bound if the HIR bounds contain any of `Trait`, `?Trait` or `!Trait`.
|
||||||
pub(crate) fn add_default_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>])>,
|
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||||
span: Span,
|
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
|
if let Some(trait_id) = trait_id
|
||||||
&& self.do_not_provide_default_trait_bound(
|
&& self.do_not_provide_default_trait_bound(
|
||||||
trait_id,
|
trait_id,
|
||||||
@@ -228,11 +414,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
self_ty_where_predicates,
|
self_ty_where_predicates,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// There was no `?Trait` or `!Trait` bound;
|
add_trait_bound(tcx, bounds, self_ty, trait_id, span);
|
||||||
// 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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,90 +424,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
hir_bounds: &'a [hir::GenericBound<'tcx>],
|
hir_bounds: &'a [hir::GenericBound<'tcx>],
|
||||||
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let tcx = self.tcx();
|
let collected = collect_bounds(hir_bounds, self_ty_where_predicates, trait_def_id);
|
||||||
let mut seen_negative_bound = false;
|
!collected.any()
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if 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,
|
'tcx: 'hir,
|
||||||
{
|
{
|
||||||
for hir_bound in hir_bounds {
|
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`,
|
// In order to avoid cycles, when we're lowering `SelfTraitThatDefines`,
|
||||||
// we skip over any traits that don't define the given associated type.
|
// we skip over any traits that don't define the given associated type.
|
||||||
if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
|
if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
|
||||||
|
|||||||
@@ -61,14 +61,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
let ast_bounds: Vec<_> =
|
let ast_bounds: Vec<_> =
|
||||||
hir_bounds.iter().map(|&trait_ref| hir::GenericBound::Trait(trait_ref)).collect();
|
hir_bounds.iter().map(|&trait_ref| hir::GenericBound::Trait(trait_ref)).collect();
|
||||||
|
|
||||||
self.add_default_traits_with_filter(
|
self.add_default_traits(&mut user_written_bounds, dummy_self, &ast_bounds, None, span);
|
||||||
&mut user_written_bounds,
|
|
||||||
dummy_self,
|
|
||||||
&ast_bounds,
|
|
||||||
None,
|
|
||||||
span,
|
|
||||||
|tr| tr != hir::LangItem::Sized,
|
|
||||||
);
|
|
||||||
|
|
||||||
let (elaborated_trait_bounds, elaborated_projection_bounds) =
|
let (elaborated_trait_bounds, elaborated_projection_bounds) =
|
||||||
traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
|
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::{CtorOf, DefKind, Res};
|
||||||
use rustc_hir::def_id::DefId;
|
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::bug;
|
||||||
use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
|
use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
|
||||||
use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
|
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};
|
use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
|
||||||
|
|
||||||
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
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
|
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
|
||||||
/// the type parameter's name as a placeholder.
|
/// the type parameter's name as a placeholder.
|
||||||
pub(crate) fn report_missing_type_params(
|
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_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM;
|
||||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
|
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, AdtKind, CanonicalUserType, GenericArgsRef, GenericParamDefKind, IsIdentity, Ty, TyCtxt,
|
self, AdtKind, CanonicalUserType, GenericArgsRef, GenericParamDefKind, IsIdentity,
|
||||||
TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs, UserSelfTy,
|
SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs,
|
||||||
|
UserSelfTy,
|
||||||
};
|
};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_session::lint;
|
use rustc_session::lint;
|
||||||
@@ -439,7 +440,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
|| {},
|
|| {},
|
||||||
);
|
);
|
||||||
// Sized types have static alignment, and so do slices.
|
// 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.
|
// Nothing else is required here.
|
||||||
} else {
|
} else {
|
||||||
// We can't be sure, let's required full `Sized`.
|
// We can't be sure, let's required full `Sized`.
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
|
|||||||
.tcx
|
.tcx
|
||||||
.explicit_super_predicates_of(def_id)
|
.explicit_super_predicates_of(def_id)
|
||||||
.iter_identity_copied()
|
.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 {
|
if direct_super_traits_iter.count() > 1 {
|
||||||
cx.emit_span_lint(
|
cx.emit_span_lint(
|
||||||
MULTIPLE_SUPERTRAIT_UPCASTABLE,
|
MULTIPLE_SUPERTRAIT_UPCASTABLE,
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||||
#![allow(rustc::untranslatable_diagnostic)]
|
#![allow(rustc::untranslatable_diagnostic)]
|
||||||
|
#![cfg_attr(not(bootstrap), feature(sized_hierarchy))]
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||||
#![doc(rust_logo)]
|
#![doc(rust_logo)]
|
||||||
#![feature(allocator_api)]
|
#![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> {
|
impl<'tcx> Key for GenericArgsRef<'tcx> {
|
||||||
type Cache<V> = DefaultCache<Self, V>;
|
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::print::{PrintTraitRefExt, describe_as_module};
|
||||||
use crate::ty::util::AlwaysRequiresDrop;
|
use crate::ty::util::AlwaysRequiresDrop;
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, Ty, TyCtxt,
|
self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, SizedTraitKind, Ty,
|
||||||
TyCtxtFeed,
|
TyCtxt, TyCtxtFeed,
|
||||||
};
|
};
|
||||||
use crate::{dep_graph, mir, thir};
|
use crate::{dep_graph, mir, thir};
|
||||||
|
|
||||||
@@ -910,9 +910,10 @@ rustc_queries! {
|
|||||||
cache_on_disk_if { key.is_local() }
|
cache_on_disk_if { key.is_local() }
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
}
|
}
|
||||||
|
query adt_sizedness_constraint(
|
||||||
query adt_sized_constraint(key: DefId) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
key: (DefId, SizedTraitKind)
|
||||||
desc { |tcx| "computing the `Sized` constraint for `{}`", tcx.def_path_str(key) }
|
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
||||||
|
desc { |tcx| "computing the sizedness constraint for `{}`", tcx.def_path_str(key.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
query adt_dtorck_constraint(
|
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>>> {
|
fn sizedness_constraint(
|
||||||
self.sized_constraint(tcx)
|
self,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
sizedness: ty::SizedTraitKind,
|
||||||
|
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
||||||
|
self.sizedness_constraint(tcx, sizedness)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_fundamental(self) -> bool {
|
fn is_fundamental(self) -> bool {
|
||||||
@@ -634,10 +638,15 @@ impl<'tcx> AdtDef<'tcx> {
|
|||||||
tcx.adt_async_destructor(self.did())
|
tcx.adt_async_destructor(self.did())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a type such that `Self: Sized` if and only if that type is `Sized`,
|
/// If this ADT is a struct, returns a type such that `Self: {Meta,Pointee,}Sized` if and only
|
||||||
/// or `None` if the type is always sized.
|
/// if that type is `{Meta,Pointee,}Sized`, or `None` if this ADT is always
|
||||||
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
/// `{Meta,Pointee,}Sized`.
|
||||||
if self.is_struct() { tcx.adt_sized_constraint(self.did()) } else { None }
|
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_abi::{FieldIdx, VariantIdx};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
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::source_map::Spanned;
|
||||||
use rustc_span::{Span, SpanDecoder, SpanEncoder};
|
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
|
/// `Decodable` can still be implemented in cases where `Decodable` is required
|
||||||
/// by a trait bound.
|
/// 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;
|
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::cache::WithDepNode;
|
||||||
use rustc_query_system::dep_graph::DepNodeIndex;
|
use rustc_query_system::dep_graph::DepNodeIndex;
|
||||||
use rustc_query_system::ich::StableHashingContext;
|
use rustc_query_system::ich::StableHashingContext;
|
||||||
|
use rustc_serialize::PointeeSized;
|
||||||
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
||||||
use rustc_session::config::CrateType;
|
use rustc_session::config::CrateType;
|
||||||
use rustc_session::cstore::{CrateStoreDyn, Untracked};
|
use rustc_session::cstore::{CrateStoreDyn, Untracked};
|
||||||
@@ -774,7 +775,9 @@ bidirectional_lang_item_map! {
|
|||||||
FutureOutput,
|
FutureOutput,
|
||||||
Iterator,
|
Iterator,
|
||||||
Metadata,
|
Metadata,
|
||||||
|
MetaSized,
|
||||||
Option,
|
Option,
|
||||||
|
PointeeSized,
|
||||||
PointeeTrait,
|
PointeeTrait,
|
||||||
Poll,
|
Poll,
|
||||||
Sized,
|
Sized,
|
||||||
@@ -1616,16 +1619,17 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
self.reserve_and_set_memory_dedup(alloc, salt)
|
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] {
|
pub fn default_traits(self) -> &'static [rustc_hir::LangItem] {
|
||||||
match self.sess.opts.unstable_opts.experimental_default_bounds {
|
if self.sess.opts.unstable_opts.experimental_default_bounds {
|
||||||
true => &[
|
&[
|
||||||
LangItem::Sized,
|
|
||||||
LangItem::DefaultTrait1,
|
LangItem::DefaultTrait1,
|
||||||
LangItem::DefaultTrait2,
|
LangItem::DefaultTrait2,
|
||||||
LangItem::DefaultTrait3,
|
LangItem::DefaultTrait3,
|
||||||
LangItem::DefaultTrait4,
|
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
|
// 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
|
// impls `Borrow` so that it can be looked up using the original
|
||||||
// (non-arena-memory-owning) types.
|
// (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 {
|
fn clone(&self) -> Self {
|
||||||
InternedInSet(self.0)
|
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 () {
|
fn into_pointer(&self) -> *const () {
|
||||||
self.0 as *const _ as *const ()
|
self.0 as *const _ as *const ()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ pub use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
|||||||
)]
|
)]
|
||||||
use rustc_type_ir::inherent;
|
use rustc_type_ir::inherent;
|
||||||
pub use rustc_type_ir::relate::VarianceDiagInfo;
|
pub use rustc_type_ir::relate::VarianceDiagInfo;
|
||||||
|
pub use rustc_type_ir::solve::SizedTraitKind;
|
||||||
pub use rustc_type_ir::*;
|
pub use rustc_type_ir::*;
|
||||||
#[allow(hidden_glob_reexports, unused_imports)]
|
#[allow(hidden_glob_reexports, unused_imports)]
|
||||||
use rustc_type_ir::{InferCtxtLike, Interner};
|
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 traits = FxIndexMap::default();
|
||||||
let mut fn_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_sized_bound = false;
|
||||||
let mut has_negative_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) {
|
for (predicate, _) in bounds.iter_instantiated_copied(tcx, args) {
|
||||||
let bound_predicate = predicate.kind();
|
let bound_predicate = predicate.kind();
|
||||||
|
|
||||||
match bound_predicate.skip_binder() {
|
match bound_predicate.skip_binder() {
|
||||||
ty::ClauseKind::Trait(pred) => {
|
ty::ClauseKind::Trait(pred) => {
|
||||||
// Don't print `+ Sized`, but rather `+ ?Sized` if absent.
|
// With `feature(sized_hierarchy)`, don't print `?Sized` as an alias for
|
||||||
if tcx.is_lang_item(pred.def_id(), LangItem::Sized) {
|
// `MetaSized`, and skip sizedness bounds to be added at the end.
|
||||||
match pred.polarity {
|
match tcx.as_lang_item(pred.def_id()) {
|
||||||
|
Some(LangItem::Sized) => match pred.polarity {
|
||||||
ty::PredicatePolarity::Positive => {
|
ty::PredicatePolarity::Positive => {
|
||||||
has_sized_bound = true;
|
has_sized_bound = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ty::PredicatePolarity::Negative => has_negative_sized_bound = true,
|
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(
|
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_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 add_sized || add_maybe_sized {
|
||||||
if !first {
|
if !first {
|
||||||
write!(self, " + ")?;
|
write!(self, " + ")?;
|
||||||
@@ -1265,6 +1281,16 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||||||
write!(self, "?")?;
|
write!(self, "?")?;
|
||||||
}
|
}
|
||||||
write!(self, "Sized")?;
|
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() {
|
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_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, extension};
|
||||||
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
||||||
use rustc_type_ir::TyKind::*;
|
use rustc_type_ir::TyKind::*;
|
||||||
|
use rustc_type_ir::solve::SizedTraitKind;
|
||||||
use rustc_type_ir::walk::TypeWalker;
|
use rustc_type_ir::walk::TypeWalker;
|
||||||
use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind, TypeVisitableExt, elaborate};
|
use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind, TypeVisitableExt, elaborate};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
@@ -1677,7 +1678,7 @@ impl<'tcx> Ty<'tcx> {
|
|||||||
let Some(pointee_ty) = self.builtin_deref(true) else {
|
let Some(pointee_ty) = self.builtin_deref(true) else {
|
||||||
bug!("Type {self:?} is not a pointer or reference type")
|
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
|
tcx.types.unit
|
||||||
} else {
|
} else {
|
||||||
match pointee_ty.ptr_metadata_ty_or_tail(tcx, |x| x) {
|
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
|
/// Returning true means the type is known to implement the sizedness trait. Returning `false`
|
||||||
/// nothing -- could be sized, might not be.
|
/// 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`
|
/// 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
|
/// 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.
|
/// 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>`.
|
/// This is why this method doesn't return `Option<bool>`.
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
#[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() {
|
match self.kind() {
|
||||||
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||||
| ty::Uint(_)
|
| ty::Uint(_)
|
||||||
@@ -1811,13 +1812,20 @@ impl<'tcx> Ty<'tcx> {
|
|||||||
| ty::Error(_)
|
| ty::Error(_)
|
||||||
| ty::Dynamic(_, _, ty::DynStar) => true,
|
| 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
|
ty::Adt(def, args) => def
|
||||||
.sized_constraint(tcx)
|
.sizedness_constraint(tcx, sizedness)
|
||||||
.is_none_or(|ty| ty.instantiate(tcx, args).is_trivially_sized(tcx)),
|
.is_none_or(|ty| ty.instantiate(tcx, args).has_trivial_sizedness(tcx, sizedness)),
|
||||||
|
|
||||||
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) | ty::Bound(..) => false,
|
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_macros::{HashStable, TyDecodable, TyEncodable, extension};
|
||||||
use rustc_session::Limit;
|
use rustc_session::Limit;
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
|
use rustc_type_ir::solve::SizedTraitKind;
|
||||||
use smallvec::{SmallVec, smallvec};
|
use smallvec::{SmallVec, smallvec};
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
@@ -1132,7 +1133,8 @@ impl<'tcx> Ty<'tcx> {
|
|||||||
/// strange rules like `<T as Foo<'static>>::Bar: Sized` that
|
/// strange rules like `<T as Foo<'static>>::Bar: Sized` that
|
||||||
/// actually carry lifetime requirements.
|
/// actually carry lifetime requirements.
|
||||||
pub fn is_sized(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool {
|
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`
|
/// Checks whether values of this type `T` implement the `Freeze`
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use std::ops::ControlFlow;
|
|||||||
use derive_where::derive_where;
|
use derive_where::derive_where;
|
||||||
use rustc_type_ir::inherent::*;
|
use rustc_type_ir::inherent::*;
|
||||||
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||||
|
use rustc_type_ir::solve::SizedTraitKind;
|
||||||
use rustc_type_ir::{
|
use rustc_type_ir::{
|
||||||
self as ty, Interner, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt as _,
|
self as ty, Interner, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt as _,
|
||||||
TypeVisitor, TypingMode, Upcast as _, elaborate,
|
TypeVisitor, TypingMode, Upcast as _, elaborate,
|
||||||
@@ -203,13 +204,15 @@ where
|
|||||||
goal: Goal<I, Self>,
|
goal: Goal<I, Self>,
|
||||||
) -> Result<Candidate<I>, NoSolution>;
|
) -> 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
|
/// These components are given by built-in rules from
|
||||||
/// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
|
/// [`structural_traits::instantiate_constituent_tys_for_sizedness_trait`].
|
||||||
fn consider_builtin_sized_candidate(
|
fn consider_builtin_sizedness_candidates(
|
||||||
ecx: &mut EvalCtxt<'_, D>,
|
ecx: &mut EvalCtxt<'_, D>,
|
||||||
goal: Goal<I, Self>,
|
goal: Goal<I, Self>,
|
||||||
|
sizedness: SizedTraitKind,
|
||||||
) -> Result<Candidate<I>, NoSolution>;
|
) -> Result<Candidate<I>, NoSolution>;
|
||||||
|
|
||||||
/// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`.
|
/// 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)
|
G::consider_trait_alias_candidate(self, goal)
|
||||||
} else {
|
} else {
|
||||||
match cx.as_lang_item(trait_def_id) {
|
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) => {
|
Some(TraitSolverLangItem::Copy | TraitSolverLangItem::Clone) => {
|
||||||
G::consider_builtin_copy_clone_candidate(self, goal)
|
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::data_structures::HashMap;
|
||||||
use rustc_type_ir::inherent::*;
|
use rustc_type_ir::inherent::*;
|
||||||
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||||
|
use rustc_type_ir::solve::SizedTraitKind;
|
||||||
use rustc_type_ir::solve::inspect::ProbeKind;
|
use rustc_type_ir::solve::inspect::ProbeKind;
|
||||||
use rustc_type_ir::{
|
use rustc_type_ir::{
|
||||||
self as ty, FallibleTypeFolder, Interner, Movability, Mutability, TypeFoldable,
|
self as ty, FallibleTypeFolder, Interner, Movability, Mutability, TypeFoldable,
|
||||||
@@ -104,8 +105,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(ecx), ret)]
|
#[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>,
|
ecx: &EvalCtxt<'_, D>,
|
||||||
|
sizedness: SizedTraitKind,
|
||||||
ty: I::Ty,
|
ty: I::Ty,
|
||||||
) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
|
) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
|
||||||
where
|
where
|
||||||
@@ -113,8 +115,9 @@ where
|
|||||||
I: Interner,
|
I: Interner,
|
||||||
{
|
{
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
// impl Sized for u*, i*, bool, f*, FnDef, FnPtr, *(const/mut) T, char, &mut? T, [T; N], dyn* Trait, !
|
// impl {Meta,}Sized for u*, i*, bool, f*, FnDef, FnPtr, *(const/mut) T, char
|
||||||
// impl Sized for Coroutine, CoroutineWitness, Closure, CoroutineClosure
|
// 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::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||||
| ty::Uint(_)
|
| ty::Uint(_)
|
||||||
| ty::Int(_)
|
| ty::Int(_)
|
||||||
@@ -135,13 +138,16 @@ where
|
|||||||
| ty::Dynamic(_, _, ty::DynStar)
|
| ty::Dynamic(_, _, ty::DynStar)
|
||||||
| ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
|
| ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
|
||||||
|
|
||||||
ty::Str
|
// impl {Meta,}Sized for str, [T], dyn Trait
|
||||||
| ty::Slice(_)
|
ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
|
||||||
| ty::Dynamic(..)
|
SizedTraitKind::Sized => Err(NoSolution),
|
||||||
| ty::Foreign(..)
|
SizedTraitKind::MetaSized => Ok(ty::Binder::dummy(vec![])),
|
||||||
| ty::Alias(..)
|
},
|
||||||
| ty::Param(_)
|
|
||||||
| ty::Placeholder(..) => Err(NoSolution),
|
// impl {} for extern type
|
||||||
|
ty::Foreign(..) => Err(NoSolution),
|
||||||
|
|
||||||
|
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => Err(NoSolution),
|
||||||
|
|
||||||
ty::Bound(..)
|
ty::Bound(..)
|
||||||
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
| 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])),
|
ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
|
||||||
|
|
||||||
// impl Sized for ()
|
// impl {Meta,}Sized for ()
|
||||||
// impl Sized for (T1, T2, .., Tn) where Tn: Sized if n >= 1
|
// 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]))),
|
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
|
// impl {Meta,}Sized for Adt<Args...>
|
||||||
// `sized_constraint(Adt)` is the deepest struct trail that can be determined
|
// where {meta,pointee,}sized_constraint(Adt)<Args...>: {Meta,}Sized
|
||||||
// by the definition of `Adt`, independent of the generic args.
|
//
|
||||||
// impl Sized for Adt<Args...> if sized_constraint(Adt) == None
|
// `{meta,pointee,}sized_constraint(Adt)` is the deepest struct trail that can be
|
||||||
// As a performance optimization, `sized_constraint(Adt)` can return `None`
|
// determined by the definition of `Adt`, independent of the generic args.
|
||||||
// if the ADTs definition implies that it is sized by for all possible 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
|
// In this case, the builtin impl will have no nested subgoals. This is a
|
||||||
// "best effort" optimization and `sized_constraint` may return `Some`, even
|
// "best effort" optimization and `{meta,pointee,}sized_constraint` may return `Some`,
|
||||||
// if the ADT is sized for all possible args.
|
// even if the ADT is {meta,pointee,}sized for all possible args.
|
||||||
ty::Adt(def, args) => {
|
ty::Adt(def, args) => {
|
||||||
if let Some(sized_crit) = def.sized_constraint(ecx.cx()) {
|
if let Some(crit) = def.sizedness_constraint(ecx.cx(), sizedness) {
|
||||||
Ok(ty::Binder::dummy(vec![sized_crit.instantiate(ecx.cx(), args)]))
|
Ok(ty::Binder::dummy(vec![crit.instantiate(ecx.cx(), args)]))
|
||||||
} else {
|
} else {
|
||||||
Ok(ty::Binder::dummy(vec![]))
|
Ok(ty::Binder::dummy(vec![]))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
||||||
use rustc_type_ir::inherent::*;
|
use rustc_type_ir::inherent::*;
|
||||||
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||||
|
use rustc_type_ir::solve::SizedTraitKind;
|
||||||
use rustc_type_ir::solve::inspect::ProbeKind;
|
use rustc_type_ir::solve::inspect::ProbeKind;
|
||||||
use rustc_type_ir::{self as ty, Interner, elaborate};
|
use rustc_type_ir::{self as ty, Interner, elaborate};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
@@ -198,11 +199,12 @@ where
|
|||||||
unreachable!("trait aliases are never const")
|
unreachable!("trait aliases are never const")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consider_builtin_sized_candidate(
|
fn consider_builtin_sizedness_candidates(
|
||||||
_ecx: &mut EvalCtxt<'_, D>,
|
_ecx: &mut EvalCtxt<'_, D>,
|
||||||
_goal: Goal<I, Self>,
|
_goal: Goal<I, Self>,
|
||||||
|
_sizedness: SizedTraitKind,
|
||||||
) -> Result<Candidate<I>, NoSolution> {
|
) -> Result<Candidate<I>, NoSolution> {
|
||||||
unreachable!("Sized is never const")
|
unreachable!("Sized/MetaSized is never const")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consider_builtin_copy_clone_candidate(
|
fn consider_builtin_copy_clone_candidate(
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ mod opaque_types;
|
|||||||
use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
||||||
use rustc_type_ir::inherent::*;
|
use rustc_type_ir::inherent::*;
|
||||||
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
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 rustc_type_ir::{self as ty, Interner, NormalizesTo, PredicateKind, Upcast as _};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
@@ -413,11 +414,12 @@ where
|
|||||||
panic!("trait aliases do not have associated types: {:?}", goal);
|
panic!("trait aliases do not have associated types: {:?}", goal);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consider_builtin_sized_candidate(
|
fn consider_builtin_sizedness_candidates(
|
||||||
_ecx: &mut EvalCtxt<'_, D>,
|
_ecx: &mut EvalCtxt<'_, D>,
|
||||||
goal: Goal<I, Self>,
|
goal: Goal<I, Self>,
|
||||||
|
_sizedness: SizedTraitKind,
|
||||||
) -> Result<Candidate<I>, NoSolution> {
|
) -> 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(
|
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::fast_reject::DeepRejectCtxt;
|
||||||
use rustc_type_ir::inherent::*;
|
use rustc_type_ir::inherent::*;
|
||||||
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||||
use rustc_type_ir::solve::CanonicalResponse;
|
use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind};
|
||||||
use rustc_type_ir::{
|
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,
|
Upcast as _, elaborate,
|
||||||
};
|
};
|
||||||
use tracing::{debug, instrument, trace};
|
use tracing::{debug, instrument, trace};
|
||||||
@@ -131,9 +131,11 @@ where
|
|||||||
assumption: I::Clause,
|
assumption: I::Clause,
|
||||||
) -> Result<(), NoSolution> {
|
) -> Result<(), NoSolution> {
|
||||||
if let Some(trait_clause) = assumption.as_trait_clause() {
|
if let Some(trait_clause) = assumption.as_trait_clause() {
|
||||||
if trait_clause.def_id() == goal.predicate.def_id()
|
if trait_clause.polarity() != goal.predicate.polarity {
|
||||||
&& 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(
|
if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
|
||||||
goal.predicate.trait_ref.args,
|
goal.predicate.trait_ref.args,
|
||||||
trait_clause.skip_binder().trait_ref.args,
|
trait_clause.skip_binder().trait_ref.args,
|
||||||
@@ -141,6 +143,17 @@ where
|
|||||||
return Ok(());
|
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)
|
Err(NoSolution)
|
||||||
@@ -154,6 +167,17 @@ where
|
|||||||
) -> QueryResult<I> {
|
) -> QueryResult<I> {
|
||||||
let trait_clause = assumption.as_trait_clause().unwrap();
|
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);
|
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)?;
|
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>,
|
ecx: &mut EvalCtxt<'_, D>,
|
||||||
goal: Goal<I, Self>,
|
goal: Goal<I, Self>,
|
||||||
|
sizedness: SizedTraitKind,
|
||||||
) -> Result<Candidate<I>, NoSolution> {
|
) -> Result<Candidate<I>, NoSolution> {
|
||||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
@@ -256,7 +281,11 @@ where
|
|||||||
ecx.probe_and_evaluate_goal_for_constituent_tys(
|
ecx.probe_and_evaluate_goal_for_constituent_tys(
|
||||||
CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
|
CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
|
||||||
goal,
|
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>
|
impl<D, I> EvalCtxt<'_, D>
|
||||||
where
|
where
|
||||||
D: SolverDelegate<Interner = I>,
|
D: SolverDelegate<Interner = I>,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![allow(rustc::internal)]
|
#![allow(rustc::internal)]
|
||||||
|
#![cfg_attr(not(bootstrap), feature(sized_hierarchy))]
|
||||||
#![cfg_attr(test, feature(test))]
|
#![cfg_attr(test, feature(test))]
|
||||||
#![doc(
|
#![doc(
|
||||||
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
||||||
@@ -27,3 +28,19 @@ mod serialize;
|
|||||||
pub mod int_overflow;
|
pub mod int_overflow;
|
||||||
pub mod leb128;
|
pub mod leb128;
|
||||||
pub mod opaque;
|
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`.
|
/// `rustc_metadata::rmeta::Lazy`.
|
||||||
/// * `TyEncodable` should be used for types that are only serialized in crate
|
/// * `TyEncodable` should be used for types that are only serialized in crate
|
||||||
/// metadata or the incremental cache. This is most types in `rustc_middle`.
|
/// 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);
|
fn encode(&self, s: &mut S);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +198,7 @@ direct_serialize_impls! {
|
|||||||
char emit_char read_char
|
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
|
where
|
||||||
T: Encodable<S>,
|
T: Encodable<S>,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![allow(rustc::usage_of_ty_tykind)]
|
#![allow(rustc::usage_of_ty_tykind)]
|
||||||
|
#![cfg_attr(not(bootstrap), feature(sized_hierarchy))]
|
||||||
#![doc(
|
#![doc(
|
||||||
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
||||||
test(attr(allow(unused_variables), deny(warnings)))
|
test(attr(allow(unused_variables), deny(warnings)))
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
|
use rustc_data_structures::PointeeSized;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::interpret::AllocId;
|
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.
|
/// 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.
|
/// The stable representation of the type implementing Stable.
|
||||||
type T;
|
type T;
|
||||||
/// Converts an object to the equivalent Stable MIR representation.
|
/// Converts an object to the equivalent Stable MIR representation.
|
||||||
|
|||||||
@@ -1355,6 +1355,7 @@ symbols! {
|
|||||||
memtag,
|
memtag,
|
||||||
message,
|
message,
|
||||||
meta,
|
meta,
|
||||||
|
meta_sized,
|
||||||
metadata_type,
|
metadata_type,
|
||||||
min_const_fn,
|
min_const_fn,
|
||||||
min_const_generics,
|
min_const_generics,
|
||||||
@@ -1613,6 +1614,7 @@ symbols! {
|
|||||||
plugin_registrar,
|
plugin_registrar,
|
||||||
plugins,
|
plugins,
|
||||||
pointee,
|
pointee,
|
||||||
|
pointee_sized,
|
||||||
pointee_trait,
|
pointee_trait,
|
||||||
pointer,
|
pointer,
|
||||||
pointer_like,
|
pointer_like,
|
||||||
@@ -2016,6 +2018,7 @@ symbols! {
|
|||||||
size_of,
|
size_of,
|
||||||
size_of_val,
|
size_of_val,
|
||||||
sized,
|
sized,
|
||||||
|
sized_hierarchy,
|
||||||
skip,
|
skip,
|
||||||
slice,
|
slice,
|
||||||
slice_from_raw_parts,
|
slice_from_raw_parts,
|
||||||
|
|||||||
@@ -199,7 +199,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||||||
// avoid inundating the user with unnecessary errors, but we now
|
// avoid inundating the user with unnecessary errors, but we now
|
||||||
// check upstream for type errors and don't add the obligations to
|
// check upstream for type errors and don't add the obligations to
|
||||||
// begin with in those cases.
|
// 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() {
|
match self.tainted_by_errors() {
|
||||||
None => {
|
None => {
|
||||||
let err = self.emit_inference_failure_err(
|
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_errors::{Applicability, Diag, E0038, E0276, MultiSpan, struct_span_code_err};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::intravisit::Visitor;
|
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::solve::Goal;
|
||||||
use rustc_infer::traits::{
|
use rustc_infer::traits::{
|
||||||
DynCompatibilityViolation, Obligation, ObligationCause, ObligationCauseCode,
|
DynCompatibilityViolation, Obligation, ObligationCause, ObligationCauseCode,
|
||||||
@@ -160,17 +160,24 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Ensure `T: Sized` and `T: WF` obligations come last. This lets us display diagnostics
|
// Ensure `T: Sized`, `T: MetaSized`, `T: PointeeSized` and `T: WF` obligations come last.
|
||||||
// with more relevant type information and hide redundant E0282 errors.
|
// This lets us display diagnostics with more relevant type information and hide redundant
|
||||||
errors.sort_by_key(|e| match e.obligation.predicate.kind().skip_binder() {
|
// E0282 errors.
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
|
errors.sort_by_key(|e| {
|
||||||
if self.tcx.is_lang_item(pred.def_id(), LangItem::Sized) =>
|
let maybe_sizedness_did = match e.obligation.predicate.kind().skip_binder() {
|
||||||
{
|
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => Some(pred.def_id()),
|
||||||
1
|
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,
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Coerce(_) => 2,
|
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => 3,
|
|
||||||
_ => 0,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
for (index, error) in errors.iter().enumerate() {
|
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 trait_ref = tcx.impl_trait_ref(impl_def_id)?.instantiate_identity();
|
||||||
let mut w = "impl".to_owned();
|
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.
|
let mut types_with_sizedness_bounds = FxIndexMap::<_, SizednessFound>::default();
|
||||||
// Needs to support ?Move and ?DynSized when they are implemented.
|
|
||||||
let mut types_without_default_bounds = FxIndexSet::default();
|
let args = ty::GenericArgs::identity_for_item(tcx, impl_def_id);
|
||||||
let sized_trait = tcx.lang_items().sized_trait();
|
|
||||||
|
|
||||||
let arg_names = args.iter().map(|k| k.to_string()).filter(|k| k != "'_").collect::<Vec<_>>();
|
let arg_names = args.iter().map(|k| k.to_string()).filter(|k| k != "'_").collect::<Vec<_>>();
|
||||||
if !arg_names.is_empty() {
|
if !arg_names.is_empty() {
|
||||||
types_without_default_bounds.extend(args.types());
|
|
||||||
w.push('<');
|
w.push('<');
|
||||||
w.push_str(&arg_names.join(", "));
|
w.push_str(&arg_names.join(", "));
|
||||||
w.push('>');
|
w.push('>');
|
||||||
|
|
||||||
|
for ty in args.types() {
|
||||||
|
// `PointeeSized` params might have no predicates.
|
||||||
|
types_with_sizedness_bounds.insert(ty, SizednessFound::default());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(
|
write!(
|
||||||
@@ -351,24 +365,47 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.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 predicates = tcx.predicates_of(impl_def_id).predicates;
|
||||||
let mut pretty_predicates =
|
let mut pretty_predicates = Vec::with_capacity(predicates.len());
|
||||||
Vec::with_capacity(predicates.len() + types_without_default_bounds.len());
|
|
||||||
|
let sized_trait = tcx.lang_items().sized_trait();
|
||||||
|
let meta_sized_trait = tcx.lang_items().meta_sized_trait();
|
||||||
|
|
||||||
for (p, _) in predicates {
|
for (p, _) in predicates {
|
||||||
if let Some(poly_trait_ref) = p.as_trait_clause() {
|
// Accumulate the sizedness bounds for each self ty.
|
||||||
if Some(poly_trait_ref.def_id()) == sized_trait {
|
if let Some(trait_clause) = p.as_trait_clause() {
|
||||||
// FIXME(#120456) - is `swap_remove` correct?
|
let self_ty = trait_clause.self_ty().skip_binder();
|
||||||
types_without_default_bounds.swap_remove(&poly_trait_ref.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;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pretty_predicates.push(p.to_string());
|
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() {
|
if !pretty_predicates.is_empty() {
|
||||||
write!(w, "\n where {}", pretty_predicates.join(", ")).unwrap();
|
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 };
|
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.
|
// 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
|
// defaults to assuming that things are *not* sized, whereas we want to
|
||||||
// fall back to assuming that things may be sized.
|
// fall back to assuming that things may be sized.
|
||||||
match impl_type.kind() {
|
match impl_type.kind() {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use rustc_infer::traits::solve::Goal;
|
|||||||
use rustc_middle::traits::query::NoSolution;
|
use rustc_middle::traits::query::NoSolution;
|
||||||
use rustc_middle::traits::solve::Certainty;
|
use rustc_middle::traits::solve::Certainty;
|
||||||
use rustc_middle::ty::{
|
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};
|
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
|
||||||
|
|
||||||
@@ -79,7 +79,14 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
|||||||
Some(LangItem::Sized)
|
Some(LangItem::Sized)
|
||||||
if self
|
if self
|
||||||
.resolve_vars_if_possible(trait_pred.self_ty().skip_binder())
|
.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);
|
return Some(Certainty::Yes);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -462,6 +462,7 @@ fn impl_intersection_has_negative_obligation(
|
|||||||
let param_env = infcx.resolve_vars_if_possible(param_env);
|
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))
|
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))
|
.any(|(clause, _)| try_prove_negated_where_clause(infcx, clause, param_env))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,15 +7,15 @@
|
|||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use rustc_errors::FatalError;
|
use rustc_errors::FatalError;
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
use rustc_hir::{self as hir, LangItem};
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||||
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
|
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
|
||||||
elaborate,
|
elaborate,
|
||||||
};
|
};
|
||||||
use rustc_span::Span;
|
use rustc_span::{DUMMY_SP, Span};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use tracing::{debug, instrument};
|
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
|
/// 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.
|
/// 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
|
/// 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:
|
/// Written as a chalk-style query:
|
||||||
/// ```ignore (not-rust)
|
/// ```ignore (not-rust)
|
||||||
/// forall (U: Trait + ?Sized) {
|
/// forall (U: Trait + MetaSized) {
|
||||||
/// if (Self: Unsize<U>) {
|
/// if (Self: Unsize<U>) {
|
||||||
/// Receiver: DispatchFromDyn<Receiver[Self => U]>
|
/// Receiver: DispatchFromDyn<Receiver[Self => U]>
|
||||||
/// }
|
/// }
|
||||||
@@ -567,9 +567,10 @@ fn receiver_is_dispatchable<'tcx>(
|
|||||||
) -> bool {
|
) -> bool {
|
||||||
debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
|
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)) =
|
||||||
let (Some(unsize_did), Some(dispatch_from_dyn_did)) = traits else {
|
(tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait())
|
||||||
debug!("receiver_is_dispatchable: Missing Unsize or DispatchFromDyn traits");
|
else {
|
||||||
|
debug!("receiver_is_dispatchable: Missing `Unsize` or `DispatchFromDyn` traits");
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -583,7 +584,7 @@ fn receiver_is_dispatchable<'tcx>(
|
|||||||
receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
|
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
|
// 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 = {
|
let param_env = {
|
||||||
// N.B. We generally want to emulate the construction of the `unnormalized_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
|
// 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);
|
let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args);
|
||||||
predicates.push(trait_predicate.upcast(tcx));
|
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(
|
normalize_param_env_or_error(
|
||||||
tcx,
|
tcx,
|
||||||
ty::ParamEnv::new(tcx.mk_clauses(&predicates)),
|
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_hir::{self as hir, CoroutineDesugaring, CoroutineKind};
|
||||||
use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
|
use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
|
||||||
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
|
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 rustc_middle::{bug, span_bug};
|
||||||
use tracing::{debug, instrument, trace};
|
use tracing::{debug, instrument, trace};
|
||||||
|
|
||||||
@@ -87,7 +87,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
candidates.vec.push(BuiltinCandidate { has_nested: false });
|
candidates.vec.push(BuiltinCandidate { has_nested: false });
|
||||||
}
|
}
|
||||||
Some(LangItem::Sized) => {
|
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) => {
|
Some(LangItem::Unsize) => {
|
||||||
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
|
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
|
||||||
@@ -201,6 +215,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
selcx.infcx.probe(|_| {
|
selcx.infcx.probe(|_| {
|
||||||
|
let bound = util::lazily_elaborate_sizedness_candidate(
|
||||||
|
selcx.infcx,
|
||||||
|
obligation,
|
||||||
|
bound,
|
||||||
|
);
|
||||||
|
|
||||||
// We checked the polarity already
|
// We checked the polarity already
|
||||||
match selcx.match_normalize_trait_ref(
|
match selcx.match_normalize_trait_ref(
|
||||||
obligation,
|
obligation,
|
||||||
@@ -245,14 +265,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
.caller_bounds()
|
.caller_bounds()
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|p| p.as_trait_clause())
|
.filter_map(|p| p.as_trait_clause())
|
||||||
// Micro-optimization: filter out predicates relating to different traits.
|
// Micro-optimization: filter out predicates with different polarities.
|
||||||
.filter(|p| p.def_id() == stack.obligation.predicate.def_id())
|
|
||||||
.filter(|p| p.polarity() == stack.obligation.predicate.polarity());
|
.filter(|p| p.polarity() == stack.obligation.predicate.polarity());
|
||||||
|
|
||||||
let drcx = DeepRejectCtxt::relate_rigid_rigid(self.tcx());
|
let drcx = DeepRejectCtxt::relate_rigid_rigid(self.tcx());
|
||||||
let obligation_args = stack.obligation.predicate.skip_binder().trait_ref.args;
|
let obligation_args = stack.obligation.predicate.skip_binder().trait_ref.args;
|
||||||
// Keep only those bounds which may apply, and propagate overflow if it occurs.
|
// Keep only those bounds which may apply, and propagate overflow if it occurs.
|
||||||
for bound in bounds {
|
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);
|
let bound_trait_ref = bound.map_bound(|t| t.trait_ref);
|
||||||
if !drcx.args_may_unify(obligation_args, bound_trait_ref.skip_binder().args) {
|
if !drcx.args_may_unify(obligation_args, bound_trait_ref.skip_binder().args) {
|
||||||
continue;
|
continue;
|
||||||
@@ -1086,15 +1113,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assembles the trait which are built-in to the language itself:
|
/// Assembles the `Sized` and `MetaSized` traits which are built-in to the language itself.
|
||||||
/// `Copy`, `Clone` and `Sized`.
|
|
||||||
#[instrument(level = "debug", skip(self, candidates))]
|
#[instrument(level = "debug", skip(self, candidates))]
|
||||||
fn assemble_builtin_sized_candidate(
|
fn assemble_builtin_sized_candidate(
|
||||||
&mut self,
|
&mut self,
|
||||||
obligation: &PolyTraitObligation<'tcx>,
|
obligation: &PolyTraitObligation<'tcx>,
|
||||||
candidates: &mut SelectionCandidateSet<'tcx>,
|
candidates: &mut SelectionCandidateSet<'tcx>,
|
||||||
|
sizedness: SizedTraitKind,
|
||||||
) {
|
) {
|
||||||
match self.sized_conditions(obligation) {
|
match self.sizedness_conditions(obligation, sizedness) {
|
||||||
BuiltinImplConditions::Where(nested) => {
|
BuiltinImplConditions::Where(nested) => {
|
||||||
candidates
|
candidates
|
||||||
.vec
|
.vec
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ use rustc_hir::lang_items::LangItem;
|
|||||||
use rustc_infer::infer::{DefineOpaqueTypes, HigherRankedType, InferOk};
|
use rustc_infer::infer::{DefineOpaqueTypes, HigherRankedType, InferOk};
|
||||||
use rustc_infer::traits::ObligationCauseCode;
|
use rustc_infer::traits::ObligationCauseCode;
|
||||||
use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData};
|
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_middle::{bug, span_bug};
|
||||||
use rustc_span::def_id::DefId;
|
use rustc_span::def_id::DefId;
|
||||||
use thin_vec::thin_vec;
|
use thin_vec::thin_vec;
|
||||||
@@ -164,10 +166,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
)
|
)
|
||||||
.break_value()
|
.break_value()
|
||||||
.expect("expected to index into clause that exists");
|
.expect("expected to index into clause that exists");
|
||||||
let candidate = candidate_predicate
|
let candidate_predicate = candidate_predicate
|
||||||
.as_trait_clause()
|
.as_trait_clause()
|
||||||
.expect("projection candidate is not a trait predicate")
|
.expect("projection candidate is not a trait predicate");
|
||||||
.map_bound(|t| t.trait_ref);
|
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(
|
let candidate = self.infcx.instantiate_binder_with_fresh_vars(
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
@@ -224,6 +229,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
) -> PredicateObligations<'tcx> {
|
) -> PredicateObligations<'tcx> {
|
||||||
debug!(?obligation, ?param, "confirm_param_candidate");
|
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
|
// During evaluation, we already checked that this
|
||||||
// where-clause trait-ref could be unified with the obligation
|
// where-clause trait-ref could be unified with the obligation
|
||||||
// trait-ref. Repeat that unification now without any
|
// trait-ref. Repeat that unification now without any
|
||||||
@@ -251,7 +263,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
let obligations = if has_nested {
|
let obligations = if has_nested {
|
||||||
let trait_def = obligation.predicate.def_id();
|
let trait_def = obligation.predicate.def_id();
|
||||||
let conditions = match tcx.as_lang_item(trait_def) {
|
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::Copy | LangItem::Clone) => self.copy_clone_conditions(obligation),
|
||||||
Some(LangItem::FusedIterator) => self.fused_iterator_conditions(obligation),
|
Some(LangItem::FusedIterator) => self.fused_iterator_conditions(obligation),
|
||||||
other => bug!("unexpected builtin trait {trait_def:?} ({other:?})"),
|
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::error::TypeErrorToStringExt;
|
||||||
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
|
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable,
|
self, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate, SizedTraitKind, Ty, TyCtxt,
|
||||||
TypeVisitableExt, TypingMode, Upcast, elaborate,
|
TypeFoldable, TypeVisitableExt, TypingMode, Upcast, elaborate,
|
||||||
};
|
};
|
||||||
use rustc_span::{Symbol, sym};
|
use rustc_span::{Symbol, sym};
|
||||||
use tracing::{debug, instrument, trace};
|
use tracing::{debug, instrument, trace};
|
||||||
@@ -2094,9 +2094,10 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> SelectionContext<'_, 'tcx> {
|
impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||||
fn sized_conditions(
|
fn sizedness_conditions(
|
||||||
&mut self,
|
&mut self,
|
||||||
obligation: &PolyTraitObligation<'tcx>,
|
obligation: &PolyTraitObligation<'tcx>,
|
||||||
|
sizedness: SizedTraitKind,
|
||||||
) -> BuiltinImplConditions<'tcx> {
|
) -> BuiltinImplConditions<'tcx> {
|
||||||
use self::BuiltinImplConditions::{Ambiguous, None, Where};
|
use self::BuiltinImplConditions::{Ambiguous, None, Where};
|
||||||
|
|
||||||
@@ -2126,7 +2127,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||||||
Where(ty::Binder::dummy(Vec::new()))
|
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(
|
ty::Tuple(tys) => Where(
|
||||||
obligation.predicate.rebind(tys.last().map_or_else(Vec::new, |&last| vec![last])),
|
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::Pat(ty, _) => Where(obligation.predicate.rebind(vec![*ty])),
|
||||||
|
|
||||||
ty::Adt(def, args) => {
|
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
|
// (*) binder moved here
|
||||||
Where(
|
Where(obligation.predicate.rebind(vec![crit.instantiate(self.tcx(), args)]))
|
||||||
obligation.predicate.rebind(vec![sized_crit.instantiate(self.tcx(), args)]),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Where(ty::Binder::dummy(Vec::new()))
|
Where(ty::Binder::dummy(Vec::new()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,13 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
|||||||
use rustc_hir::LangItem;
|
use rustc_hir::LangItem;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::infer::InferCtxt;
|
use rustc_infer::infer::InferCtxt;
|
||||||
|
use rustc_infer::traits::PolyTraitObligation;
|
||||||
pub use rustc_infer::traits::util::*;
|
pub use rustc_infer::traits::util::*;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
|
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
|
||||||
use rustc_middle::ty::{
|
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;
|
pub use rustc_next_trait_solver::placeholder::BoundVarReplacer;
|
||||||
use rustc_span::Span;
|
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 {
|
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%
|
// Proving `Sized`/`MetaSized`, very often on "obviously sized" types like
|
||||||
// percentage of the predicates we have to prove. No need to canonicalize and all that for
|
// `&T`, accounts for about 60% percentage of the predicates we have to prove. No need to
|
||||||
// such cases.
|
// canonicalize and all that for such cases.
|
||||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) =
|
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) =
|
||||||
predicate.kind().skip_binder()
|
predicate.kind().skip_binder()
|
||||||
{
|
{
|
||||||
if tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized)
|
let sizedness = match tcx.as_lang_item(trait_ref.def_id()) {
|
||||||
&& trait_ref.self_ty().is_trivially_sized(tcx)
|
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");
|
debug!("fast path -- trivial sizedness");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -378,3 +385,39 @@ pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
|
|||||||
|
|
||||||
false
|
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,
|
def_id: DefId,
|
||||||
args: GenericArgsRef<'tcx>,
|
args: GenericArgsRef<'tcx>,
|
||||||
) -> PredicateObligations<'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 predicates = self.tcx().predicates_of(def_id);
|
||||||
let mut origins = vec![def_id; predicates.predicates.len()];
|
let mut origins = vec![def_id; predicates.predicates.len()];
|
||||||
let mut head = predicates;
|
let mut head = predicates;
|
||||||
|
|||||||
@@ -1,23 +1,29 @@
|
|||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::LangItem;
|
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_index::bit_set::DenseBitSet;
|
use rustc_index::bit_set::DenseBitSet;
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::{
|
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::DUMMY_SP;
|
||||||
use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
|
use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits;
|
||||||
use tracing::instrument;
|
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)]
|
#[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() {
|
match ty.kind() {
|
||||||
// these are always sized
|
// Always `Sized` or `MetaSized`
|
||||||
ty::Bool
|
ty::Bool
|
||||||
| ty::Char
|
| ty::Char
|
||||||
| ty::Int(..)
|
| ty::Int(..)
|
||||||
@@ -35,31 +41,40 @@ fn sized_constraint_for_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'
|
|||||||
| ty::Never
|
| ty::Never
|
||||||
| ty::Dynamic(_, _, ty::DynStar) => None,
|
| ty::Dynamic(_, _, ty::DynStar) => None,
|
||||||
|
|
||||||
// these are never sized
|
ty::Str | ty::Slice(..) | ty::Dynamic(_, _, ty::Dyn) => match sizedness {
|
||||||
ty::Str | ty::Slice(..) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => Some(ty),
|
// Never `Sized`
|
||||||
|
SizedTraitKind::Sized => Some(ty),
|
||||||
|
// Always `MetaSized`
|
||||||
|
SizedTraitKind::MetaSized => None,
|
||||||
|
},
|
||||||
|
|
||||||
ty::Pat(ty, _) => sized_constraint_for_ty(tcx, *ty),
|
// Maybe `Sized` or `MetaSized`
|
||||||
|
|
||||||
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.
|
|
||||||
ty::Param(..) | ty::Alias(..) | ty::Error(_) => Some(ty),
|
ty::Param(..) | ty::Alias(..) | ty::Error(_) => Some(ty),
|
||||||
|
|
||||||
// We cannot instantiate the binder, so just return the *original* type back,
|
// 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 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`.
|
// but don't actually use the result from `sized_constraint_for_ty`.
|
||||||
ty::UnsafeBinder(inner_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(..) => {
|
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:
|
/// For `Sized`, there are only a few options for the types in the constraint:
|
||||||
/// - an obviously-unsized type
|
/// - 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
|
/// - a type parameter or projection whose sizedness can't be known
|
||||||
#[instrument(level = "debug", skip(tcx), ret)]
|
#[instrument(level = "debug", skip(tcx), ret)]
|
||||||
fn adt_sized_constraint<'tcx>(
|
fn adt_sizedness_constraint<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
def_id: DefId,
|
(def_id, sizedness): (DefId, SizedTraitKind),
|
||||||
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
||||||
if let Some(def_id) = def_id.as_local() {
|
if let Some(def_id) = def_id.as_local() {
|
||||||
if let ty::Representability::Infinite(_) = tcx.representability(def_id) {
|
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);
|
let def = tcx.adt_def(def_id);
|
||||||
|
|
||||||
if !def.is_struct() {
|
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_def = def.non_enum_variant().tail_opt()?;
|
||||||
let tail_ty = tcx.type_of(tail_def.did).instantiate_identity();
|
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.
|
// 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;
|
let predicates = tcx.predicates_of(def.did()).predicates;
|
||||||
if predicates.iter().any(|(p, _)| {
|
if predicates.iter().any(|(p, _)| {
|
||||||
p.as_trait_clause().is_some_and(|trait_pred| {
|
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
|
&& 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) {
|
pub(crate) fn provide(providers: &mut Providers) {
|
||||||
*providers = Providers {
|
*providers = Providers {
|
||||||
asyncness,
|
asyncness,
|
||||||
adt_sized_constraint,
|
adt_sizedness_constraint,
|
||||||
param_env,
|
param_env,
|
||||||
typing_env_normalized_for_post_analysis,
|
typing_env_normalized_for_post_analysis,
|
||||||
defaultness,
|
defaultness,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use smallvec::smallvec;
|
|||||||
|
|
||||||
use crate::data_structures::HashSet;
|
use crate::data_structures::HashSet;
|
||||||
use crate::inherent::*;
|
use crate::inherent::*;
|
||||||
|
use crate::lang_items::TraitSolverLangItem;
|
||||||
use crate::outlives::{Component, push_outlives_components};
|
use crate::outlives::{Component, push_outlives_components};
|
||||||
use crate::{self as ty, Interner, Upcast as _};
|
use crate::{self as ty, Interner, Upcast as _};
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ pub struct Elaborator<I: Interner, O> {
|
|||||||
stack: Vec<O>,
|
stack: Vec<O>,
|
||||||
visited: HashSet<ty::Binder<I, ty::PredicateKind<I>>>,
|
visited: HashSet<ty::Binder<I, ty::PredicateKind<I>>>,
|
||||||
mode: Filter,
|
mode: Filter,
|
||||||
|
elaborate_sized: ElaborateSized,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Filter {
|
enum Filter {
|
||||||
@@ -25,6 +27,12 @@ enum Filter {
|
|||||||
OnlySelf,
|
OnlySelf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq)]
|
||||||
|
enum ElaborateSized {
|
||||||
|
Yes,
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
||||||
/// Describes how to elaborate an obligation into a sub-obligation.
|
/// Describes how to elaborate an obligation into a sub-obligation.
|
||||||
pub trait Elaboratable<I: Interner> {
|
pub trait Elaboratable<I: Interner> {
|
||||||
fn predicate(&self) -> I::Predicate;
|
fn predicate(&self) -> I::Predicate;
|
||||||
@@ -77,13 +85,19 @@ pub fn elaborate<I: Interner, O: Elaboratable<I>>(
|
|||||||
cx: I,
|
cx: I,
|
||||||
obligations: impl IntoIterator<Item = O>,
|
obligations: impl IntoIterator<Item = O>,
|
||||||
) -> Elaborator<I, O> {
|
) -> Elaborator<I, O> {
|
||||||
let mut elaborator =
|
let mut elaborator = Elaborator {
|
||||||
Elaborator { cx, stack: Vec::new(), visited: HashSet::default(), mode: Filter::All };
|
cx,
|
||||||
|
stack: Vec::new(),
|
||||||
|
visited: HashSet::default(),
|
||||||
|
mode: Filter::All,
|
||||||
|
elaborate_sized: ElaborateSized::No,
|
||||||
|
};
|
||||||
elaborator.extend_deduped(obligations);
|
elaborator.extend_deduped(obligations);
|
||||||
elaborator
|
elaborator
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
|
impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
|
||||||
|
/// Adds `obligations` to the stack.
|
||||||
fn extend_deduped(&mut self, obligations: impl IntoIterator<Item = O>) {
|
fn extend_deduped(&mut self, obligations: impl IntoIterator<Item = O>) {
|
||||||
// Only keep those bounds that we haven't already seen.
|
// Only keep those bounds that we haven't already seen.
|
||||||
// This is necessary to prevent infinite recursion in some
|
// This is necessary to prevent infinite recursion in some
|
||||||
@@ -103,6 +117,13 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
|
|||||||
self
|
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) {
|
fn elaborate(&mut self, elaboratable: &O) {
|
||||||
let cx = self.cx;
|
let cx = self.cx;
|
||||||
|
|
||||||
@@ -111,6 +132,19 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
|
|||||||
return;
|
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();
|
let bound_clause = clause.kind();
|
||||||
match bound_clause.skip_binder() {
|
match bound_clause.skip_binder() {
|
||||||
ty::ClauseKind::Trait(data) => {
|
ty::ClauseKind::Trait(data) => {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use rustc_ast_ir::Mutability;
|
|||||||
use crate::elaborate::Elaboratable;
|
use crate::elaborate::Elaboratable;
|
||||||
use crate::fold::{TypeFoldable, TypeSuperFoldable};
|
use crate::fold::{TypeFoldable, TypeSuperFoldable};
|
||||||
use crate::relate::Relate;
|
use crate::relate::Relate;
|
||||||
use crate::solve::AdtDestructorKind;
|
use crate::solve::{AdtDestructorKind, SizedTraitKind};
|
||||||
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
|
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
|
||||||
use crate::{self as ty, CollectAndApply, Interner, UpcastFrom};
|
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`.
|
// FIXME: perhaps use `all_fields` and expose `FieldDef`.
|
||||||
fn all_field_tys(self, interner: I) -> ty::EarlyBinder<I, impl IntoIterator<Item = I::Ty>>;
|
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;
|
fn is_fundamental(self) -> bool;
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ pub enum TraitSolverLangItem {
|
|||||||
FutureOutput,
|
FutureOutput,
|
||||||
Iterator,
|
Iterator,
|
||||||
Metadata,
|
Metadata,
|
||||||
|
MetaSized,
|
||||||
Option,
|
Option,
|
||||||
|
PointeeSized,
|
||||||
PointeeTrait,
|
PointeeTrait,
|
||||||
Poll,
|
Poll,
|
||||||
Sized,
|
Sized,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use derive_where::derive_where;
|
|||||||
use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
|
use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
|
||||||
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
||||||
|
|
||||||
|
use crate::lang_items::TraitSolverLangItem;
|
||||||
use crate::search_graph::PathKind;
|
use crate::search_graph::PathKind;
|
||||||
use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Upcast};
|
use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Upcast};
|
||||||
|
|
||||||
@@ -366,3 +367,24 @@ pub enum AdtDestructorKind {
|
|||||||
NotConst,
|
NotConst,
|
||||||
Const,
|
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")]
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
|
use crate::marker::PointeeSized;
|
||||||
|
|
||||||
mod uninit;
|
mod uninit;
|
||||||
|
|
||||||
/// A common trait that allows explicit creation of a duplicate value.
|
/// 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",
|
reason = "deriving hack, should not be public",
|
||||||
issue = "none"
|
issue = "none"
|
||||||
)]
|
)]
|
||||||
pub struct AssertParamIsClone<T: Clone + ?Sized> {
|
pub struct AssertParamIsClone<T: Clone + PointeeSized> {
|
||||||
_field: crate::marker::PhantomData<T>,
|
_field: crate::marker::PhantomData<T>,
|
||||||
}
|
}
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@@ -293,7 +295,7 @@ pub struct AssertParamIsClone<T: Clone + ?Sized> {
|
|||||||
reason = "deriving hack, should not be public",
|
reason = "deriving hack, should not be public",
|
||||||
issue = "none"
|
issue = "none"
|
||||||
)]
|
)]
|
||||||
pub struct AssertParamIsCopy<T: Copy + ?Sized> {
|
pub struct AssertParamIsCopy<T: Copy + PointeeSized> {
|
||||||
_field: crate::marker::PhantomData<T>,
|
_field: crate::marker::PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,6 +532,8 @@ unsafe impl CloneToUninit for crate::bstr::ByteStr {
|
|||||||
/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
|
/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
|
||||||
/// in `rustc_trait_selection`.
|
/// in `rustc_trait_selection`.
|
||||||
mod impls {
|
mod impls {
|
||||||
|
use crate::marker::PointeeSized;
|
||||||
|
|
||||||
macro_rules! impl_clone {
|
macro_rules! impl_clone {
|
||||||
($($t:ty)*) => {
|
($($t:ty)*) => {
|
||||||
$(
|
$(
|
||||||
@@ -560,7 +564,7 @@ mod impls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> Clone for *const T {
|
impl<T: PointeeSized> Clone for *const T {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
*self
|
*self
|
||||||
@@ -568,7 +572,7 @@ mod impls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> Clone for *mut T {
|
impl<T: PointeeSized> Clone for *mut T {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
*self
|
*self
|
||||||
@@ -577,7 +581,7 @@ mod impls {
|
|||||||
|
|
||||||
/// Shared references can be cloned, but mutable references *cannot*!
|
/// Shared references can be cloned, but mutable references *cannot*!
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> Clone for &T {
|
impl<T: PointeeSized> Clone for &T {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[rustc_diagnostic_item = "noop_method_clone"]
|
#[rustc_diagnostic_item = "noop_method_clone"]
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
@@ -587,5 +591,5 @@ mod impls {
|
|||||||
|
|
||||||
/// Shared references can be cloned, but mutable references *cannot*!
|
/// Shared references can be cloned, but mutable references *cannot*!
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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;
|
pub(crate) use bytewise::BytewiseEq;
|
||||||
|
|
||||||
use self::Ordering::*;
|
use self::Ordering::*;
|
||||||
|
use crate::marker::PointeeSized;
|
||||||
use crate::ops::ControlFlow;
|
use crate::ops::ControlFlow;
|
||||||
|
|
||||||
/// Trait for comparisons using the equality operator.
|
/// Trait for comparisons using the equality operator.
|
||||||
@@ -246,7 +247,7 @@ use crate::ops::ControlFlow;
|
|||||||
append_const_msg
|
append_const_msg
|
||||||
)]
|
)]
|
||||||
#[rustc_diagnostic_item = "PartialEq"]
|
#[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 `==`.
|
/// Tests for `self` and `other` values to be equal, and is used by `==`.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
@@ -332,7 +333,7 @@ pub macro PartialEq($item:item) {
|
|||||||
#[doc(alias = "!=")]
|
#[doc(alias = "!=")]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_diagnostic_item = "Eq"]
|
#[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
|
// 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
|
// type implements `Eq` itself. The current deriving infrastructure means doing this assertion
|
||||||
// without using a method on this trait is nearly impossible.
|
// without using a method on this trait is nearly impossible.
|
||||||
@@ -361,7 +362,7 @@ pub macro Eq($item:item) {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
#[unstable(feature = "derive_eq", reason = "deriving hack, should not be public", issue = "none")]
|
#[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>,
|
_field: crate::marker::PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -954,7 +955,7 @@ impl<T: Clone> Clone for Reverse<T> {
|
|||||||
#[doc(alias = ">=")]
|
#[doc(alias = ">=")]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_diagnostic_item = "Ord"]
|
#[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`.
|
/// This method returns an [`Ordering`] between `self` and `other`.
|
||||||
///
|
///
|
||||||
/// By convention, `self.cmp(&other)` returns the ordering matching the expression
|
/// By convention, `self.cmp(&other)` returns the ordering matching the expression
|
||||||
@@ -1337,7 +1338,8 @@ pub macro Ord($item:item) {
|
|||||||
append_const_msg
|
append_const_msg
|
||||||
)]
|
)]
|
||||||
#[rustc_diagnostic_item = "PartialOrd"]
|
#[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.
|
/// This method returns an ordering between `self` and `other` values if one exists.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # 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,
|
lhs: &T,
|
||||||
rhs: &U,
|
rhs: &U,
|
||||||
p: impl FnOnce(Ordering) -> bool,
|
p: impl FnOnce(Ordering) -> bool,
|
||||||
@@ -1803,6 +1805,7 @@ where
|
|||||||
mod impls {
|
mod impls {
|
||||||
use crate::cmp::Ordering::{self, Equal, Greater, Less};
|
use crate::cmp::Ordering::{self, Equal, Greater, Less};
|
||||||
use crate::hint::unreachable_unchecked;
|
use crate::hint::unreachable_unchecked;
|
||||||
|
use crate::marker::PointeeSized;
|
||||||
use crate::ops::ControlFlow::{self, Break, Continue};
|
use crate::ops::ControlFlow::{self, Break, Continue};
|
||||||
|
|
||||||
macro_rules! partial_eq_impl {
|
macro_rules! partial_eq_impl {
|
||||||
@@ -2015,7 +2018,7 @@ mod impls {
|
|||||||
// & pointers
|
// & pointers
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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
|
where
|
||||||
A: PartialEq<B>,
|
A: PartialEq<B>,
|
||||||
{
|
{
|
||||||
@@ -2029,7 +2032,7 @@ mod impls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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
|
where
|
||||||
A: PartialOrd<B>,
|
A: PartialOrd<B>,
|
||||||
{
|
{
|
||||||
@@ -2071,7 +2074,7 @@ mod impls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<A: ?Sized> Ord for &A
|
impl<A: PointeeSized> Ord for &A
|
||||||
where
|
where
|
||||||
A: Ord,
|
A: Ord,
|
||||||
{
|
{
|
||||||
@@ -2081,12 +2084,12 @@ mod impls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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
|
// &mut pointers
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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
|
where
|
||||||
A: PartialEq<B>,
|
A: PartialEq<B>,
|
||||||
{
|
{
|
||||||
@@ -2100,7 +2103,7 @@ mod impls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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
|
where
|
||||||
A: PartialOrd<B>,
|
A: PartialOrd<B>,
|
||||||
{
|
{
|
||||||
@@ -2142,7 +2145,7 @@ mod impls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<A: ?Sized> Ord for &mut A
|
impl<A: PointeeSized> Ord for &mut A
|
||||||
where
|
where
|
||||||
A: Ord,
|
A: Ord,
|
||||||
{
|
{
|
||||||
@@ -2152,10 +2155,10 @@ mod impls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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")]
|
#[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
|
where
|
||||||
A: PartialEq<B>,
|
A: PartialEq<B>,
|
||||||
{
|
{
|
||||||
@@ -2170,7 +2173,7 @@ mod impls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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
|
where
|
||||||
A: PartialEq<B>,
|
A: PartialEq<B>,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::hash::{Hash, Hasher};
|
use crate::hash::{Hash, Hasher};
|
||||||
|
use crate::marker::PointeeSized;
|
||||||
|
|
||||||
mod num;
|
mod num;
|
||||||
|
|
||||||
@@ -215,7 +216,7 @@ pub const fn identity<T>(x: T) -> T {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_diagnostic_item = "AsRef"]
|
#[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.
|
/// Converts this type into a shared reference of the (usually inferred) input type.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn as_ref(&self) -> &T;
|
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).
|
/// `&mut Vec<u8>`, for example, is the better choice (callers need to pass the correct type then).
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_diagnostic_item = "AsMut"]
|
#[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.
|
/// Converts this type into a mutable reference of the (usually inferred) input type.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn as_mut(&mut self) -> &mut T;
|
fn as_mut(&mut self) -> &mut T;
|
||||||
@@ -701,7 +702,7 @@ pub trait TryFrom<T>: Sized {
|
|||||||
|
|
||||||
// As lifts over &
|
// As lifts over &
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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
|
where
|
||||||
T: AsRef<U>,
|
T: AsRef<U>,
|
||||||
{
|
{
|
||||||
@@ -713,7 +714,7 @@ where
|
|||||||
|
|
||||||
// As lifts over &mut
|
// As lifts over &mut
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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
|
where
|
||||||
T: AsRef<U>,
|
T: AsRef<U>,
|
||||||
{
|
{
|
||||||
@@ -733,7 +734,7 @@ where
|
|||||||
|
|
||||||
// AsMut lifts over &mut
|
// AsMut lifts over &mut
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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
|
where
|
||||||
T: AsMut<U>,
|
T: AsMut<U>,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
use crate::cell::{Cell, Ref, RefCell, RefMut, SyncUnsafeCell, UnsafeCell};
|
use crate::cell::{Cell, Ref, RefCell, RefMut, SyncUnsafeCell, UnsafeCell};
|
||||||
use crate::char::{EscapeDebugExtArgs, MAX_LEN_UTF8};
|
use crate::char::{EscapeDebugExtArgs, MAX_LEN_UTF8};
|
||||||
use crate::marker::PhantomData;
|
use crate::marker::{PhantomData, PointeeSized};
|
||||||
use crate::num::fmt as numfmt;
|
use crate::num::fmt as numfmt;
|
||||||
use crate::ops::Deref;
|
use crate::ops::Deref;
|
||||||
use crate::{iter, result, str};
|
use crate::{iter, result, str};
|
||||||
@@ -864,7 +864,7 @@ impl Display for Arguments<'_> {
|
|||||||
#[doc(alias = "{:?}")]
|
#[doc(alias = "{:?}")]
|
||||||
#[rustc_diagnostic_item = "Debug"]
|
#[rustc_diagnostic_item = "Debug"]
|
||||||
#[rustc_trivial_field_reads]
|
#[rustc_trivial_field_reads]
|
||||||
pub trait Debug {
|
pub trait Debug: PointeeSized {
|
||||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@@ -995,7 +995,7 @@ pub use macros::Debug;
|
|||||||
#[doc(alias = "{}")]
|
#[doc(alias = "{}")]
|
||||||
#[rustc_diagnostic_item = "Display"]
|
#[rustc_diagnostic_item = "Display"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait Display {
|
pub trait Display: PointeeSized {
|
||||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@@ -1071,7 +1071,7 @@ pub trait Display {
|
|||||||
/// assert_eq!(format!("l as octal is: {l:#06o}"), "l as octal is: 0o0011");
|
/// assert_eq!(format!("l as octal is: {l:#06o}"), "l as octal is: 0o0011");
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait Octal {
|
pub trait Octal: PointeeSized {
|
||||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
||||||
@@ -1130,7 +1130,7 @@ pub trait Octal {
|
|||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait Binary {
|
pub trait Binary: PointeeSized {
|
||||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
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");
|
/// assert_eq!(format!("l as hex is: {l:#010x}"), "l as hex is: 0x00000009");
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait LowerHex {
|
pub trait LowerHex: PointeeSized {
|
||||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
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");
|
/// assert_eq!(format!("l as hex is: {l:#010X}"), "l as hex is: 0x7FFFFFFF");
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait UpperHex {
|
pub trait UpperHex: PointeeSized {
|
||||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
||||||
@@ -1299,7 +1299,7 @@ pub trait UpperHex {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_diagnostic_item = "Pointer"]
|
#[rustc_diagnostic_item = "Pointer"]
|
||||||
pub trait Pointer {
|
pub trait Pointer: PointeeSized {
|
||||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
||||||
@@ -1350,7 +1350,7 @@ pub trait Pointer {
|
|||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait LowerExp {
|
pub trait LowerExp: PointeeSized {
|
||||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
||||||
@@ -1401,7 +1401,7 @@ pub trait LowerExp {
|
|||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait UpperExp {
|
pub trait UpperExp: PointeeSized {
|
||||||
#[doc = include_str!("fmt_trait_method_doc.md")]
|
#[doc = include_str!("fmt_trait_method_doc.md")]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
|
||||||
@@ -2646,11 +2646,11 @@ macro_rules! fmt_refs {
|
|||||||
($($tr:ident),*) => {
|
($($tr:ident),*) => {
|
||||||
$(
|
$(
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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) }
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result { $tr::fmt(&**self, f) }
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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) }
|
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")]
|
#[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 {
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||||
if <<T as core::ptr::Pointee>::Metadata as core::unit::IsUnit>::is_unit() {
|
if <<T as core::ptr::Pointee>::Metadata as core::unit::IsUnit>::is_unit() {
|
||||||
pointer_fmt_inner(self.expose_provenance(), f)
|
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")]
|
#[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 {
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||||
Pointer::fmt(&(*self as *const T), f)
|
Pointer::fmt(&(*self as *const T), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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 {
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||||
Pointer::fmt(&(*self as *const T), f)
|
Pointer::fmt(&(*self as *const T), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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 {
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||||
Pointer::fmt(&(&**self as *const T), f)
|
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
|
// Implementation of Display/Debug for various core types
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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 {
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||||
Pointer::fmt(self, f)
|
Pointer::fmt(self, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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 {
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||||
Pointer::fmt(self, f)
|
Pointer::fmt(self, f)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ mod sip;
|
|||||||
/// [impl]: ../../std/primitive.str.html#impl-Hash-for-str
|
/// [impl]: ../../std/primitive.str.html#impl-Hash-for-str
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_diagnostic_item = "Hash"]
|
#[rustc_diagnostic_item = "Hash"]
|
||||||
pub trait Hash {
|
pub trait Hash: marker::PointeeSized {
|
||||||
/// Feeds this value into the given [`Hasher`].
|
/// Feeds this value into the given [`Hasher`].
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@@ -941,7 +941,7 @@ mod impls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized + Hash> Hash for &T {
|
impl<T: ?Sized + marker::PointeeSized + Hash> Hash for &T {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
(**self).hash(state);
|
(**self).hash(state);
|
||||||
@@ -949,7 +949,7 @@ mod impls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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]
|
#[inline]
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
(**self).hash(state);
|
(**self).hash(state);
|
||||||
@@ -957,7 +957,7 @@ mod impls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> Hash for *const T {
|
impl<T: ?Sized + marker::PointeeSized> Hash for *const T {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
let (address, metadata) = self.to_raw_parts();
|
let (address, metadata) = self.to_raw_parts();
|
||||||
@@ -967,7 +967,7 @@ mod impls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> Hash for *mut T {
|
impl<T: ?Sized + marker::PointeeSized> Hash for *mut T {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
let (address, metadata) = self.to_raw_parts();
|
let (address, metadata) = self.to_raw_parts();
|
||||||
|
|||||||
@@ -1,39 +1,41 @@
|
|||||||
//! Various traits used to restrict intrinsics to not-completely-wrong types.
|
//! 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,
|
/// Types with a built-in dereference operator in runtime MIR,
|
||||||
/// aka references and raw pointers.
|
/// aka references and raw pointers.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// Must actually *be* such a type.
|
/// Must actually *be* such a type.
|
||||||
pub unsafe trait BuiltinDeref: Sized {
|
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;
|
type Pointee = T;
|
||||||
}
|
}
|
||||||
unsafe impl<T: ?Sized> BuiltinDeref for &T {
|
unsafe impl<T: PointeeSized> BuiltinDeref for &T {
|
||||||
type Pointee = T;
|
type Pointee = T;
|
||||||
}
|
}
|
||||||
unsafe impl<T: ?Sized> BuiltinDeref for *mut T {
|
unsafe impl<T: PointeeSized> BuiltinDeref for *mut T {
|
||||||
type Pointee = T;
|
type Pointee = T;
|
||||||
}
|
}
|
||||||
unsafe impl<T: ?Sized> BuiltinDeref for *const T {
|
unsafe impl<T: PointeeSized> BuiltinDeref for *const T {
|
||||||
type Pointee = T;
|
type Pointee = T;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ChangePointee<U: ?Sized>: BuiltinDeref {
|
pub trait ChangePointee<U: PointeeSized>: BuiltinDeref {
|
||||||
type Output;
|
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;
|
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;
|
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;
|
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;
|
type Output = *const U;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
)]
|
)]
|
||||||
#![allow(missing_docs)]
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
use crate::marker::{ConstParamTy, DiscriminantKind, Tuple};
|
use crate::marker::{ConstParamTy, DiscriminantKind, PointeeSized, Tuple};
|
||||||
use crate::ptr;
|
use crate::ptr;
|
||||||
|
|
||||||
mod bounds;
|
mod bounds;
|
||||||
@@ -2740,7 +2740,7 @@ where
|
|||||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||||
#[rustc_intrinsic_const_stable_indirect]
|
#[rustc_intrinsic_const_stable_indirect]
|
||||||
#[rustc_intrinsic]
|
#[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.
|
/// 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
|
// 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")]
|
#[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")]
|
#[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
|
// 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
|
// `&T: Send` (and it also removes the unsound default instance `T Send` -> `&T: Send` that would
|
||||||
// otherwise exist).
|
// otherwise exist).
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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.
|
/// 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_specialization_trait]
|
||||||
#[rustc_deny_explicit_impl]
|
#[rustc_deny_explicit_impl]
|
||||||
#[rustc_do_not_implement_via_object]
|
#[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]
|
#[rustc_coinductive]
|
||||||
pub trait Sized {
|
pub trait Sized: MetaSized {
|
||||||
// Empty.
|
// 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.
|
/// Types that can be "unsized" to a dynamically-sized type.
|
||||||
///
|
///
|
||||||
/// For example, the sized array type `[i8; 2]` implements `Unsize<[i8]>` and
|
/// For example, the sized array type `[i8; 2]` implements `Unsize<[i8]>` and
|
||||||
@@ -192,7 +229,7 @@ pub trait Sized {
|
|||||||
#[lang = "unsize"]
|
#[lang = "unsize"]
|
||||||
#[rustc_deny_explicit_impl]
|
#[rustc_deny_explicit_impl]
|
||||||
#[rustc_do_not_implement_via_object]
|
#[rustc_do_not_implement_via_object]
|
||||||
pub trait Unsize<T: ?Sized> {
|
pub trait Unsize<T: PointeeSized>: PointeeSized {
|
||||||
// Empty.
|
// Empty.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,7 +266,7 @@ marker_impls! {
|
|||||||
(),
|
(),
|
||||||
{T, const N: usize} [T; N],
|
{T, const N: usize} [T; N],
|
||||||
{T} [T],
|
{T} [T],
|
||||||
{T: ?Sized} &T,
|
{T: PointeeSized} &T,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Types whose values can be duplicated simply by copying bits.
|
/// Types whose values can be duplicated simply by copying bits.
|
||||||
@@ -442,8 +479,8 @@ marker_impls! {
|
|||||||
isize, i8, i16, i32, i64, i128,
|
isize, i8, i16, i32, i64, i128,
|
||||||
f16, f32, f64, f128,
|
f16, f32, f64, f128,
|
||||||
bool, char,
|
bool, char,
|
||||||
{T: ?Sized} *const T,
|
{T: PointeeSized} *const T,
|
||||||
{T: ?Sized} *mut T,
|
{T: PointeeSized} *mut T,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,7 +489,7 @@ impl Copy for ! {}
|
|||||||
|
|
||||||
/// Shared references can be copied, but mutable references *cannot*!
|
/// Shared references can be copied, but mutable references *cannot*!
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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
|
/// Marker trait for the types that are allowed in union fields and unsafe
|
||||||
/// binder types.
|
/// binder types.
|
||||||
@@ -636,9 +673,9 @@ pub unsafe auto trait Sync {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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")]
|
#[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`.
|
/// 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
|
/// [drop check]: Drop#drop-check
|
||||||
#[lang = "phantom_data"]
|
#[lang = "phantom_data"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct PhantomData<T: ?Sized>;
|
pub struct PhantomData<T: PointeeSized>;
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> Hash for PhantomData<T> {
|
impl<T: PointeeSized> Hash for PhantomData<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: Hasher>(&self, _: &mut H) {}
|
fn hash<H: Hasher>(&self, _: &mut H) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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 {
|
fn eq(&self, _other: &PhantomData<T>) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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")]
|
#[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> {
|
fn partial_cmp(&self, _other: &PhantomData<T>) -> Option<cmp::Ordering> {
|
||||||
Option::Some(cmp::Ordering::Equal)
|
Option::Some(cmp::Ordering::Equal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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 {
|
fn cmp(&self, _other: &PhantomData<T>) -> cmp::Ordering {
|
||||||
cmp::Ordering::Equal
|
cmp::Ordering::Equal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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")]
|
#[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 {
|
fn clone(&self) -> Self {
|
||||||
Self
|
Self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> Default for PhantomData<T> {
|
impl<T: PointeeSized> Default for PhantomData<T> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self
|
Self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "structural_match", issue = "31434")]
|
#[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.
|
/// Compiler-internal trait used to indicate the type of enum discriminants.
|
||||||
///
|
///
|
||||||
@@ -868,15 +905,15 @@ pub trait DiscriminantKind {
|
|||||||
pub unsafe auto trait Freeze {}
|
pub unsafe auto trait Freeze {}
|
||||||
|
|
||||||
#[unstable(feature = "freeze", issue = "121675")]
|
#[unstable(feature = "freeze", issue = "121675")]
|
||||||
impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
|
impl<T: PointeeSized> !Freeze for UnsafeCell<T> {}
|
||||||
marker_impls! {
|
marker_impls! {
|
||||||
#[unstable(feature = "freeze", issue = "121675")]
|
#[unstable(feature = "freeze", issue = "121675")]
|
||||||
unsafe Freeze for
|
unsafe Freeze for
|
||||||
{T: ?Sized} PhantomData<T>,
|
{T: PointeeSized} PhantomData<T>,
|
||||||
{T: ?Sized} *const T,
|
{T: PointeeSized} *const T,
|
||||||
{T: ?Sized} *mut T,
|
{T: PointeeSized} *mut T,
|
||||||
{T: ?Sized} &T,
|
{T: PointeeSized} &T,
|
||||||
{T: ?Sized} &mut T,
|
{T: PointeeSized} &mut T,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used to determine whether a type contains any `UnsafePinned` (or `PhantomPinned`) internally,
|
/// Used to determine whether a type contains any `UnsafePinned` (or `PhantomPinned`) internally,
|
||||||
@@ -991,15 +1028,15 @@ impl !UnsafeUnpin for PhantomPinned {}
|
|||||||
marker_impls! {
|
marker_impls! {
|
||||||
#[stable(feature = "pin", since = "1.33.0")]
|
#[stable(feature = "pin", since = "1.33.0")]
|
||||||
Unpin for
|
Unpin for
|
||||||
{T: ?Sized} &T,
|
{T: PointeeSized} &T,
|
||||||
{T: ?Sized} &mut T,
|
{T: PointeeSized} &mut T,
|
||||||
}
|
}
|
||||||
|
|
||||||
marker_impls! {
|
marker_impls! {
|
||||||
#[stable(feature = "pin_raw", since = "1.38.0")]
|
#[stable(feature = "pin_raw", since = "1.38.0")]
|
||||||
Unpin for
|
Unpin for
|
||||||
{T: ?Sized} *const T,
|
{T: PointeeSized} *const T,
|
||||||
{T: ?Sized} *mut T,
|
{T: PointeeSized} *mut T,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A marker for types that can be dropped.
|
/// A marker for types that can be dropped.
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use crate::marker::PointeeSized;
|
||||||
|
|
||||||
/// Used for immutable dereferencing operations, like `*v`.
|
/// Used for immutable dereferencing operations, like `*v`.
|
||||||
///
|
///
|
||||||
/// In addition to being used for explicit dereferencing operations with the
|
/// In addition to being used for explicit dereferencing operations with the
|
||||||
@@ -135,7 +137,7 @@
|
|||||||
#[rustc_diagnostic_item = "Deref"]
|
#[rustc_diagnostic_item = "Deref"]
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
|
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
|
||||||
pub trait Deref {
|
pub trait Deref: PointeeSized {
|
||||||
/// The resulting type after dereferencing.
|
/// The resulting type after dereferencing.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_diagnostic_item = "deref_target"]
|
#[rustc_diagnostic_item = "deref_target"]
|
||||||
@@ -267,7 +269,7 @@ impl<T: ?Sized> const Deref for &mut T {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
|
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
|
||||||
pub trait DerefMut: ~const Deref {
|
pub trait DerefMut: ~const Deref + PointeeSized {
|
||||||
/// Mutably dereferences the value.
|
/// Mutably dereferences the value.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_diagnostic_item = "deref_mut_method"]
|
#[rustc_diagnostic_item = "deref_mut_method"]
|
||||||
@@ -293,7 +295,7 @@ impl<T: ?Sized> const DerefMut for &mut T {
|
|||||||
/// unchanged.
|
/// unchanged.
|
||||||
#[unstable(feature = "deref_pure_trait", issue = "87121")]
|
#[unstable(feature = "deref_pure_trait", issue = "87121")]
|
||||||
#[lang = "deref_pure"]
|
#[lang = "deref_pure"]
|
||||||
pub unsafe trait DerefPure {}
|
pub unsafe trait DerefPure: PointeeSized {}
|
||||||
|
|
||||||
#[unstable(feature = "deref_pure_trait", issue = "87121")]
|
#[unstable(feature = "deref_pure_trait", issue = "87121")]
|
||||||
unsafe impl<T: ?Sized> DerefPure for &T {}
|
unsafe impl<T: ?Sized> DerefPure for &T {}
|
||||||
@@ -366,7 +368,7 @@ unsafe impl<T: ?Sized> DerefPure for &mut T {}
|
|||||||
/// ```
|
/// ```
|
||||||
#[lang = "receiver"]
|
#[lang = "receiver"]
|
||||||
#[unstable(feature = "arbitrary_self_types", issue = "44874")]
|
#[unstable(feature = "arbitrary_self_types", issue = "44874")]
|
||||||
pub trait Receiver {
|
pub trait Receiver: PointeeSized {
|
||||||
/// The target type on which the method may be called.
|
/// The target type on which the method may be called.
|
||||||
#[rustc_diagnostic_item = "receiver_target"]
|
#[rustc_diagnostic_item = "receiver_target"]
|
||||||
#[lang = "receiver_target"]
|
#[lang = "receiver_target"]
|
||||||
@@ -393,12 +395,12 @@ where
|
|||||||
#[lang = "legacy_receiver"]
|
#[lang = "legacy_receiver"]
|
||||||
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
|
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub trait LegacyReceiver {
|
pub trait LegacyReceiver: PointeeSized {
|
||||||
// Empty.
|
// Empty.
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
|
#[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")]
|
#[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,
|
/// Trait that indicates that this is a pointer or a wrapper for one,
|
||||||
/// where unsizing can be performed on the pointee.
|
/// where unsizing can be performed on the pointee.
|
||||||
@@ -33,40 +33,40 @@ use crate::marker::Unsize;
|
|||||||
/// [nomicon-coerce]: ../../nomicon/coercions.html
|
/// [nomicon-coerce]: ../../nomicon/coercions.html
|
||||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
||||||
#[lang = "coerce_unsized"]
|
#[lang = "coerce_unsized"]
|
||||||
pub trait CoerceUnsized<T: ?Sized> {
|
pub trait CoerceUnsized<T: PointeeSized> {
|
||||||
// Empty.
|
// Empty.
|
||||||
}
|
}
|
||||||
|
|
||||||
// &mut T -> &mut U
|
// &mut T -> &mut U
|
||||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
#[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
|
// &mut T -> &U
|
||||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
#[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
|
// &mut T -> *mut U
|
||||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
#[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
|
// &mut T -> *const U
|
||||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
#[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
|
// &T -> &U
|
||||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
#[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
|
// &T -> *const U
|
||||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
#[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
|
// *mut T -> *mut U
|
||||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
#[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
|
// *mut T -> *const U
|
||||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
#[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
|
// *const T -> *const U
|
||||||
#[unstable(feature = "coerce_unsized", issue = "18598")]
|
#[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
|
/// `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.
|
/// 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
|
// &T -> &U
|
||||||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
#[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
|
// &mut T -> &mut U
|
||||||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
#[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
|
// *const T -> *const U
|
||||||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
#[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
|
// *mut T -> *mut U
|
||||||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
#[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::mem::{self, SizedTypeProperties};
|
||||||
use crate::slice::{self, SliceIndex};
|
use crate::slice::{self, SliceIndex};
|
||||||
|
|
||||||
impl<T: ?Sized> *const T {
|
impl<T: PointeeSized> *const T {
|
||||||
#[doc = include_str!("docs/is_null.md")]
|
#[doc = include_str!("docs/is_null.md")]
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@@ -129,7 +129,7 @@ impl<T: ?Sized> *const T {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub const fn with_metadata_of<U>(self, meta: *const U) -> *const U
|
pub const fn with_metadata_of<U>(self, meta: *const U) -> *const U
|
||||||
where
|
where
|
||||||
U: ?Sized,
|
U: PointeeSized,
|
||||||
{
|
{
|
||||||
from_raw_parts::<U>(self as *const (), metadata(meta))
|
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.
|
/// Pointer equality is by address, as produced by the [`<*const T>::addr`](pointer::addr) method.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> PartialEq for *const T {
|
impl<T: PointeeSized> PartialEq for *const T {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||||
fn eq(&self, other: &*const T) -> bool {
|
fn eq(&self, other: &*const T) -> bool {
|
||||||
@@ -1596,11 +1596,11 @@ impl<T: ?Sized> PartialEq for *const T {
|
|||||||
|
|
||||||
/// Pointer equality is an equivalence relation.
|
/// Pointer equality is an equivalence relation.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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.
|
/// Pointer comparison is by address, as produced by the `[`<*const T>::addr`](pointer::addr)` method.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> Ord for *const T {
|
impl<T: PointeeSized> Ord for *const T {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||||
fn cmp(&self, other: &*const T) -> Ordering {
|
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.
|
/// Pointer comparison is by address, as produced by the `[`<*const T>::addr`](pointer::addr)` method.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> PartialOrd for *const T {
|
impl<T: PointeeSized> PartialOrd for *const T {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||||
fn partial_cmp(&self, other: &*const T) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &*const T) -> Option<Ordering> {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::hash::{Hash, Hasher};
|
use crate::hash::{Hash, Hasher};
|
||||||
use crate::intrinsics::{aggregate_raw_ptr, ptr_metadata};
|
use crate::intrinsics::{aggregate_raw_ptr, ptr_metadata};
|
||||||
use crate::marker::Freeze;
|
use crate::marker::{Freeze, PointeeSized};
|
||||||
use crate::ptr::NonNull;
|
use crate::ptr::NonNull;
|
||||||
|
|
||||||
/// Provides the pointer metadata type of any pointed-to type.
|
/// Provides the pointer metadata type of any pointed-to type.
|
||||||
@@ -55,7 +55,7 @@ use crate::ptr::NonNull;
|
|||||||
#[lang = "pointee_trait"]
|
#[lang = "pointee_trait"]
|
||||||
#[rustc_deny_explicit_impl]
|
#[rustc_deny_explicit_impl]
|
||||||
#[rustc_do_not_implement_via_object]
|
#[rustc_do_not_implement_via_object]
|
||||||
pub trait Pointee {
|
pub trait Pointee: PointeeSized {
|
||||||
/// The type for metadata in pointers and references to `Self`.
|
/// The type for metadata in pointers and references to `Self`.
|
||||||
#[lang = "metadata_type"]
|
#[lang = "metadata_type"]
|
||||||
// NOTE: Keep trait bounds in `static_assert_expected_bounds_for_metadata`
|
// NOTE: Keep trait bounds in `static_assert_expected_bounds_for_metadata`
|
||||||
@@ -81,7 +81,7 @@ pub trait Pointee {
|
|||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
||||||
// NOTE: don’t stabilize this before trait aliases are stable in the language?
|
// 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.
|
/// Extracts the metadata component of a pointer.
|
||||||
///
|
///
|
||||||
@@ -96,7 +96,7 @@ pub trait Thin = Pointee<Metadata = ()>;
|
|||||||
/// assert_eq!(std::ptr::metadata("foo"), 3_usize);
|
/// assert_eq!(std::ptr::metadata("foo"), 3_usize);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[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)
|
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
|
/// [`slice::from_raw_parts`]: crate::slice::from_raw_parts
|
||||||
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn from_raw_parts<T: ?Sized>(
|
pub const fn from_raw_parts<T: PointeeSized>(
|
||||||
data_pointer: *const impl Thin,
|
data_pointer: *const impl Thin,
|
||||||
metadata: <T as Pointee>::Metadata,
|
metadata: <T as Pointee>::Metadata,
|
||||||
) -> *const T {
|
) -> *const T {
|
||||||
@@ -122,7 +122,7 @@ pub const fn from_raw_parts<T: ?Sized>(
|
|||||||
/// See the documentation of [`from_raw_parts`] for more details.
|
/// See the documentation of [`from_raw_parts`] for more details.
|
||||||
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn from_raw_parts_mut<T: ?Sized>(
|
pub const fn from_raw_parts_mut<T: PointeeSized>(
|
||||||
data_pointer: *mut impl Thin,
|
data_pointer: *mut impl Thin,
|
||||||
metadata: <T as Pointee>::Metadata,
|
metadata: <T as Pointee>::Metadata,
|
||||||
) -> *mut T {
|
) -> *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
|
/// 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).
|
/// compare equal (since identical vtables can be deduplicated within a codegen unit).
|
||||||
#[lang = "dyn_metadata"]
|
#[lang = "dyn_metadata"]
|
||||||
pub struct DynMetadata<Dyn: ?Sized> {
|
pub struct DynMetadata<Dyn: PointeeSized> {
|
||||||
_vtable_ptr: NonNull<VTable>,
|
_vtable_ptr: NonNull<VTable>,
|
||||||
_phantom: crate::marker::PhantomData<Dyn>,
|
_phantom: crate::marker::PhantomData<Dyn>,
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ unsafe extern "C" {
|
|||||||
type VTable;
|
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
|
/// 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
|
/// 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
|
/// 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: PointeeSized> Send for DynMetadata<Dyn> {}
|
||||||
unsafe impl<Dyn: ?Sized> Sync 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 {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_tuple("DynMetadata").field(&self.vtable_ptr()).finish()
|
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.
|
// 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]
|
#[inline]
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> 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]
|
#[inline]
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
crate::ptr::eq::<VTable>(self.vtable_ptr(), other.vtable_ptr())
|
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]
|
#[inline]
|
||||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||||
fn cmp(&self, other: &Self) -> crate::cmp::Ordering {
|
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]
|
#[inline]
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<crate::cmp::Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<crate::cmp::Ordering> {
|
||||||
Some(self.cmp(other))
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Dyn: ?Sized> Hash for DynMetadata<Dyn> {
|
impl<Dyn: PointeeSized> Hash for DynMetadata<Dyn> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
||||||
crate::ptr::hash::<VTable, _>(self.vtable_ptr(), hasher)
|
crate::ptr::hash::<VTable, _>(self.vtable_ptr(), hasher)
|
||||||
|
|||||||
@@ -398,7 +398,7 @@
|
|||||||
|
|
||||||
use crate::cmp::Ordering;
|
use crate::cmp::Ordering;
|
||||||
use crate::intrinsics::const_eval_select;
|
use crate::intrinsics::const_eval_select;
|
||||||
use crate::marker::FnPtr;
|
use crate::marker::{FnPtr, PointeeSized};
|
||||||
use crate::mem::{self, MaybeUninit, SizedTypeProperties};
|
use crate::mem::{self, MaybeUninit, SizedTypeProperties};
|
||||||
use crate::num::NonZero;
|
use crate::num::NonZero;
|
||||||
use crate::{fmt, hash, intrinsics, ub_checks};
|
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"]
|
#[lang = "drop_in_place"]
|
||||||
#[allow(unconditional_recursion)]
|
#[allow(unconditional_recursion)]
|
||||||
#[rustc_diagnostic_item = "ptr_drop_in_place"]
|
#[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
|
// Code here does not matter - this is replaced by the
|
||||||
// real drop glue by the compiler.
|
// 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_promotable]
|
||||||
#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
|
#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
|
||||||
#[rustc_diagnostic_item = "ptr_null"]
|
#[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), ())
|
from_raw_parts(without_provenance::<()>(0), ())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -850,7 +850,7 @@ pub const fn null<T: ?Sized + Thin>() -> *const T {
|
|||||||
#[rustc_promotable]
|
#[rustc_promotable]
|
||||||
#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
|
#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
|
||||||
#[rustc_diagnostic_item = "ptr_null_mut"]
|
#[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), ())
|
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_const_stable(feature = "ptr_from_ref", since = "1.76.0")]
|
||||||
#[rustc_never_returns_null_ptr]
|
#[rustc_never_returns_null_ptr]
|
||||||
#[rustc_diagnostic_item = "ptr_from_ref"]
|
#[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
|
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")]
|
#[stable(feature = "ptr_from_ref", since = "1.76.0")]
|
||||||
#[rustc_const_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]
|
#[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
|
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"]
|
#[must_use = "pointer comparison produces a value"]
|
||||||
#[rustc_diagnostic_item = "ptr_eq"]
|
#[rustc_diagnostic_item = "ptr_eq"]
|
||||||
#[allow(ambiguous_wide_pointer_comparisons)] // it's actually clear here
|
#[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
|
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")]
|
#[stable(feature = "ptr_addr_eq", since = "1.76.0")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use = "pointer comparison produces a value"]
|
#[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 ())
|
(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);
|
/// assert_eq!(actual, expected);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "ptr_hash", since = "1.35.0")]
|
#[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;
|
use crate::hash::Hash;
|
||||||
hashee.hash(into);
|
hashee.hash(into);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::cmp::Ordering::{Equal, Greater, Less};
|
use crate::cmp::Ordering::{Equal, Greater, Less};
|
||||||
use crate::intrinsics::const_eval_select;
|
use crate::intrinsics::const_eval_select;
|
||||||
|
use crate::marker::PointeeSized;
|
||||||
use crate::mem::{self, SizedTypeProperties};
|
use crate::mem::{self, SizedTypeProperties};
|
||||||
use crate::slice::{self, SliceIndex};
|
use crate::slice::{self, SliceIndex};
|
||||||
|
|
||||||
impl<T: ?Sized> *mut T {
|
impl<T: PointeeSized> *mut T {
|
||||||
#[doc = include_str!("docs/is_null.md")]
|
#[doc = include_str!("docs/is_null.md")]
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@@ -110,7 +111,7 @@ impl<T: ?Sized> *mut T {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub const fn with_metadata_of<U>(self, meta: *const U) -> *mut U
|
pub const fn with_metadata_of<U>(self, meta: *const U) -> *mut U
|
||||||
where
|
where
|
||||||
U: ?Sized,
|
U: PointeeSized,
|
||||||
{
|
{
|
||||||
from_raw_parts_mut::<U>(self as *mut (), metadata(meta))
|
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.
|
/// Pointer equality is by address, as produced by the [`<*mut T>::addr`](pointer::addr) method.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> PartialEq for *mut T {
|
impl<T: PointeeSized> PartialEq for *mut T {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||||
fn eq(&self, other: &*mut T) -> bool {
|
fn eq(&self, other: &*mut T) -> bool {
|
||||||
@@ -2016,11 +2017,11 @@ impl<T: ?Sized> PartialEq for *mut T {
|
|||||||
|
|
||||||
/// Pointer equality is an equivalence relation.
|
/// Pointer equality is an equivalence relation.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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.
|
/// Pointer comparison is by address, as produced by the [`<*mut T>::addr`](pointer::addr) method.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> Ord for *mut T {
|
impl<T: PointeeSized> Ord for *mut T {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||||
fn cmp(&self, other: &*mut T) -> Ordering {
|
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.
|
/// Pointer comparison is by address, as produced by the [`<*mut T>::addr`](pointer::addr) method.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized> PartialOrd for *mut T {
|
impl<T: PointeeSized> PartialOrd for *mut T {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||||
fn partial_cmp(&self, other: &*mut T) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &*mut T) -> Option<Ordering> {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::cmp::Ordering;
|
use crate::cmp::Ordering;
|
||||||
use crate::marker::Unsize;
|
use crate::marker::{PointeeSized, Unsize};
|
||||||
use crate::mem::{MaybeUninit, SizedTypeProperties};
|
use crate::mem::{MaybeUninit, SizedTypeProperties};
|
||||||
use crate::num::NonZero;
|
use crate::num::NonZero;
|
||||||
use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
||||||
@@ -67,7 +67,7 @@ use crate::{fmt, hash, intrinsics, mem, ptr};
|
|||||||
#[rustc_layout_scalar_valid_range_start(1)]
|
#[rustc_layout_scalar_valid_range_start(1)]
|
||||||
#[rustc_nonnull_optimization_guaranteed]
|
#[rustc_nonnull_optimization_guaranteed]
|
||||||
#[rustc_diagnostic_item = "NonNull"]
|
#[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
|
// 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>.
|
// this is banned by <https://github.com/rust-lang/compiler-team/issues/807>.
|
||||||
pointer: *const T,
|
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.
|
/// `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.
|
// N.B., this impl is unnecessary, but should provide better error messages.
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
#[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.
|
/// `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.
|
// N.B., this impl is unnecessary, but should provide better error messages.
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
#[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> {
|
impl<T: Sized> NonNull<T> {
|
||||||
/// Creates a pointer with the given address and no [provenance][crate::ptr#provenance].
|
/// 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`.
|
/// Creates a new `NonNull`.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
@@ -1604,7 +1604,7 @@ impl<T> NonNull<[T]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
impl<T: ?Sized> Clone for NonNull<T> {
|
impl<T: PointeeSized> Clone for NonNull<T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
*self
|
*self
|
||||||
@@ -1612,39 +1612,39 @@ impl<T: ?Sized> Clone for NonNull<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
#[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")]
|
#[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")]
|
#[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")]
|
#[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")]
|
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||||
impl<T> core::marker::PointerLike for NonNull<T> {}
|
impl<T> core::marker::PointerLike for NonNull<T> {}
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
#[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 {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
fmt::Pointer::fmt(&self.as_ptr(), f)
|
fmt::Pointer::fmt(&self.as_ptr(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
#[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 {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
fmt::Pointer::fmt(&self.as_ptr(), f)
|
fmt::Pointer::fmt(&self.as_ptr(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
#[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")]
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
impl<T: ?Sized> PartialEq for NonNull<T> {
|
impl<T: PointeeSized> PartialEq for NonNull<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
@@ -1653,7 +1653,7 @@ impl<T: ?Sized> PartialEq for NonNull<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
impl<T: ?Sized> Ord for NonNull<T> {
|
impl<T: PointeeSized> Ord for NonNull<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
@@ -1662,7 +1662,7 @@ impl<T: ?Sized> Ord for NonNull<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
impl<T: ?Sized> PartialOrd for NonNull<T> {
|
impl<T: PointeeSized> PartialOrd for NonNull<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
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")]
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
impl<T: ?Sized> hash::Hash for NonNull<T> {
|
impl<T: PointeeSized> hash::Hash for NonNull<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
self.as_ptr().hash(state)
|
self.as_ptr().hash(state)
|
||||||
@@ -1679,7 +1679,7 @@ impl<T: ?Sized> hash::Hash for NonNull<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
#[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]
|
#[inline]
|
||||||
fn from(unique: Unique<T>) -> Self {
|
fn from(unique: Unique<T>) -> Self {
|
||||||
unique.as_non_null_ptr()
|
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")]
|
#[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>`.
|
/// Converts a `&mut T` to a `NonNull<T>`.
|
||||||
///
|
///
|
||||||
/// This conversion is safe and infallible since references cannot be null.
|
/// 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")]
|
#[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>`.
|
/// Converts a `&T` to a `NonNull<T>`.
|
||||||
///
|
///
|
||||||
/// This conversion is safe and infallible since references cannot be null.
|
/// This conversion is safe and infallible since references cannot be null.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::marker::{PhantomData, Unsize};
|
use crate::marker::{PhantomData, PointeeSized, Unsize};
|
||||||
use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
||||||
use crate::pin::PinCoerceUnsized;
|
use crate::pin::PinCoerceUnsized;
|
||||||
use crate::ptr::NonNull;
|
use crate::ptr::NonNull;
|
||||||
@@ -34,7 +34,7 @@ use crate::ptr::NonNull;
|
|||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
// Lang item used experimentally by Miri to define the semantics of `Unique`.
|
// Lang item used experimentally by Miri to define the semantics of `Unique`.
|
||||||
#[lang = "ptr_unique"]
|
#[lang = "ptr_unique"]
|
||||||
pub struct Unique<T: ?Sized> {
|
pub struct Unique<T: PointeeSized> {
|
||||||
pointer: NonNull<T>,
|
pointer: NonNull<T>,
|
||||||
// NOTE: this marker has no consequences for variance, but is necessary
|
// NOTE: this marker has no consequences for variance, but is necessary
|
||||||
// for dropck to understand that we logically own a `T`.
|
// 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
|
/// unenforced by the type system; the abstraction using the
|
||||||
/// `Unique` must enforce it.
|
/// `Unique` must enforce it.
|
||||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
#[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
|
/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
|
||||||
/// reference is unaliased. Note that this aliasing invariant is
|
/// reference is unaliased. Note that this aliasing invariant is
|
||||||
/// unenforced by the type system; the abstraction using the
|
/// unenforced by the type system; the abstraction using the
|
||||||
/// `Unique` must enforce it.
|
/// `Unique` must enforce it.
|
||||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
#[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")]
|
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||||
impl<T: Sized> Unique<T> {
|
impl<T: Sized> Unique<T> {
|
||||||
@@ -78,7 +78,7 @@ impl<T: Sized> Unique<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||||
impl<T: ?Sized> Unique<T> {
|
impl<T: PointeeSized> Unique<T> {
|
||||||
/// Creates a new `Unique`.
|
/// Creates a new `Unique`.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
@@ -157,7 +157,7 @@ impl<T: ?Sized> Unique<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||||
impl<T: ?Sized> Clone for Unique<T> {
|
impl<T: PointeeSized> Clone for Unique<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
*self
|
*self
|
||||||
@@ -165,33 +165,33 @@ impl<T: ?Sized> Clone for Unique<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
#[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")]
|
#[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")]
|
#[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")]
|
#[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")]
|
#[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 {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
fmt::Pointer::fmt(&self.as_ptr(), f)
|
fmt::Pointer::fmt(&self.as_ptr(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
#[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 {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
fmt::Pointer::fmt(&self.as_ptr(), f)
|
fmt::Pointer::fmt(&self.as_ptr(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
#[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>`.
|
/// Converts a `&mut T` to a `Unique<T>`.
|
||||||
///
|
///
|
||||||
/// This conversion is infallible since references cannot be null.
|
/// 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")]
|
#[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>`.
|
/// Converts a `NonNull<T>` to a `Unique<T>`.
|
||||||
///
|
///
|
||||||
/// This conversion is infallible since `NonNull` cannot be null.
|
/// This conversion is infallible since `NonNull` cannot be null.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// See core/src/primitive_docs.rs for documentation.
|
// See core/src/primitive_docs.rs for documentation.
|
||||||
|
|
||||||
use crate::cmp::Ordering::{self, *};
|
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};
|
use crate::ops::ControlFlow::{self, Break, Continue};
|
||||||
|
|
||||||
// Recursive macro for implementing n-ary tuple functions and operations
|
// 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")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<$($T: PartialEq),+> PartialEq for ($($T,)+)
|
impl<$($T: PartialEq),+> PartialEq for ($($T,)+)
|
||||||
where
|
where
|
||||||
last_type!($($T,)+): ?Sized
|
last_type!($($T,)+): PointeeSized
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn eq(&self, other: &($($T,)+)) -> bool {
|
fn eq(&self, other: &($($T,)+)) -> bool {
|
||||||
@@ -43,7 +43,7 @@ macro_rules! tuple_impls {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<$($T: Eq),+> Eq for ($($T,)+)
|
impl<$($T: Eq),+> Eq for ($($T,)+)
|
||||||
where
|
where
|
||||||
last_type!($($T,)+): ?Sized
|
last_type!($($T,)+): PointeeSized
|
||||||
{}
|
{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ macro_rules! tuple_impls {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<$($T: PartialOrd),+> PartialOrd for ($($T,)+)
|
impl<$($T: PartialOrd),+> PartialOrd for ($($T,)+)
|
||||||
where
|
where
|
||||||
last_type!($($T,)+): ?Sized
|
last_type!($($T,)+): PointeeSized
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
|
||||||
@@ -119,7 +119,7 @@ macro_rules! tuple_impls {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<$($T: Ord),+> Ord for ($($T,)+)
|
impl<$($T: Ord),+> Ord for ($($T,)+)
|
||||||
where
|
where
|
||||||
last_type!($($T,)+): ?Sized
|
last_type!($($T,)+): PointeeSized
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn cmp(&self, other: &($($T,)+)) -> Ordering {
|
fn cmp(&self, other: &($($T,)+)) -> Ordering {
|
||||||
|
|||||||
@@ -21,8 +21,21 @@
|
|||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![warn(unreachable_pub)]
|
#![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"]
|
#[lang = "sized"]
|
||||||
trait Sized {}
|
pub trait Sized {}
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
#[lang = "sized"]
|
||||||
|
pub trait Sized: MetaSized {}
|
||||||
|
|
||||||
#[lang = "sync"]
|
#[lang = "sync"]
|
||||||
auto trait Sync {}
|
auto trait Sync {}
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
@@ -30,14 +43,25 @@ trait Copy {}
|
|||||||
#[lang = "freeze"]
|
#[lang = "freeze"]
|
||||||
auto trait Freeze {}
|
auto trait Freeze {}
|
||||||
|
|
||||||
|
#[cfg(bootstrap)]
|
||||||
impl<T: ?Sized> Copy for *mut T {}
|
impl<T: ?Sized> Copy for *mut T {}
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
impl<T: PointeeSized> Copy for *mut T {}
|
||||||
|
|
||||||
|
#[cfg(bootstrap)]
|
||||||
#[lang = "drop_in_place"]
|
#[lang = "drop_in_place"]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unconditional_recursion)]
|
#[allow(unconditional_recursion)]
|
||||||
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||||
drop_in_place(to_drop);
|
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
|
// Frame unwind info registration
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -8,8 +8,21 @@
|
|||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![warn(unreachable_pub)]
|
#![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"]
|
#[lang = "sized"]
|
||||||
trait Sized {}
|
pub trait Sized {}
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
#[lang = "sized"]
|
||||||
|
pub trait Sized: MetaSized {}
|
||||||
|
|
||||||
#[lang = "sync"]
|
#[lang = "sync"]
|
||||||
trait Sync {}
|
trait Sync {}
|
||||||
impl<T> Sync for T {}
|
impl<T> Sync for T {}
|
||||||
@@ -18,14 +31,25 @@ trait Copy {}
|
|||||||
#[lang = "freeze"]
|
#[lang = "freeze"]
|
||||||
auto trait Freeze {}
|
auto trait Freeze {}
|
||||||
|
|
||||||
|
#[cfg(bootstrap)]
|
||||||
impl<T: ?Sized> Copy for *mut T {}
|
impl<T: ?Sized> Copy for *mut T {}
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
impl<T: PointeeSized> Copy for *mut T {}
|
||||||
|
|
||||||
|
#[cfg(bootstrap)]
|
||||||
#[lang = "drop_in_place"]
|
#[lang = "drop_in_place"]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unconditional_recursion)]
|
#[allow(unconditional_recursion)]
|
||||||
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||||
drop_in_place(to_drop);
|
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"))]
|
#[cfg(all(target_os = "windows", target_arch = "x86", target_env = "gnu"))]
|
||||||
pub mod eh_frames {
|
pub mod eh_frames {
|
||||||
|
|||||||
@@ -2574,7 +2574,7 @@ fn prepare_cargo_test(
|
|||||||
// by `Cargo::new` and that actually makes things go wrong.
|
// by `Cargo::new` and that actually makes things go wrong.
|
||||||
if builder.kind != Kind::Miri {
|
if builder.kind != Kind::Miri {
|
||||||
let mut dylib_paths = builder.rustc_lib_paths(compiler);
|
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);
|
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 compiler = builder.compiler_for(builder.top_stage, host, host);
|
||||||
let mut cmd = command(builder.ensure(ErrorIndex { compiler }).tool_path);
|
let mut cmd = command(builder.ensure(ErrorIndex { compiler }).tool_path);
|
||||||
let mut dylib_paths = builder.rustc_lib_paths(compiler);
|
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);
|
add_dylib_path(dylib_paths, &mut cmd);
|
||||||
cmd
|
cmd
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -265,13 +265,27 @@ pub(crate) fn build_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Trait {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let generics = clean_ty_generics(cx, did);
|
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 }
|
clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_trait_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::TraitAlias {
|
fn build_trait_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::TraitAlias {
|
||||||
let generics = clean_ty_generics(cx, did);
|
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 }
|
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_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry};
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::{FatalError, struct_span_code_err};
|
use rustc_errors::{FatalError, struct_span_code_err};
|
||||||
use rustc_hir::PredicateOrigin;
|
|
||||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||||
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId};
|
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::hir_ty_lowering::FeedConstTy;
|
||||||
use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty};
|
use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty};
|
||||||
use rustc_middle::metadata::Reexport;
|
use rustc_middle::metadata::Reexport;
|
||||||
@@ -886,6 +886,10 @@ fn clean_ty_generics_inner<'tcx>(
|
|||||||
if b.is_sized_bound(cx) {
|
if b.is_sized_bound(cx) {
|
||||||
has_sized = true;
|
has_sized = true;
|
||||||
false
|
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 {
|
} else {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@@ -1448,6 +1452,13 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
|
|||||||
}
|
}
|
||||||
_ => true,
|
_ => 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
|
// 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
|
// 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
|
// (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,
|
_ => 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()
|
if let Some(sized) = cx.tcx.lang_items().sized_trait()
|
||||||
&& trait_ref.def_id() == sized
|
&& 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
|
// don't actually know the set of associated types right here so that
|
||||||
// should be handled when cleaning associated types.
|
// should be handled when cleaning associated types.
|
||||||
generics.where_predicates.retain(|pred| {
|
generics.where_predicates.retain(|pred| {
|
||||||
if let WP::BoundPredicate { ty: clean::Generic(param), bounds, .. } = pred
|
let WP::BoundPredicate { ty: clean::Generic(param), bounds, .. } = pred else {
|
||||||
&& bounds.iter().any(|b| b.is_sized_bound(cx))
|
return true;
|
||||||
{
|
};
|
||||||
|
|
||||||
|
if bounds.iter().any(|b| b.is_sized_bound(cx)) {
|
||||||
sized_params.insert(*param);
|
sized_params.insert(*param);
|
||||||
false
|
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 {
|
} else {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1289,11 +1289,19 @@ impl GenericBound {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
|
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(
|
if let GenericBound::TraitBound(
|
||||||
PolyTrait { ref trait_, .. },
|
PolyTrait { ref trait_, .. },
|
||||||
rustc_hir::TraitBoundModifiers::NONE,
|
rustc_hir::TraitBoundModifiers::NONE,
|
||||||
) = *self
|
) = *self
|
||||||
&& Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait()
|
&& cx.tcx.is_lang_item(trait_.def_id(), lang_item)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -388,9 +388,11 @@ fn check_other_call_arg<'tcx>(
|
|||||||
&& let (input, n_refs) = peel_middle_ty_refs(*input)
|
&& let (input, n_refs) = peel_middle_ty_refs(*input)
|
||||||
&& let (trait_predicates, _) = get_input_traits_and_projections(cx, callee_def_id, 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(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
|
&& let [trait_predicate] = trait_predicates
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|trait_predicate| trait_predicate.def_id() != sized_def_id)
|
.filter(|trait_predicate| trait_predicate.def_id() != sized_def_id)
|
||||||
|
.filter(|trait_predicate| trait_predicate.def_id() != meta_sized_def_id)
|
||||||
.collect::<Vec<_>>()[..]
|
.collect::<Vec<_>>()[..]
|
||||||
&& let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref)
|
&& 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)
|
&& let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef)
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ fn needless_borrow_count<'tcx>(
|
|||||||
) -> usize {
|
) -> usize {
|
||||||
let destruct_trait_def_id = cx.tcx.lang_items().destruct_trait();
|
let destruct_trait_def_id = cx.tcx.lang_items().destruct_trait();
|
||||||
let sized_trait_def_id = cx.tcx.lang_items().sized_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 drop_trait_def_id = cx.tcx.lang_items().drop_trait();
|
||||||
|
|
||||||
let fn_sig = cx.tcx.fn_sig(fn_id).instantiate_identity().skip_binder();
|
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| {
|
.all(|trait_def_id| {
|
||||||
Some(trait_def_id) == destruct_trait_def_id
|
Some(trait_def_id) == destruct_trait_def_id
|
||||||
|| Some(trait_def_id) == sized_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)
|
|| 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 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())
|
let preds = traits::elaborate(cx.tcx, cx.param_env.caller_bounds().iter())
|
||||||
.filter(|p| !p.is_global())
|
.filter(|p| !p.is_global())
|
||||||
.filter_map(|pred| {
|
.filter_map(|pred| {
|
||||||
// Note that we do not want to deal with qualified predicates here.
|
// Note that we do not want to deal with qualified predicates here.
|
||||||
match pred.kind().no_bound_vars() {
|
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,
|
_ => None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,8 +7,14 @@
|
|||||||
#[link(name = "c")]
|
#[link(name = "c")]
|
||||||
unsafe extern "C" {}
|
unsafe extern "C" {}
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
pub trait PointeeSized {}
|
||||||
|
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
pub trait MetaSized: PointeeSized {}
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
pub trait Sized {}
|
pub trait Sized: MetaSized {}
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
pub trait Copy {}
|
pub trait Copy {}
|
||||||
#[lang = "freeze"]
|
#[lang = "freeze"]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
|
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 {
|
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)
|
// Functions with no declared return type (i.e., the default return)
|
||||||
// have the output_type `Tuple([])`.
|
// 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()) };
|
unsafe { ffi::call::<()>(ptr, libffi_args.as_slice()) };
|
||||||
return interp_ok(ImmTy::uninit(dest.layout));
|
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
|
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
|
--> RUSTLIB/core/src/ptr/mod.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
LL | pub unsafe fn drop_in_place<T: PointeeSized>(to_drop: *mut T) {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this error occurs as part of retag at ALLOC[0x0..0x1]
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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: 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
|
= 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)
|
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
|
--> RUSTLIB/core/src/ptr/mod.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
LL | pub unsafe fn drop_in_place<T: PointeeSized>(to_drop: *mut T) {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
||||||
|
|
|
|
||||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
= 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
|
= 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)]
|
#![feature(abi_ptx, lang_items, no_core)]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
trait PointeeSized {}
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
trait MetaSized: PointeeSized {}
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized {}
|
trait Sized: MetaSized {}
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
trait Copy {}
|
trait Copy {}
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,12 @@
|
|||||||
#![feature(abi_ptx, lang_items, no_core)]
|
#![feature(abi_ptx, lang_items, no_core)]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
trait PointeeSized {}
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
trait MetaSized: PointeeSized {}
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized {}
|
trait Sized: MetaSized {}
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
trait Copy {}
|
trait Copy {}
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,12 @@
|
|||||||
#![feature(abi_ptx, lang_items, no_core)]
|
#![feature(abi_ptx, lang_items, no_core)]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
trait PointeeSized {}
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
trait MetaSized: PointeeSized {}
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized {}
|
trait Sized: MetaSized {}
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
trait Copy {}
|
trait Copy {}
|
||||||
|
|
||||||
|
|||||||
@@ -13,12 +13,16 @@
|
|||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
|
||||||
// FIXME: Migrate these code after PR #130693 is landed.
|
// 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"]
|
#[lang = "sized"]
|
||||||
trait Sized {}
|
pub trait Sized: MetaSized {}
|
||||||
|
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
trait Copy {}
|
trait Copy {}
|
||||||
|
|||||||
@@ -15,12 +15,17 @@
|
|||||||
#![no_core]
|
#![no_core]
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
// Cases where vector feature is disabled are rejected.
|
// Cases where vector feature is disabled are rejected.
|
||||||
// See tests/ui/simd-abi-checks-s390x.rs for test for them.
|
// 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"]
|
#[lang = "sized"]
|
||||||
pub trait Sized {}
|
pub trait Sized: MetaSized {}
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
pub trait Copy {}
|
pub trait Copy {}
|
||||||
#[lang = "freeze"]
|
#[lang = "freeze"]
|
||||||
|
|||||||
@@ -19,8 +19,14 @@
|
|||||||
#![no_core]
|
#![no_core]
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
pub trait PointeeSized {}
|
||||||
|
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
pub trait MetaSized: PointeeSized {}
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized {}
|
pub trait Sized: MetaSized {}
|
||||||
|
|
||||||
#[lang = "drop_in_place"]
|
#[lang = "drop_in_place"]
|
||||||
fn drop_in_place<T>(_: *mut T) {}
|
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"]
|
#[lang = "sized"]
|
||||||
pub trait Sized {}
|
pub trait Sized: MetaSized {}
|
||||||
|
|
||||||
#[lang = "legacy_receiver"]
|
#[lang = "legacy_receiver"]
|
||||||
pub trait LegacyReceiver {}
|
pub trait LegacyReceiver {}
|
||||||
impl<T: ?Sized> LegacyReceiver for &T {}
|
impl<T: PointeeSized> LegacyReceiver for &T {}
|
||||||
impl<T: ?Sized> LegacyReceiver for &mut T {}
|
impl<T: PointeeSized> LegacyReceiver for &mut T {}
|
||||||
|
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
pub trait Copy: Sized {}
|
pub trait Copy: Sized {}
|
||||||
@@ -67,14 +73,14 @@ impl_marker_trait!(
|
|||||||
f16, f32, f64, f128,
|
f16, f32, f64, f128,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
impl<'a, T: ?Sized> Copy for &'a T {}
|
impl<'a, T: PointeeSized> Copy for &'a T {}
|
||||||
impl<T: ?Sized> Copy for *const T {}
|
impl<T: PointeeSized> Copy for *const T {}
|
||||||
impl<T: ?Sized> Copy for *mut T {}
|
impl<T: PointeeSized> Copy for *mut T {}
|
||||||
impl<T: Copy, const N: usize> Copy for [T; N] {}
|
impl<T: Copy, const N: usize> Copy for [T; N] {}
|
||||||
|
|
||||||
#[lang = "phantom_data"]
|
#[lang = "phantom_data"]
|
||||||
pub struct PhantomData<T: ?Sized>;
|
pub struct PhantomData<T: PointeeSized>;
|
||||||
impl<T: ?Sized> Copy for PhantomData<T> {}
|
impl<T: PointeeSized> Copy for PhantomData<T> {}
|
||||||
|
|
||||||
pub enum Option<T> {
|
pub enum Option<T> {
|
||||||
None,
|
None,
|
||||||
@@ -90,17 +96,17 @@ impl<T: Copy, E: Copy> Copy for Result<T, E> {}
|
|||||||
|
|
||||||
#[lang = "manually_drop"]
|
#[lang = "manually_drop"]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct ManuallyDrop<T: ?Sized> {
|
pub struct ManuallyDrop<T: PointeeSized> {
|
||||||
value: T,
|
value: T,
|
||||||
}
|
}
|
||||||
impl<T: Copy + ?Sized> Copy for ManuallyDrop<T> {}
|
impl<T: Copy + PointeeSized> Copy for ManuallyDrop<T> {}
|
||||||
|
|
||||||
#[lang = "unsafe_cell"]
|
#[lang = "unsafe_cell"]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct UnsafeCell<T: ?Sized> {
|
pub struct UnsafeCell<T: PointeeSized> {
|
||||||
value: T,
|
value: T,
|
||||||
}
|
}
|
||||||
impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
|
impl<T: PointeeSized> !Freeze for UnsafeCell<T> {}
|
||||||
|
|
||||||
#[lang = "tuple_trait"]
|
#[lang = "tuple_trait"]
|
||||||
pub trait Tuple {}
|
pub trait Tuple {}
|
||||||
@@ -176,15 +182,15 @@ pub trait Fn<Args: Tuple>: FnMut<Args> {
|
|||||||
#[lang = "dispatch_from_dyn"]
|
#[lang = "dispatch_from_dyn"]
|
||||||
trait DispatchFromDyn<T> {}
|
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"]
|
#[lang = "unsize"]
|
||||||
trait Unsize<T: ?Sized> {}
|
trait Unsize<T: PointeeSized>: PointeeSized {}
|
||||||
|
|
||||||
#[lang = "coerce_unsized"]
|
#[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"]
|
#[lang = "drop"]
|
||||||
trait Drop {
|
trait Drop {
|
||||||
|
|||||||
@@ -28,8 +28,14 @@ fn panic_div_overflow() -> ! {
|
|||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
pub trait PointeeSized {}
|
||||||
|
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
pub trait MetaSized: PointeeSized {}
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized {}
|
pub trait Sized: MetaSized {}
|
||||||
|
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
trait Copy {}
|
trait Copy {}
|
||||||
|
|||||||
@@ -17,7 +17,13 @@
|
|||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized {}
|
trait Sized: MetaSized {}
|
||||||
|
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
trait MetaSized: PointeeSized {}
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
trait PointeeSized {}
|
||||||
|
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
trait Copy {}
|
trait Copy {}
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
//@ compile-flags: -C no-prepopulate-passes -Copt-level=0
|
//@ compile-flags: -C no-prepopulate-passes -Copt-level=0
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![feature(extern_types)]
|
#![feature(extern_types, sized_hierarchy)]
|
||||||
|
|
||||||
|
use std::marker::PointeeSized;
|
||||||
use std::ptr::addr_of;
|
use std::ptr::addr_of;
|
||||||
|
|
||||||
// Hack to get the correct type for usize
|
// Hack to get the correct type for usize
|
||||||
@@ -12,7 +13,7 @@ use std::ptr::addr_of;
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn helper(_: usize) {}
|
pub fn helper(_: usize) {}
|
||||||
|
|
||||||
struct Dst<T: ?Sized> {
|
struct Dst<T: PointeeSized> {
|
||||||
x: u32,
|
x: u32,
|
||||||
y: u8,
|
y: u8,
|
||||||
z: T,
|
z: T,
|
||||||
|
|||||||
@@ -9,8 +9,14 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
pub trait PointeeSized {}
|
||||||
|
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
pub trait MetaSized: PointeeSized {}
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized {}
|
pub trait Sized: MetaSized {}
|
||||||
#[lang = "freeze"]
|
#[lang = "freeze"]
|
||||||
trait Freeze {}
|
trait Freeze {}
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
|
|||||||
@@ -8,8 +8,14 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
pub trait PointeeSized {}
|
||||||
|
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
pub trait MetaSized: PointeeSized {}
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized {}
|
pub trait Sized: MetaSized {}
|
||||||
#[lang = "freeze"]
|
#[lang = "freeze"]
|
||||||
trait Freeze {}
|
trait Freeze {}
|
||||||
#[lang = "copy"]
|
#[lang = "copy"]
|
||||||
|
|||||||
@@ -15,8 +15,14 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
pub trait PointeeSized {}
|
||||||
|
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
pub trait MetaSized: PointeeSized {}
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized {}
|
pub trait Sized: MetaSized {}
|
||||||
|
|
||||||
unsafe extern "C-unwind" {
|
unsafe extern "C-unwind" {
|
||||||
safe fn unwinds();
|
safe fn unwinds();
|
||||||
|
|||||||
@@ -2,8 +2,15 @@
|
|||||||
//@ compile-flags: --target=armv7-unknown-linux-gnueabihf --crate-type=rlib -Cno-prepopulate-passes
|
//@ compile-flags: --target=armv7-unknown-linux-gnueabihf --crate-type=rlib -Cno-prepopulate-passes
|
||||||
#![no_core]
|
#![no_core]
|
||||||
#![feature(no_core, lang_items)]
|
#![feature(no_core, lang_items)]
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
pub trait PointeeSized {}
|
||||||
|
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
pub trait MetaSized: PointeeSized {}
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized {}
|
pub trait Sized: MetaSized {}
|
||||||
|
|
||||||
// Test that `nounwind` attributes are correctly applied to exported `aapcs` and
|
// Test that `nounwind` attributes are correctly applied to exported `aapcs` and
|
||||||
// `aapcs-unwind` extern functions. `aapcs-unwind` functions MUST NOT have this attribute. We
|
// `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
|
//@ compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
|
||||||
#![no_core]
|
#![no_core]
|
||||||
#![feature(no_core, lang_items)]
|
#![feature(no_core, lang_items)]
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
pub trait PointeeSized {}
|
||||||
|
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
pub trait MetaSized: PointeeSized {}
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized {}
|
pub trait Sized: MetaSized {}
|
||||||
|
|
||||||
// Test that `nounwind` attributes are correctly applied to exported `fastcall` and
|
// Test that `nounwind` attributes are correctly applied to exported `fastcall` and
|
||||||
// `fastcall-unwind` extern functions. `fastcall-unwind` functions MUST NOT have this attribute. We
|
// `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
|
//@ compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
|
||||||
#![no_core]
|
#![no_core]
|
||||||
#![feature(no_core, lang_items)]
|
#![feature(no_core, lang_items)]
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
pub trait PointeeSized {}
|
||||||
|
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
pub trait MetaSized: PointeeSized {}
|
||||||
|
|
||||||
#[lang = "sized"]
|
#[lang = "sized"]
|
||||||
trait Sized {}
|
pub trait Sized: MetaSized {}
|
||||||
|
|
||||||
// Test that `nounwind` attributes are correctly applied to exported `stdcall` and `stdcall-unwind`
|
// 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
|
// 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