2015-01-05 19:03:46 -06:00
|
|
|
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
|
|
|
//! Primitive traits and marker types representing basic 'kinds' of types.
|
|
|
|
//!
|
|
|
|
//! Rust types can be classified in various useful ways according to
|
|
|
|
//! intrinsic properties of the type. These classifications, often called
|
|
|
|
//! 'kinds', are represented as traits.
|
|
|
|
//!
|
|
|
|
//! They cannot be implemented by user code, but are instead implemented
|
|
|
|
//! by the compiler automatically for the types to which they apply.
|
|
|
|
//!
|
|
|
|
//! Marker types are special types that are used with unsafe code to
|
|
|
|
//! inform the compiler of special constraints. Marker types should
|
|
|
|
//! only be needed when you are creating an abstraction that is
|
|
|
|
//! implemented using unsafe code. In that case, you may want to embed
|
|
|
|
//! some of the marker types below into your type.
|
|
|
|
|
2015-01-23 23:48:20 -06:00
|
|
|
#![stable(feature = "rust1", since = "1.0.0")]
|
2015-01-05 19:03:46 -06:00
|
|
|
|
|
|
|
use clone::Clone;
|
2015-02-12 04:16:02 -06:00
|
|
|
use cmp;
|
|
|
|
use option::Option;
|
|
|
|
use hash::Hash;
|
|
|
|
use hash::Hasher;
|
2015-01-05 19:03:46 -06:00
|
|
|
|
2015-02-12 22:15:05 -06:00
|
|
|
/// Types able to be transferred across thread boundaries.
|
2015-02-18 16:30:14 -06:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2015-05-09 14:50:28 -05:00
|
|
|
#[lang = "send"]
|
2015-02-12 22:15:05 -06:00
|
|
|
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
2015-04-17 17:32:42 -05:00
|
|
|
pub unsafe trait Send {
|
|
|
|
// empty.
|
|
|
|
}
|
|
|
|
|
2015-03-11 18:53:55 -05:00
|
|
|
unsafe impl Send for .. { }
|
2015-03-08 22:02:57 -05:00
|
|
|
|
2015-01-26 14:30:56 -06:00
|
|
|
impl<T> !Send for *const T { }
|
|
|
|
impl<T> !Send for *mut T { }
|
|
|
|
|
2015-01-05 19:03:46 -06:00
|
|
|
/// Types with a constant size known at compile-time.
|
2015-01-23 23:48:20 -06:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2015-05-09 14:50:28 -05:00
|
|
|
#[lang = "sized"]
|
2015-01-20 16:04:17 -06:00
|
|
|
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
|
2015-03-30 16:52:00 -05:00
|
|
|
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
|
2015-04-17 17:32:42 -05:00
|
|
|
pub trait Sized {
|
|
|
|
// Empty.
|
|
|
|
}
|
|
|
|
|
2015-04-14 18:57:29 -05:00
|
|
|
/// Types that can be "unsized" to a dynamically sized type.
|
|
|
|
#[unstable(feature = "core")]
|
|
|
|
#[lang="unsize"]
|
|
|
|
pub trait Unsize<T> {
|
|
|
|
// Empty.
|
|
|
|
}
|
|
|
|
|
2015-01-05 19:03:46 -06:00
|
|
|
/// Types that can be copied by simply copying bits (i.e. `memcpy`).
|
2015-01-16 15:21:06 -06:00
|
|
|
///
|
|
|
|
/// By default, variable bindings have 'move semantics.' In other
|
|
|
|
/// words:
|
|
|
|
///
|
|
|
|
/// ```
|
2015-01-28 07:34:18 -06:00
|
|
|
/// #[derive(Debug)]
|
2015-01-16 15:21:06 -06:00
|
|
|
/// struct Foo;
|
|
|
|
///
|
|
|
|
/// let x = Foo;
|
|
|
|
///
|
|
|
|
/// let y = x;
|
|
|
|
///
|
|
|
|
/// // `x` has moved into `y`, and so cannot be used
|
|
|
|
///
|
|
|
|
/// // println!("{:?}", x); // error: use of moved value
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// However, if a type implements `Copy`, it instead has 'copy semantics':
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// // we can just derive a `Copy` implementation
|
2015-03-30 08:40:52 -05:00
|
|
|
/// #[derive(Debug, Copy, Clone)]
|
2015-01-16 15:21:06 -06:00
|
|
|
/// struct Foo;
|
|
|
|
///
|
|
|
|
/// let x = Foo;
|
|
|
|
///
|
|
|
|
/// let y = x;
|
|
|
|
///
|
|
|
|
/// // `y` is a copy of `x`
|
|
|
|
///
|
|
|
|
/// println!("{:?}", x); // A-OK!
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// It's important to note that in these two examples, the only difference is if you are allowed to
|
|
|
|
/// access `x` after the assignment: a move is also a bitwise copy under the hood.
|
|
|
|
///
|
|
|
|
/// ## When can my type be `Copy`?
|
|
|
|
///
|
|
|
|
/// A type can implement `Copy` if all of its components implement `Copy`. For example, this
|
|
|
|
/// `struct` can be `Copy`:
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// struct Point {
|
|
|
|
/// x: i32,
|
|
|
|
/// y: i32,
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// A `struct` can be `Copy`, and `i32` is `Copy`, so therefore, `Point` is eligible to be `Copy`.
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// # struct Point;
|
|
|
|
/// struct PointList {
|
|
|
|
/// points: Vec<Point>,
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// The `PointList` `struct` cannot implement `Copy`, because `Vec<T>` is not `Copy`. If we
|
2015-05-20 16:09:49 -05:00
|
|
|
/// attempt to derive a `Copy` implementation, we'll get an error:
|
2015-01-16 15:21:06 -06:00
|
|
|
///
|
|
|
|
/// ```text
|
2015-05-20 16:09:49 -05:00
|
|
|
/// the trait `Copy` may not be implemented for this type; field `points` does not implement `Copy`
|
2015-01-16 15:21:06 -06:00
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// ## How can I implement `Copy`?
|
|
|
|
///
|
|
|
|
/// There are two ways to implement `Copy` on your type:
|
|
|
|
///
|
|
|
|
/// ```
|
2015-03-30 08:40:52 -05:00
|
|
|
/// #[derive(Copy, Clone)]
|
2015-01-16 15:21:06 -06:00
|
|
|
/// struct MyStruct;
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// and
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// struct MyStruct;
|
|
|
|
/// impl Copy for MyStruct {}
|
2015-03-30 08:40:52 -05:00
|
|
|
/// impl Clone for MyStruct { fn clone(&self) -> MyStruct { *self } }
|
2015-01-16 15:21:06 -06:00
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// There is a small difference between the two: the `derive` strategy will also place a `Copy`
|
|
|
|
/// bound on type parameters, which isn't always desired.
|
|
|
|
///
|
|
|
|
/// ## When can my type _not_ be `Copy`?
|
|
|
|
///
|
|
|
|
/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased
|
|
|
|
/// mutable reference, and copying `String` would result in two attempts to free the same buffer.
|
|
|
|
///
|
|
|
|
/// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's
|
|
|
|
/// managing some resource besides its own `size_of::<T>()` bytes.
|
|
|
|
///
|
|
|
|
/// ## When should my type be `Copy`?
|
|
|
|
///
|
|
|
|
/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing
|
|
|
|
/// to consider though: if you think your type may _not_ be able to implement `Copy` in the future,
|
|
|
|
/// then it might be prudent to not implement `Copy`. This is because removing `Copy` is a breaking
|
|
|
|
/// change: that second example would fail to compile if we made `Foo` non-`Copy`.
|
2015-01-23 23:48:20 -06:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2015-05-09 14:50:28 -05:00
|
|
|
#[lang = "copy"]
|
2015-03-26 15:41:13 -05:00
|
|
|
pub trait Copy : Clone {
|
2015-01-05 19:03:46 -06:00
|
|
|
// Empty.
|
|
|
|
}
|
|
|
|
|
2015-01-22 03:22:16 -06:00
|
|
|
/// Types that can be safely shared between threads when aliased.
|
2015-01-05 19:03:46 -06:00
|
|
|
///
|
|
|
|
/// The precise definition is: a type `T` is `Sync` if `&T` is
|
|
|
|
/// thread-safe. In other words, there is no possibility of data races
|
2015-01-22 03:22:16 -06:00
|
|
|
/// when passing `&T` references between threads.
|
2015-01-05 19:03:46 -06:00
|
|
|
///
|
|
|
|
/// As one would expect, primitive types like `u8` and `f64` are all
|
|
|
|
/// `Sync`, and so are simple aggregate types containing them (like
|
|
|
|
/// tuples, structs and enums). More instances of basic `Sync` types
|
|
|
|
/// include "immutable" types like `&T` and those with simple
|
|
|
|
/// inherited mutability, such as `Box<T>`, `Vec<T>` and most other
|
|
|
|
/// collection types. (Generic parameters need to be `Sync` for their
|
|
|
|
/// container to be `Sync`.)
|
|
|
|
///
|
|
|
|
/// A somewhat surprising consequence of the definition is `&mut T` is
|
|
|
|
/// `Sync` (if `T` is `Sync`) even though it seems that it might
|
|
|
|
/// provide unsynchronised mutation. The trick is a mutable reference
|
|
|
|
/// stored in an aliasable reference (that is, `& &mut T`) becomes
|
|
|
|
/// read-only, as if it were a `& &T`, hence there is no risk of a data
|
|
|
|
/// race.
|
|
|
|
///
|
|
|
|
/// Types that are not `Sync` are those that have "interior
|
|
|
|
/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell`
|
|
|
|
/// in `std::cell`. These types allow for mutation of their contents
|
|
|
|
/// even when in an immutable, aliasable slot, e.g. the contents of
|
|
|
|
/// `&Cell<T>` can be `.set`, and do not ensure data races are
|
|
|
|
/// impossible, hence they cannot be `Sync`. A higher level example
|
|
|
|
/// of a non-`Sync` type is the reference counted pointer
|
|
|
|
/// `std::rc::Rc`, because any reference `&Rc<T>` can clone a new
|
|
|
|
/// reference, which modifies the reference counts in a non-atomic
|
|
|
|
/// way.
|
|
|
|
///
|
|
|
|
/// For cases when one does need thread-safe interior mutability,
|
|
|
|
/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in
|
|
|
|
/// the `sync` crate do ensure that any mutation cannot cause data
|
|
|
|
/// races. Hence these types are `Sync`.
|
|
|
|
///
|
2015-04-17 17:32:42 -05:00
|
|
|
/// Any types with interior mutability must also use the `std::cell::UnsafeCell`
|
|
|
|
/// wrapper around the value(s) which can be mutated when behind a `&`
|
|
|
|
/// reference; not doing this is undefined behaviour (for example,
|
|
|
|
/// `transmute`-ing from `&T` to `&mut T` is illegal).
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2015-05-09 14:50:28 -05:00
|
|
|
#[lang = "sync"]
|
2015-04-17 17:32:42 -05:00
|
|
|
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
|
|
|
|
pub unsafe trait Sync {
|
|
|
|
// Empty
|
|
|
|
}
|
|
|
|
|
2015-03-11 18:53:55 -05:00
|
|
|
unsafe impl Sync for .. { }
|
2015-03-08 22:02:57 -05:00
|
|
|
|
2015-01-26 14:30:56 -06:00
|
|
|
impl<T> !Sync for *const T { }
|
|
|
|
impl<T> !Sync for *mut T { }
|
|
|
|
|
2015-01-05 19:03:46 -06:00
|
|
|
/// A type which is considered "not POD", meaning that it is not
|
|
|
|
/// implicitly copyable. This is typically embedded in other types to
|
|
|
|
/// ensure that they are never copied, even if they lack a destructor.
|
2015-01-22 20:22:03 -06:00
|
|
|
#[unstable(feature = "core",
|
2015-01-12 20:40:19 -06:00
|
|
|
reason = "likely to change with new variance strategy")]
|
2015-05-09 14:50:28 -05:00
|
|
|
#[lang = "no_copy_bound"]
|
2015-01-05 19:03:46 -06:00
|
|
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
|
|
|
pub struct NoCopy;
|
|
|
|
|
2015-02-12 04:16:02 -06:00
|
|
|
macro_rules! impls{
|
|
|
|
($t: ident) => (
|
2015-02-18 17:58:07 -06:00
|
|
|
impl<T:?Sized> Hash for $t<T> {
|
|
|
|
#[inline]
|
|
|
|
fn hash<H: Hasher>(&self, _: &mut H) {
|
|
|
|
}
|
|
|
|
}
|
2015-02-12 04:16:02 -06:00
|
|
|
|
|
|
|
impl<T:?Sized> cmp::PartialEq for $t<T> {
|
|
|
|
fn eq(&self, _other: &$t<T>) -> bool {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T:?Sized> cmp::Eq for $t<T> {
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T:?Sized> cmp::PartialOrd for $t<T> {
|
|
|
|
fn partial_cmp(&self, _other: &$t<T>) -> Option<cmp::Ordering> {
|
|
|
|
Option::Some(cmp::Ordering::Equal)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T:?Sized> cmp::Ord for $t<T> {
|
|
|
|
fn cmp(&self, _other: &$t<T>) -> cmp::Ordering {
|
|
|
|
cmp::Ordering::Equal
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T:?Sized> Copy for $t<T> { }
|
|
|
|
|
|
|
|
impl<T:?Sized> Clone for $t<T> {
|
|
|
|
fn clone(&self) -> $t<T> {
|
|
|
|
$t
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2015-03-31 19:18:32 -05:00
|
|
|
/// `PhantomData<T>` allows you to describe that a type acts as if it stores a value of type `T`,
|
|
|
|
/// even though it does not. This allows you to inform the compiler about certain safety properties
|
|
|
|
/// of your code.
|
|
|
|
///
|
|
|
|
/// Though they both have scary names, `PhantomData<T>` and "phantom types" are unrelated. 👻👻👻
|
2015-02-12 04:16:02 -06:00
|
|
|
///
|
2015-03-01 22:14:45 -06:00
|
|
|
/// # Examples
|
|
|
|
///
|
2015-04-04 05:30:35 -05:00
|
|
|
/// ## Unused lifetime parameter
|
|
|
|
///
|
|
|
|
/// Perhaps the most common time that `PhantomData` is required is
|
|
|
|
/// with a struct that has an unused lifetime parameter, typically as
|
|
|
|
/// part of some unsafe code. For example, here is a struct `Slice`
|
|
|
|
/// that has two pointers of type `*const T`, presumably pointing into
|
|
|
|
/// an array somewhere:
|
|
|
|
///
|
2015-04-07 11:40:55 -05:00
|
|
|
/// ```ignore
|
2015-04-04 05:30:35 -05:00
|
|
|
/// struct Slice<'a, T> {
|
|
|
|
/// start: *const T,
|
|
|
|
/// end: *const T,
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// The intention is that the underlying data is only valid for the
|
|
|
|
/// lifetime `'a`, so `Slice` should not outlive `'a`. However, this
|
|
|
|
/// intent is not expressed in the code, since there are no uses of
|
|
|
|
/// the lifetime `'a` and hence it is not clear what data it applies
|
|
|
|
/// to. We can correct this by telling the compiler to act *as if* the
|
|
|
|
/// `Slice` struct contained a borrowed reference `&'a T`:
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::marker::PhantomData;
|
|
|
|
///
|
|
|
|
/// struct Slice<'a, T:'a> {
|
|
|
|
/// start: *const T,
|
|
|
|
/// end: *const T,
|
|
|
|
/// phantom: PhantomData<&'a T>
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// This also in turn requires that we annotate `T:'a`, indicating
|
|
|
|
/// that `T` is a type that can be borrowed for the lifetime `'a`.
|
|
|
|
///
|
|
|
|
/// ## Unused type parameters
|
|
|
|
///
|
|
|
|
/// It sometimes happens that there are unused type parameters that
|
|
|
|
/// indicate what type of data a struct is "tied" to, even though that
|
|
|
|
/// data is not actually found in the struct itself. Here is an
|
|
|
|
/// example where this arises when handling external resources over a
|
|
|
|
/// foreign function interface. `PhantomData<T>` can prevent
|
|
|
|
/// mismatches by enforcing types in the method implementations:
|
2015-03-01 22:14:45 -06:00
|
|
|
///
|
|
|
|
/// ```
|
2015-05-08 07:44:11 -05:00
|
|
|
/// # trait ResType { fn foo(&self); }
|
2015-03-01 22:14:45 -06:00
|
|
|
/// # struct ParamType;
|
|
|
|
/// # mod foreign_lib {
|
|
|
|
/// # pub fn new(_: usize) -> *mut () { 42 as *mut () }
|
|
|
|
/// # pub fn do_stuff(_: *mut (), _: usize) {}
|
|
|
|
/// # }
|
|
|
|
/// # fn convert_params(_: ParamType) -> usize { 42 }
|
|
|
|
/// use std::marker::PhantomData;
|
|
|
|
/// use std::mem;
|
|
|
|
///
|
|
|
|
/// struct ExternalResource<R> {
|
|
|
|
/// resource_handle: *mut (),
|
|
|
|
/// resource_type: PhantomData<R>,
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// impl<R: ResType> ExternalResource<R> {
|
|
|
|
/// fn new() -> ExternalResource<R> {
|
|
|
|
/// let size_of_res = mem::size_of::<R>();
|
|
|
|
/// ExternalResource {
|
|
|
|
/// resource_handle: foreign_lib::new(size_of_res),
|
|
|
|
/// resource_type: PhantomData,
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// fn do_stuff(&self, param: ParamType) {
|
|
|
|
/// let foreign_params = convert_params(param);
|
|
|
|
/// foreign_lib::do_stuff(self.resource_handle, foreign_params);
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
2015-04-04 05:30:35 -05:00
|
|
|
/// ## Indicating ownership
|
|
|
|
///
|
|
|
|
/// Adding a field of type `PhantomData<T>` also indicates that your
|
|
|
|
/// struct owns data of type `T`. This in turn implies that when your
|
|
|
|
/// struct is dropped, it may in turn drop one or more instances of
|
|
|
|
/// the type `T`, though that may not be apparent from the other
|
|
|
|
/// structure of the type itself. This is commonly necessary if the
|
|
|
|
/// structure is using an unsafe pointer like `*mut T` whose referent
|
|
|
|
/// may be dropped when the type is dropped, as a `*mut T` is
|
|
|
|
/// otherwise not treated as owned.
|
|
|
|
///
|
|
|
|
/// If your struct does not in fact *own* the data of type `T`, it is
|
|
|
|
/// better to use a reference type, like `PhantomData<&'a T>`
|
|
|
|
/// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so
|
|
|
|
/// as not to indicate ownership.
|
2015-05-09 14:50:28 -05:00
|
|
|
#[lang = "phantom_data"]
|
2015-02-18 15:38:39 -06:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2015-02-12 04:16:02 -06:00
|
|
|
pub struct PhantomData<T:?Sized>;
|
|
|
|
|
|
|
|
impls! { PhantomData }
|
|
|
|
|
2015-02-13 07:07:48 -06:00
|
|
|
mod impls {
|
|
|
|
use super::{Send, Sync, Sized};
|
|
|
|
|
|
|
|
unsafe impl<'a, T: Sync + ?Sized> Send for &'a T {}
|
|
|
|
unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
|
|
|
|
}
|
2015-02-18 16:14:27 -06:00
|
|
|
|
2015-03-24 14:55:29 -05:00
|
|
|
/// A marker trait indicates a type that can be reflected over. This
|
|
|
|
/// trait is implemented for all types. Its purpose is to ensure that
|
|
|
|
/// when you write a generic function that will employ reflection,
|
|
|
|
/// that must be reflected (no pun intended) in the generic bounds of
|
|
|
|
/// that function. Here is an example:
|
|
|
|
///
|
|
|
|
/// ```
|
2015-03-26 20:12:52 -05:00
|
|
|
/// #![feature(core)]
|
2015-03-24 14:55:29 -05:00
|
|
|
/// use std::marker::Reflect;
|
|
|
|
/// use std::any::Any;
|
|
|
|
/// fn foo<T:Reflect+'static>(x: &T) {
|
|
|
|
/// let any: &Any = x;
|
|
|
|
/// if any.is::<u32>() { println!("u32"); }
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// Without the declaration `T:Reflect`, `foo` would not type check
|
|
|
|
/// (note: as a matter of style, it would be preferable to to write
|
|
|
|
/// `T:Any`, because `T:Any` implies `T:Reflect` and `T:'static`, but
|
|
|
|
/// we use `Reflect` here to show how it works). The `Reflect` bound
|
|
|
|
/// thus serves to alert `foo`'s caller to the fact that `foo` may
|
|
|
|
/// behave differently depending on whether `T=u32` or not. In
|
|
|
|
/// particular, thanks to the `Reflect` bound, callers know that a
|
|
|
|
/// function declared like `fn bar<T>(...)` will always act in
|
|
|
|
/// precisely the same way no matter what type `T` is supplied,
|
2015-03-28 10:09:51 -05:00
|
|
|
/// because there are no bounds declared on `T`. (The ability for a
|
2015-03-24 14:55:29 -05:00
|
|
|
/// caller to reason about what a function may do based solely on what
|
|
|
|
/// generic bounds are declared is often called the ["parametricity
|
|
|
|
/// property"][1].)
|
|
|
|
///
|
|
|
|
/// [1]: http://en.wikipedia.org/wiki/Parametricity
|
|
|
|
#[rustc_reflect_like]
|
|
|
|
#[unstable(feature = "core", reason = "requires RFC and more experience")]
|
2015-03-31 18:58:15 -05:00
|
|
|
#[allow(deprecated)]
|
2015-04-24 16:34:57 -05:00
|
|
|
#[rustc_on_unimplemented = "`{Self}` does not implement `Any`; \
|
|
|
|
ensure all type parameters are bounded by `Any`"]
|
2015-04-17 17:32:42 -05:00
|
|
|
pub trait Reflect {}
|
|
|
|
|
2015-03-24 14:55:29 -05:00
|
|
|
impl Reflect for .. { }
|