Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a DynSized trait #44469

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 72 additions & 25 deletions src/libcore/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ use hash::Hasher;
/// [ub]: ../../reference/behavior-considered-undefined.html
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "send"]
#[cfg(not(stage0))]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
pub unsafe trait Send: ?DynSized {
// empty.
}

/// docs
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "send"]
#[cfg(stage0)]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
pub unsafe trait Send {
// empty.
Expand All @@ -49,9 +59,9 @@ pub unsafe trait Send {
unsafe impl Send for .. { }

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> !Send for *const T { }
impl<T: ?DynSized> !Send for *const T { }
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> !Send for *mut T { }
impl<T: ?DynSized> !Send for *mut T { }

/// Types with a constant size known at compile time.
///
Expand Down Expand Up @@ -94,6 +104,29 @@ pub trait Sized {
// Empty.
}

/// Types with a size known at run time.
///
/// This trait is implemented both by `Sized` types, and by dynamically sized
/// types such as slices and [trait objects]. [Extern types], whose size is not
/// known, even at runtime, do not implement this trait.
///
/// All traits and type parameters have an implicit bound of `DynSized`. The
/// special syntax `?DynSized` can be used to remove this bound if it's not
/// appropriate.
///
/// [trait object]: ../../book/first-edition/trait-objects.html
#[cfg(not(stage0))]
#[unstable(feature = "dynsized", issue = "0")]
#[lang = "dynsized"]
#[rustc_on_unimplemented = "`{Self}` does not have a size known at run-time"]
#[fundamental]
pub trait DynSized: ?DynSized {
// Empty.
}

#[cfg(stage0)]
use self::Sized as DynSized; // This is just so we don't have to stage too much stuff

/// Types that can be "unsized" to a dynamically-sized type.
///
/// For example, the sized array type `[i8; 2]` implements `Unsize<[i8]>` and
Expand Down Expand Up @@ -343,6 +376,16 @@ pub trait Copy : Clone {
/// [transmute]: ../../std/mem/fn.transmute.html
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "sync"]
#[cfg(not(stage0))]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
pub unsafe trait Sync: ?DynSized {
// Empty
}

/// docs
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "sync"]
#[cfg(stage0)]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
pub unsafe trait Sync {
// Empty
Expand All @@ -352,56 +395,56 @@ pub unsafe trait Sync {
unsafe impl Sync for .. { }

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> !Sync for *const T { }
impl<T: ?DynSized> !Sync for *const T { }
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> !Sync for *mut T { }
impl<T: ?DynSized> !Sync for *mut T { }

macro_rules! impls{
($t: ident) => (
#[stable(feature = "rust1", since = "1.0.0")]
impl<T:?Sized> Hash for $t<T> {
impl<T:?DynSized> Hash for $t<T> {
#[inline]
fn hash<H: Hasher>(&self, _: &mut H) {
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T:?Sized> cmp::PartialEq for $t<T> {
impl<T:?DynSized> cmp::PartialEq for $t<T> {
fn eq(&self, _other: &$t<T>) -> bool {
true
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T:?Sized> cmp::Eq for $t<T> {
impl<T:?DynSized> cmp::Eq for $t<T> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T:?Sized> cmp::PartialOrd for $t<T> {
impl<T:?DynSized> cmp::PartialOrd for $t<T> {
fn partial_cmp(&self, _other: &$t<T>) -> Option<cmp::Ordering> {
Option::Some(cmp::Ordering::Equal)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T:?Sized> cmp::Ord for $t<T> {
impl<T:?DynSized> cmp::Ord for $t<T> {
fn cmp(&self, _other: &$t<T>) -> cmp::Ordering {
cmp::Ordering::Equal
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T:?Sized> Copy for $t<T> { }
impl<T:?DynSized> Copy for $t<T> { }

#[stable(feature = "rust1", since = "1.0.0")]
impl<T:?Sized> Clone for $t<T> {
impl<T:?DynSized> Clone for $t<T> {
fn clone(&self) -> $t<T> {
$t
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T:?Sized> Default for $t<T> {
impl<T:?DynSized> Default for $t<T> {
fn default() -> $t<T> {
$t
}
Expand Down Expand Up @@ -544,29 +587,33 @@ macro_rules! impls{
/// [drop check]: ../../nomicon/dropck.html
#[lang = "phantom_data"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct PhantomData<T:?Sized>;
pub struct PhantomData<T:?DynSized>;

impls! { PhantomData }

mod impls {
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<'a, T: Sync + ?Sized> Send for &'a T {}
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
}
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<'a, T: Sync + ?DynSized> Send for &'a T {}
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<'a, T: Send + ?DynSized> Send for &'a mut T {}

/// Compiler-internal trait used to determine whether a type contains
/// any `UnsafeCell` internally, but not through an indirection.
/// This affects, for example, whether a `static` of that type is
/// placed in read-only static memory or writable static memory.
#[lang = "freeze"]
#[cfg(not(stage0))]
unsafe trait Freeze: ?DynSized {}

/// docs
#[lang = "freeze"]
#[cfg(stage0)]
unsafe trait Freeze {}

unsafe impl Freeze for .. {}

impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
unsafe impl<T: ?Sized> Freeze for PhantomData<T> {}
unsafe impl<T: ?Sized> Freeze for *const T {}
unsafe impl<T: ?Sized> Freeze for *mut T {}
unsafe impl<'a, T: ?Sized> Freeze for &'a T {}
unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
impl<T: ?DynSized> !Freeze for UnsafeCell<T> {}
unsafe impl<T: ?DynSized> Freeze for PhantomData<T> {}
unsafe impl<T: ?DynSized> Freeze for *const T {}
unsafe impl<T: ?DynSized> Freeze for *mut T {}
unsafe impl<'a, T: ?DynSized> Freeze for &'a T {}
unsafe impl<'a, T: ?DynSized> Freeze for &'a mut T {}
27 changes: 17 additions & 10 deletions src/libcore/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ use nonzero::NonZero;

use cmp::Ordering::{self, Less, Equal, Greater};

#[cfg(stage0)]
use marker::Sized as DynSized;
#[cfg(not(stage0))]
use marker::DynSized;

// FIXME #19649: intrinsic docs don't render, so these have no docs :(

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -58,7 +63,7 @@ pub use intrinsics::write_bytes;
#[stable(feature = "drop_in_place", since = "1.8.0")]
#[lang="drop_in_place"]
#[allow(unconditional_recursion)]
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
pub unsafe fn drop_in_place<T: ?DynSized>(to_drop: *mut T) {
// Code here does not matter - this is replaced by the
// real drop glue by the compiler.
drop_in_place(to_drop);
Expand Down Expand Up @@ -473,7 +478,7 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
}

#[lang = "const_ptr"]
impl<T: ?Sized> *const T {
impl<T: ?DynSized> *const T {
/// Returns `true` if the pointer is null.
///
/// # Examples
Expand All @@ -487,8 +492,9 @@ impl<T: ?Sized> *const T {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_null(self) -> bool where T: Sized {
self == null()
pub fn is_null(self) -> bool {
// cast to () pointer, as T may not be sized
self as *const () == null()
}

/// Returns `None` if the pointer is null, or else returns a reference to
Expand Down Expand Up @@ -519,7 +525,7 @@ impl<T: ?Sized> *const T {
/// ```
#[stable(feature = "ptr_as_ref", since = "1.9.0")]
#[inline]
pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized {
pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
if self.is_null() {
None
} else {
Expand Down Expand Up @@ -1104,7 +1110,7 @@ impl<T: ?Sized> *const T {
}

#[lang = "mut_ptr"]
impl<T: ?Sized> *mut T {
impl<T: ?DynSized> *mut T {
/// Returns `true` if the pointer is null.
///
/// # Examples
Expand All @@ -1118,8 +1124,9 @@ impl<T: ?Sized> *mut T {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_null(self) -> bool where T: Sized {
self == null_mut()
pub fn is_null(self) -> bool {
// cast to () pointer, as T may not be sized
self as *mut () == null_mut()
}

/// Returns `None` if the pointer is null, or else returns a reference to
Expand Down Expand Up @@ -1150,7 +1157,7 @@ impl<T: ?Sized> *mut T {
/// ```
#[stable(feature = "ptr_as_ref", since = "1.9.0")]
#[inline]
pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized {
pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
if self.is_null() {
None
} else {
Expand Down Expand Up @@ -1274,7 +1281,7 @@ impl<T: ?Sized> *mut T {
/// ```
#[stable(feature = "ptr_as_ref", since = "1.9.0")]
#[inline]
pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> where T: Sized {
pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
if self.is_null() {
None
} else {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ define_dep_nodes!( <'tcx>
[] IsForeignItem(DefId),
[] TypeParamPredicates { item_id: DefId, param_id: DefId },
[] SizedConstraint(DefId),
[] DynSizedConstraint(DefId),
[] DtorckConstraint(DefId),
[] AdtDestructor(DefId),
[] AssociatedItemDefIds(DefId),
Expand All @@ -492,6 +493,7 @@ define_dep_nodes!( <'tcx>

[anon] IsCopy,
[anon] IsSized,
[anon] IsDynSized,
[anon] IsFreeze,
[anon] NeedsDrop,
[anon] Layout,
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/hir/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub enum Def {
Variant(DefId),
Trait(DefId),
TyAlias(DefId),
TyForeign(DefId),
AssociatedTy(DefId),
PrimTy(hir::PrimTy),
TyParam(DefId),
Expand Down Expand Up @@ -152,7 +153,7 @@ impl Def {
Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
Def::AssociatedConst(id) | Def::Macro(id, ..) |
Def::GlobalAsm(id) => {
Def::GlobalAsm(id) | Def::TyForeign(id) => {
id
}

Expand Down Expand Up @@ -186,6 +187,7 @@ impl Def {
Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
Def::Union(..) => "union",
Def::Trait(..) => "trait",
Def::TyForeign(..) => "foreign type",
Def::Method(..) => "method",
Def::Const(..) => "constant",
Def::AssociatedConst(..) => "associated constant",
Expand Down
1 change: 1 addition & 0 deletions src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v
}
}
ForeignItemStatic(ref typ, _) => visitor.visit_ty(typ),
ForeignItemType => (),
}

walk_list!(visitor, visit_attribute, &foreign_item.attrs);
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1715,6 +1715,9 @@ impl<'a> LoweringContext<'a> {
ForeignItemKind::Static(ref t, m) => {
hir::ForeignItemStatic(this.lower_ty(t), m)
}
ForeignItemKind::Ty => {
hir::ForeignItemType
}
},
vis: this.lower_visibility(&i.vis, None),
span: i.span,
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1904,13 +1904,16 @@ pub enum ForeignItem_ {
/// A foreign static item (`static ext: u8`), with optional mutability
/// (the boolean is true when mutable)
ForeignItemStatic(P<Ty>, bool),
/// A foreign type
ForeignItemType,
}

impl ForeignItem_ {
pub fn descriptive_variant(&self) -> &str {
match *self {
ForeignItemFn(..) => "foreign function",
ForeignItemStatic(..) => "foreign static item",
ForeignItemType => "foreign type",
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,13 @@ impl<'a> State<'a> {
self.end()?; // end the head-ibox
self.end() // end the outer cbox
}
hir::ForeignItemType => {
self.head(&visibility_qualified(&item.vis, "type"))?;
self.print_name(item.name)?;
self.s.word(";")?;
self.end()?; // end the head-ibox
self.end() // end the outer cbox
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/librustc/ich/impls_hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -968,7 +968,8 @@ impl_stable_hash_for!(struct hir::ForeignItem {

impl_stable_hash_for!(enum hir::ForeignItem_ {
ForeignItemFn(fn_decl, arg_names, generics),
ForeignItemStatic(ty, is_mutbl)
ForeignItemStatic(ty, is_mutbl),
ForeignItemType
});

impl_stable_hash_for!(enum hir::Stmt_ {
Expand Down Expand Up @@ -1077,6 +1078,7 @@ impl_stable_hash_for!(enum hir::def::Def {
PrimTy(prim_ty),
TyParam(def_id),
SelfTy(trait_def_id, impl_def_id),
TyForeign(def_id),
Fn(def_id),
Const(def_id),
Static(def_id, is_mutbl),
Expand Down
Loading