Skip to content

Commit c0dc1e7

Browse files
committed
Auto merge of rust-lang#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 rust-lang#137944 (comment) Fixes rust-lang#79409. r? `@ghost` (I'll discuss this with relevant teams to find a reviewer)
2 parents 3b96c9b + 4fddff0 commit c0dc1e7

File tree

19 files changed

+294
-196
lines changed

19 files changed

+294
-196
lines changed

core/src/clone.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
3737
#![stable(feature = "rust1", since = "1.0.0")]
3838

39+
use crate::marker::PointeeSized;
40+
3941
mod uninit;
4042

4143
/// A common trait that allows explicit creation of a duplicate value.
@@ -283,7 +285,7 @@ impl_use_cloned! {
283285
reason = "deriving hack, should not be public",
284286
issue = "none"
285287
)]
286-
pub struct AssertParamIsClone<T: Clone + ?Sized> {
288+
pub struct AssertParamIsClone<T: Clone + PointeeSized> {
287289
_field: crate::marker::PhantomData<T>,
288290
}
289291
#[doc(hidden)]
@@ -293,7 +295,7 @@ pub struct AssertParamIsClone<T: Clone + ?Sized> {
293295
reason = "deriving hack, should not be public",
294296
issue = "none"
295297
)]
296-
pub struct AssertParamIsCopy<T: Copy + ?Sized> {
298+
pub struct AssertParamIsCopy<T: Copy + PointeeSized> {
297299
_field: crate::marker::PhantomData<T>,
298300
}
299301

@@ -530,6 +532,8 @@ unsafe impl CloneToUninit for crate::bstr::ByteStr {
530532
/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
531533
/// in `rustc_trait_selection`.
532534
mod impls {
535+
use crate::marker::PointeeSized;
536+
533537
macro_rules! impl_clone {
534538
($($t:ty)*) => {
535539
$(
@@ -560,15 +564,15 @@ mod impls {
560564
}
561565

562566
#[stable(feature = "rust1", since = "1.0.0")]
563-
impl<T: ?Sized> Clone for *const T {
567+
impl<T: PointeeSized> Clone for *const T {
564568
#[inline(always)]
565569
fn clone(&self) -> Self {
566570
*self
567571
}
568572
}
569573

570574
#[stable(feature = "rust1", since = "1.0.0")]
571-
impl<T: ?Sized> Clone for *mut T {
575+
impl<T: PointeeSized> Clone for *mut T {
572576
#[inline(always)]
573577
fn clone(&self) -> Self {
574578
*self
@@ -577,7 +581,7 @@ mod impls {
577581

578582
/// Shared references can be cloned, but mutable references *cannot*!
579583
#[stable(feature = "rust1", since = "1.0.0")]
580-
impl<T: ?Sized> Clone for &T {
584+
impl<T: PointeeSized> Clone for &T {
581585
#[inline(always)]
582586
#[rustc_diagnostic_item = "noop_method_clone"]
583587
fn clone(&self) -> Self {
@@ -587,5 +591,5 @@ mod impls {
587591

588592
/// Shared references can be cloned, but mutable references *cannot*!
589593
#[stable(feature = "rust1", since = "1.0.0")]
590-
impl<T: ?Sized> !Clone for &mut T {}
594+
impl<T: PointeeSized> !Clone for &mut T {}
591595
}

core/src/cmp.rs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ mod bytewise;
2929
pub(crate) use bytewise::BytewiseEq;
3030

3131
use self::Ordering::*;
32+
use crate::marker::PointeeSized;
3233
use crate::ops::ControlFlow;
3334

3435
/// Trait for comparisons using the equality operator.
@@ -246,7 +247,7 @@ use crate::ops::ControlFlow;
246247
append_const_msg
247248
)]
248249
#[rustc_diagnostic_item = "PartialEq"]
249-
pub trait PartialEq<Rhs: ?Sized = Self> {
250+
pub trait PartialEq<Rhs: PointeeSized = Self>: PointeeSized {
250251
/// Tests for `self` and `other` values to be equal, and is used by `==`.
251252
#[must_use]
252253
#[stable(feature = "rust1", since = "1.0.0")]
@@ -332,7 +333,7 @@ pub macro PartialEq($item:item) {
332333
#[doc(alias = "!=")]
333334
#[stable(feature = "rust1", since = "1.0.0")]
334335
#[rustc_diagnostic_item = "Eq"]
335-
pub trait Eq: PartialEq<Self> {
336+
pub trait Eq: PartialEq<Self> + PointeeSized {
336337
// this method is used solely by `impl Eq or #[derive(Eq)]` to assert that every component of a
337338
// type implements `Eq` itself. The current deriving infrastructure means doing this assertion
338339
// without using a method on this trait is nearly impossible.
@@ -361,7 +362,7 @@ pub macro Eq($item:item) {
361362
#[doc(hidden)]
362363
#[allow(missing_debug_implementations)]
363364
#[unstable(feature = "derive_eq", reason = "deriving hack, should not be public", issue = "none")]
364-
pub struct AssertParamIsEq<T: Eq + ?Sized> {
365+
pub struct AssertParamIsEq<T: Eq + PointeeSized> {
365366
_field: crate::marker::PhantomData<T>,
366367
}
367368

@@ -954,7 +955,7 @@ impl<T: Clone> Clone for Reverse<T> {
954955
#[doc(alias = ">=")]
955956
#[stable(feature = "rust1", since = "1.0.0")]
956957
#[rustc_diagnostic_item = "Ord"]
957-
pub trait Ord: Eq + PartialOrd<Self> {
958+
pub trait Ord: Eq + PartialOrd<Self> + PointeeSized {
958959
/// This method returns an [`Ordering`] between `self` and `other`.
959960
///
960961
/// By convention, `self.cmp(&other)` returns the ordering matching the expression
@@ -1337,7 +1338,8 @@ pub macro Ord($item:item) {
13371338
append_const_msg
13381339
)]
13391340
#[rustc_diagnostic_item = "PartialOrd"]
1340-
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
1341+
#[allow(multiple_supertrait_upcastable)] // FIXME(sized_hierarchy): remove this
1342+
pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
13411343
/// This method returns an ordering between `self` and `other` values if one exists.
13421344
///
13431345
/// # Examples
@@ -1481,7 +1483,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
14811483
}
14821484
}
14831485

1484-
fn default_chaining_impl<T: ?Sized, U: ?Sized>(
1486+
fn default_chaining_impl<T: PointeeSized, U: PointeeSized>(
14851487
lhs: &T,
14861488
rhs: &U,
14871489
p: impl FnOnce(Ordering) -> bool,
@@ -1803,6 +1805,7 @@ where
18031805
mod impls {
18041806
use crate::cmp::Ordering::{self, Equal, Greater, Less};
18051807
use crate::hint::unreachable_unchecked;
1808+
use crate::marker::PointeeSized;
18061809
use crate::ops::ControlFlow::{self, Break, Continue};
18071810

18081811
macro_rules! partial_eq_impl {
@@ -2015,7 +2018,7 @@ mod impls {
20152018
// & pointers
20162019

20172020
#[stable(feature = "rust1", since = "1.0.0")]
2018-
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &A
2021+
impl<A: PointeeSized, B: PointeeSized> PartialEq<&B> for &A
20192022
where
20202023
A: PartialEq<B>,
20212024
{
@@ -2029,7 +2032,7 @@ mod impls {
20292032
}
20302033
}
20312034
#[stable(feature = "rust1", since = "1.0.0")]
2032-
impl<A: ?Sized, B: ?Sized> PartialOrd<&B> for &A
2035+
impl<A: PointeeSized, B: PointeeSized> PartialOrd<&B> for &A
20332036
where
20342037
A: PartialOrd<B>,
20352038
{
@@ -2071,7 +2074,7 @@ mod impls {
20712074
}
20722075
}
20732076
#[stable(feature = "rust1", since = "1.0.0")]
2074-
impl<A: ?Sized> Ord for &A
2077+
impl<A: PointeeSized> Ord for &A
20752078
where
20762079
A: Ord,
20772080
{
@@ -2081,12 +2084,12 @@ mod impls {
20812084
}
20822085
}
20832086
#[stable(feature = "rust1", since = "1.0.0")]
2084-
impl<A: ?Sized> Eq for &A where A: Eq {}
2087+
impl<A: PointeeSized> Eq for &A where A: Eq {}
20852088

20862089
// &mut pointers
20872090

20882091
#[stable(feature = "rust1", since = "1.0.0")]
2089-
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &mut A
2092+
impl<A: PointeeSized, B: PointeeSized> PartialEq<&mut B> for &mut A
20902093
where
20912094
A: PartialEq<B>,
20922095
{
@@ -2100,7 +2103,7 @@ mod impls {
21002103
}
21012104
}
21022105
#[stable(feature = "rust1", since = "1.0.0")]
2103-
impl<A: ?Sized, B: ?Sized> PartialOrd<&mut B> for &mut A
2106+
impl<A: PointeeSized, B: PointeeSized> PartialOrd<&mut B> for &mut A
21042107
where
21052108
A: PartialOrd<B>,
21062109
{
@@ -2142,7 +2145,7 @@ mod impls {
21422145
}
21432146
}
21442147
#[stable(feature = "rust1", since = "1.0.0")]
2145-
impl<A: ?Sized> Ord for &mut A
2148+
impl<A: PointeeSized> Ord for &mut A
21462149
where
21472150
A: Ord,
21482151
{
@@ -2152,10 +2155,10 @@ mod impls {
21522155
}
21532156
}
21542157
#[stable(feature = "rust1", since = "1.0.0")]
2155-
impl<A: ?Sized> Eq for &mut A where A: Eq {}
2158+
impl<A: PointeeSized> Eq for &mut A where A: Eq {}
21562159

21572160
#[stable(feature = "rust1", since = "1.0.0")]
2158-
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &A
2161+
impl<A: PointeeSized, B: PointeeSized> PartialEq<&mut B> for &A
21592162
where
21602163
A: PartialEq<B>,
21612164
{
@@ -2170,7 +2173,7 @@ mod impls {
21702173
}
21712174

21722175
#[stable(feature = "rust1", since = "1.0.0")]
2173-
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &mut A
2176+
impl<A: PointeeSized, B: PointeeSized> PartialEq<&B> for &mut A
21742177
where
21752178
A: PartialEq<B>,
21762179
{

core/src/convert/mod.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
use crate::error::Error;
3939
use crate::fmt;
4040
use crate::hash::{Hash, Hasher};
41+
use crate::marker::PointeeSized;
4142

4243
mod num;
4344

@@ -215,7 +216,7 @@ pub const fn identity<T>(x: T) -> T {
215216
/// ```
216217
#[stable(feature = "rust1", since = "1.0.0")]
217218
#[rustc_diagnostic_item = "AsRef"]
218-
pub trait AsRef<T: ?Sized> {
219+
pub trait AsRef<T: PointeeSized>: PointeeSized {
219220
/// Converts this type into a shared reference of the (usually inferred) input type.
220221
#[stable(feature = "rust1", since = "1.0.0")]
221222
fn as_ref(&self) -> &T;
@@ -366,7 +367,7 @@ pub trait AsRef<T: ?Sized> {
366367
/// `&mut Vec<u8>`, for example, is the better choice (callers need to pass the correct type then).
367368
#[stable(feature = "rust1", since = "1.0.0")]
368369
#[rustc_diagnostic_item = "AsMut"]
369-
pub trait AsMut<T: ?Sized> {
370+
pub trait AsMut<T: PointeeSized>: PointeeSized {
370371
/// Converts this type into a mutable reference of the (usually inferred) input type.
371372
#[stable(feature = "rust1", since = "1.0.0")]
372373
fn as_mut(&mut self) -> &mut T;
@@ -701,7 +702,7 @@ pub trait TryFrom<T>: Sized {
701702

702703
// As lifts over &
703704
#[stable(feature = "rust1", since = "1.0.0")]
704-
impl<T: ?Sized, U: ?Sized> AsRef<U> for &T
705+
impl<T: PointeeSized, U: PointeeSized> AsRef<U> for &T
705706
where
706707
T: AsRef<U>,
707708
{
@@ -713,7 +714,7 @@ where
713714

714715
// As lifts over &mut
715716
#[stable(feature = "rust1", since = "1.0.0")]
716-
impl<T: ?Sized, U: ?Sized> AsRef<U> for &mut T
717+
impl<T: PointeeSized, U: PointeeSized> AsRef<U> for &mut T
717718
where
718719
T: AsRef<U>,
719720
{
@@ -733,7 +734,7 @@ where
733734

734735
// AsMut lifts over &mut
735736
#[stable(feature = "rust1", since = "1.0.0")]
736-
impl<T: ?Sized, U: ?Sized> AsMut<U> for &mut T
737+
impl<T: PointeeSized, U: PointeeSized> AsMut<U> for &mut T
737738
where
738739
T: AsMut<U>,
739740
{

0 commit comments

Comments
 (0)