diff options
| author | Michael Hewson <michael@michaelhewson.ca> | 2018-09-20 03:04:08 -0400 |
|---|---|---|
| committer | Michael Hewson <michael@michaelhewson.ca> | 2018-11-01 18:15:19 -0400 |
| commit | be80a79a1ea247a71e5ffa408356b9b72cddb644 (patch) | |
| tree | 54ccfa95c9f9bba137969d387c839b0b4f9e176d | |
| parent | a920036f4fe6403396ea05e7c70d0d87c769ff0a (diff) | |
| download | rust-be80a79a1ea247a71e5ffa408356b9b72cddb644.tar.gz rust-be80a79a1ea247a71e5ffa408356b9b72cddb644.zip | |
Add CoerceSized trait and lang item
This trait is more-or-less the reverse of CoerceUnsized, and will be used for object-safety checks. Receiver types like `Rc` will have to implement `CoerceSized` so that methods that use `Rc<Self>` as the receiver will be considered object-safe.
| -rw-r--r-- | src/libcore/ops/mod.rs | 3 | ||||
| -rw-r--r-- | src/libcore/ops/unsize.rs | 33 | ||||
| -rw-r--r-- | src/librustc/middle/lang_items.rs | 1 |
3 files changed, 36 insertions, 1 deletions
diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index ce4f45762de..bf9775e2ae8 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -201,3 +201,6 @@ pub use self::generator::{Generator, GeneratorState}; #[unstable(feature = "coerce_unsized", issue = "27732")] pub use self::unsize::CoerceUnsized; + +#[unstable(feature = "coerce_sized", issue = "0")] +pub use self::unsize::CoerceSized; diff --git a/src/libcore/ops/unsize.rs b/src/libcore/ops/unsize.rs index da72f374842..4faace26b02 100644 --- a/src/libcore/ops/unsize.rs +++ b/src/libcore/ops/unsize.rs @@ -43,7 +43,7 @@ use marker::Unsize; /// [nomicon-coerce]: ../../nomicon/coercions.html #[unstable(feature = "coerce_unsized", issue = "27732")] #[lang = "coerce_unsized"] -pub trait CoerceUnsized<T> { +pub trait CoerceUnsized<T: ?Sized> { // Empty. } @@ -77,3 +77,34 @@ impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {} // *const T -> *const U #[unstable(feature = "coerce_unsized", issue = "27732")] impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {} + + +/// Pointers to unsized types that can be coerced to a pointer to a sized type, +/// as long as pointee is actually a value of that sized type. This is used for +/// object safety, to check that a method's receiver type can be coerced from the version +/// where `Self = dyn Trait` to the version where `Self = T`, the erased, sized type +/// of the underlying object. +/// +/// CoerceSized is implemented for: +/// - &[T] is CoerceSized<&[T; N]> for any N +/// - &Trait is CoerceSized<&T> for any T: Trait +/// - and similarly for &mut T, *const T, *mut T, Box<T>, Rc<T>, Arc<T> +#[unstable(feature = "coerce_sized", issue = "0")] +#[cfg_attr(not(stage0), lang = "coerce_sized")] +pub trait CoerceSized<T> where T: CoerceUnsized<Self> { + // Empty. +} + +// &U -> &T +#[unstable(feature = "coerce_sized", issue = "0")] +impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceSized<&'a T> for &'a U {} +// &mut U -> &mut T +#[unstable(feature = "coerce_sized", issue = "0")] +impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceSized<&'a mut T> for &'a mut U {} +// *const U -> *const T +#[unstable(feature = "coerce_sized", issue = "0")] +impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceSized<*const T> for *const U {} +// *mut U -> *mut T +#[unstable(feature = "coerce_sized", issue = "0")] +impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceSized<*mut T> for *mut U {} + diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 45de958e72e..67864f67bfc 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -271,6 +271,7 @@ language_item_table! { DropTraitLangItem, "drop", drop_trait, Target::Trait; CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait, Target::Trait; + CoerceSizedTraitLangItem, "coerce_sized", coerce_sized_trait, Target::Trait; AddTraitLangItem, "add", add_trait, Target::Trait; SubTraitLangItem, "sub", sub_trait, Target::Trait; |
