Skip to content

Commit

Permalink
Immovable types prototype where the Move trait is builtin
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoxc committed Sep 29, 2017
1 parent a379780 commit 6d6240e
Show file tree
Hide file tree
Showing 62 changed files with 1,133 additions and 155 deletions.
16 changes: 16 additions & 0 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,7 @@ pub trait FnBox<A> {
fn call_box(self: Box<Self>, args: A) -> Self::Output;
}

#[cfg(stage0)]
#[unstable(feature = "fnbox",
reason = "will be deprecated if and when `Box<FnOnce>` becomes usable", issue = "28796")]
impl<A, F> FnBox<A> for F
Expand All @@ -729,6 +730,21 @@ impl<A, F> FnBox<A> for F
}
}

#[cfg(not(stage0))]
#[unstable(feature = "fnbox",
reason = "will be deprecated if and when `Box<FnOnce>` becomes usable", issue = "28796")]
impl<A, F> FnBox<A> for F
where F: FnOnce<A>,
<F as FnOnce<A>>::Output: marker::Move,

{
type Output = F::Output;

fn call_box(self: Box<F>, args: A) -> F::Output {
self.call_once(args)
}
}

#[unstable(feature = "fnbox",
reason = "will be deprecated if and when `Box<FnOnce>` becomes usable", issue = "28796")]
impl<'a, A, R> FnOnce<A> for Box<FnBox<A, Output = R> + 'a> {
Expand Down
1 change: 1 addition & 0 deletions src/liballoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
#![feature(slice_rsplit)]
#![feature(specialization)]
#![feature(staged_api)]
#![cfg_attr(not(stage0), feature(immovable_types))]
#![feature(str_internals)]
#![feature(trusted_len)]
#![feature(unboxed_closures)]
Expand Down
33 changes: 33 additions & 0 deletions src/libcore/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ use marker::Unsize;
use mem;
use ops::{Deref, DerefMut, CoerceUnsized};
use ptr;
#[cfg(not(stage0))]
use marker::Move;

/// A mutable memory location.
///
Expand Down Expand Up @@ -1267,3 +1269,34 @@ fn assert_coerce_unsized(a: UnsafeCell<&i32>, b: Cell<&i32>, c: RefCell<&i32>) {
let _: Cell<&Send> = b;
let _: RefCell<&Send> = c;
}

/// A cell that is always movable, even if the interior type is immovable.
/// This prevents pointers to the inner type which means it can never be observed.
#[cfg(not(stage0))]
#[unstable(feature = "immovable_types", issue = "0")]
#[lang = "movable_cell"]
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Hash, Debug)]
pub struct MovableCell<T: ?Move> {
value: T,
}

#[unstable(feature = "immovable_types", issue = "0")]
#[cfg(not(stage0))]
impl<T: ?Move> MovableCell<T> {
/// Creates a new MovableCell.
pub const fn new(value: T) -> Self {
MovableCell {
value: value,
}
}

/// Extracts the inner value.
pub fn into_inner(self) -> T {
self.value
}

/// Replaces the inner value.
pub fn replace(&mut self, new_value: T) -> T {
mem::replace(self, MovableCell::new(new_value)).into_inner()
}
}
76 changes: 76 additions & 0 deletions src/libcore/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,37 @@ use hash::Hasher;
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
#[cfg(not(stage0))]
pub unsafe trait Send: ?Move {
// empty.
}

/// docs
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
#[cfg(stage0)]
pub unsafe trait Send {
// empty.
}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl Send for .. { }

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

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

/// Types with a constant size known at compile time.
///
/// All type parameters have an implicit bound of `Sized`. The special syntax
Expand Down Expand Up @@ -90,10 +109,36 @@ impl<T: ?Sized> !Send for *mut T { }
#[lang = "sized"]
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
#[cfg(not(stage0))]
pub trait Sized: ?Move {
// Empty.
}

/// docs
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "sized"]
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
#[cfg(stage0)]
pub trait Sized {
// Empty.
}

/// Types that can be moved after being borrowed.
#[cfg(not(stage0))]
#[lang = "move"]
#[unstable(feature = "immovable_types", issue = "0")]
pub unsafe trait Move: ?Move {
// Empty.
}

/// A zero-sized struct which is immovable.
#[cfg(not(stage0))]
#[lang = "immovable"]
#[unstable(feature = "immovable_types", issue = "0")]
#[allow(missing_debug_implementations)]
pub struct Immovable;

/// 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 @@ -344,18 +389,37 @@ pub trait Copy : Clone {
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
#[cfg(not(stage0))]
pub unsafe trait Sync: ?Move {
// Empty
}

/// docs
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
#[cfg(stage0)]
pub unsafe trait Sync {
// Empty
}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl Sync for .. { }

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

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

macro_rules! impls{
($t: ident) => (
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -542,6 +606,13 @@ macro_rules! impls{
/// as not to indicate ownership.
///
/// [drop check]: ../../nomicon/dropck.html
#[cfg(not(stage0))]
#[lang = "phantom_data"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct PhantomData<T:?Sized+?Move>;

/// docs
#[cfg(stage0)]
#[lang = "phantom_data"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct PhantomData<T:?Sized>;
Expand All @@ -560,6 +631,11 @@ mod impls {
/// 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: ?Move {}

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

unsafe impl Freeze for .. {}
Expand Down
12 changes: 12 additions & 0 deletions src/libcore/nonzero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
issue = "27730")]

use ops::CoerceUnsized;
#[cfg(not(stage0))]
use marker::Move;

/// Unsafe trait to indicate what types are usable with the NonZero struct
pub unsafe trait Zeroable {
Expand All @@ -24,6 +26,7 @@ pub unsafe trait Zeroable {
macro_rules! impl_zeroable_for_pointer_types {
( $( $Ptr: ty )+ ) => {
$(
#[cfg(stage0)]
/// For fat pointers to be considered "zero", only the "data" part needs to be null.
unsafe impl<T: ?Sized> Zeroable for $Ptr {
#[inline]
Expand All @@ -32,6 +35,15 @@ macro_rules! impl_zeroable_for_pointer_types {
(*self as *mut u8).is_null()
}
}
#[cfg(not(stage0))]
/// For fat pointers to be considered "zero", only the "data" part needs to be null.
unsafe impl<T: ?Sized+?Move> Zeroable for $Ptr {
#[inline]
fn is_zero(&self) -> bool {
// Cast because `is_null` is only available on thin pointers
(*self as *mut u8).is_null()
}
}
)+
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/libcore/ops/deref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(not(stage0))]
use marker::Move;

/// Used for immutable dereferencing operations, like `*v`.
///
/// In addition to being used for explicit dereferencing operations with the
Expand Down Expand Up @@ -72,7 +75,12 @@
pub trait Deref {
/// The resulting type after dereferencing.
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(stage0)]
type Target: ?Sized;
/// The resulting type after dereferencing
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
type Target: ?Sized+?Move;

/// Dereferences the value.
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
44 changes: 44 additions & 0 deletions src/libcore/ops/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(not(stage0))]
use marker::Move;

/// The version of the call operator that takes an immutable receiver.
///
/// Instances of `Fn` can be called repeatedly without mutating state.
Expand Down Expand Up @@ -67,6 +70,18 @@
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[cfg(not(stage0))]
pub trait Fn<Args: ?Move> : FnMut<Args> {
/// This is called when the call operator is used.
#[unstable(feature = "fn_traits", issue = "29625")]
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}
/// docs
#[lang = "fn"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[cfg(stage0)]
pub trait Fn<Args> : FnMut<Args> {
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
Expand Down Expand Up @@ -140,6 +155,18 @@ pub trait Fn<Args> : FnMut<Args> {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[cfg(not(stage0))]
pub trait FnMut<Args: ?Move> : FnOnce<Args> {
/// This is called when the call operator is used.
#[unstable(feature = "fn_traits", issue = "29625")]
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}
/// docs
#[lang = "fn_mut"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[cfg(stage0)]
pub trait FnMut<Args> : FnOnce<Args> {
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
Expand Down Expand Up @@ -213,6 +240,23 @@ pub trait FnMut<Args> : FnOnce<Args> {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[cfg(not(stage0))]
pub trait FnOnce<Args: ?Move> {
/// The returned type after the call operator is used.
#[stable(feature = "fn_once_output", since = "1.12.0")]
type Output: ?Move;

/// This is called when the call operator is used.
#[unstable(feature = "fn_traits", issue = "29625")]
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}

/// docs
#[lang = "fn_once"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[cfg(stage0)]
pub trait FnOnce<Args> {
/// The returned type after the call operator is used.
#[stable(feature = "fn_once_output", since = "1.12.0")]
Expand Down
Loading

0 comments on commit 6d6240e

Please sign in to comment.