about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Hewson <michael@michaelhewson.ca>2018-09-20 03:04:08 -0400
committerMichael Hewson <michael@michaelhewson.ca>2018-11-01 18:15:19 -0400
commitbe80a79a1ea247a71e5ffa408356b9b72cddb644 (patch)
tree54ccfa95c9f9bba137969d387c839b0b4f9e176d
parenta920036f4fe6403396ea05e7c70d0d87c769ff0a (diff)
downloadrust-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.rs3
-rw-r--r--src/libcore/ops/unsize.rs33
-rw-r--r--src/librustc/middle/lang_items.rs1
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;