From 9c9bb9ce1d51e2a9ca4963bd418e365b6e17fbfa Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 24 Mar 2015 15:55:29 -0400 Subject: Implement `Reflect` trait with a variant on the standard OIBIT semantics that tests the *interface* of trait objects, rather than what they close over. --- src/libcore/any.rs | 24 +++++++++++++----------- src/libcore/lib.rs | 1 + src/libcore/marker.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 11 deletions(-) (limited to 'src/libcore') diff --git a/src/libcore/any.rs b/src/libcore/any.rs index c94d8e2ed0c..d3bc07b173a 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -55,7 +55,7 @@ //! } //! //! // This function wants to log its parameter out prior to doing work with it. -//! fn do_work(value: &T) { +//! fn do_work(value: &T) { //! log(value); //! // ...do some other work //! } @@ -76,7 +76,7 @@ use mem::transmute; use option::Option::{self, Some, None}; use raw::TraitObject; use intrinsics; -use marker::Sized; +use marker::{Reflect, Sized}; /////////////////////////////////////////////////////////////////////////////// // Any trait @@ -88,14 +88,16 @@ use marker::Sized; /// /// [mod]: ../index.html #[stable(feature = "rust1", since = "1.0.0")] -pub trait Any: 'static { +pub trait Any: Reflect + 'static { /// Get the `TypeId` of `self` #[unstable(feature = "core", reason = "this method will likely be replaced by an associated static")] fn get_type_id(&self) -> TypeId; } -impl Any for T { +impl Any for T + where T: Reflect + 'static +{ fn get_type_id(&self) -> TypeId { TypeId::of::() } } @@ -107,7 +109,7 @@ impl Any { /// Returns true if the boxed type is the same as `T` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn is(&self) -> bool { + pub fn is(&self) -> bool { // Get TypeId of the type this function is instantiated with let t = TypeId::of::(); @@ -122,7 +124,7 @@ impl Any { /// `None` if it isn't. #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn downcast_ref(&self) -> Option<&T> { + pub fn downcast_ref(&self) -> Option<&T> { if self.is::() { unsafe { // Get the raw representation of the trait object @@ -140,7 +142,7 @@ impl Any { /// `None` if it isn't. #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn downcast_mut(&mut self) -> Option<&mut T> { + pub fn downcast_mut(&mut self) -> Option<&mut T> { if self.is::() { unsafe { // Get the raw representation of the trait object @@ -159,21 +161,21 @@ impl Any+Send { /// Forwards to the method defined on the type `Any`. #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn is(&self) -> bool { + pub fn is(&self) -> bool { Any::is::(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn downcast_ref(&self) -> Option<&T> { + pub fn downcast_ref(&self) -> Option<&T> { Any::downcast_ref::(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn downcast_mut(&mut self) -> Option<&mut T> { + pub fn downcast_mut(&mut self) -> Option<&mut T> { Any::downcast_mut::(self) } } @@ -202,7 +204,7 @@ impl TypeId { /// instantiated with #[unstable(feature = "core", reason = "may grow a `Reflect` bound soon via marker traits")] - pub fn of() -> TypeId { + pub fn of() -> TypeId { TypeId { t: unsafe { intrinsics::type_id::() }, } diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index a2b13584270..7225b016e6b 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -72,6 +72,7 @@ #![feature(rustc_attrs)] #![feature(optin_builtin_traits)] #![feature(concat_idents)] +#![feature(reflect)] #[macro_use] mod macros; diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 88c10e3661e..26bb53c6b2d 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -450,3 +450,45 @@ pub struct CovariantType; #[deprecated(since = "1.0.0", reason = "Replace with `PhantomData>`")] #[lang="invariant_type"] pub struct InvariantType; + +/// 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: +/// +/// ``` +/// use std::marker::Reflect; +/// use std::any::Any; +/// fn foo(x: &T) { +/// let any: &Any = x; +/// if any.is::() { 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(...)` will always act in +/// precisely the same way no matter what type `T` is supplied, +/// beacuse there are no bounds declared on `T`. (The ability for a +/// 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")] +pub trait Reflect : MarkerTrait { +} + +#[cfg(stage0)] +impl Reflect for T { } + +#[cfg(not(stage0))] +impl Reflect for .. { } + -- cgit 1.4.1-3-g733a5 From dd8cf9238940b7b0dc54cc05d0788d8d7282aa27 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 26 Mar 2015 21:12:52 -0400 Subject: Fix doc tests. --- src/libcore/marker.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/libcore') diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 26bb53c6b2d..35fde2cb64a 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -458,6 +458,7 @@ pub struct InvariantType; /// that function. Here is an example: /// /// ``` +/// #![feature(core)] /// use std::marker::Reflect; /// use std::any::Any; /// fn foo(x: &T) { -- cgit 1.4.1-3-g733a5