From 05e3248a7974f55b64f75a2483b37ff8c001a4ff Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 25 Jun 2014 18:18:13 -0700 Subject: librustc: Match trait self types exactly. This can break code that looked like: impl Foo for Box { fn f(&self) { ... } } let x: Box = ...; x.f(); Change such code to: impl Foo for Box { fn f(&self) { ... } } let x: Box = ...; x.f(); That is, upcast before calling methods. This is a conservative solution to #5781. A more proper treatment (see the xfail'd `trait-contravariant-self.rs`) would take variance into account. This change fixes the soundness hole. Some library changes had to be made to make this work. In particular, `Box` is no longer showable, and only `Box` is showable. Eventually, this restriction can be lifted; for now, it does not prove too onerous, because `Any` is only used for propagating the result of task failure. This patch also adds a test for the variance inference work in #12828, which accidentally landed as part of DST. Closes #5781. [breaking-change] --- src/liballoc/owned.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'src/liballoc') diff --git a/src/liballoc/owned.rs b/src/liballoc/owned.rs index 6f5d3293556..94b8bee8cc9 100644 --- a/src/liballoc/owned.rs +++ b/src/liballoc/owned.rs @@ -16,6 +16,7 @@ use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering}; use core::default::Default; use core::fmt; use core::intrinsics; +use core::kinds::Send; use core::mem; use core::raw::TraitObject; use core::result::{Ok, Err, Result}; @@ -106,6 +107,34 @@ impl AnyOwnExt for Box { } } +/// Extension methods for an owning `Any+Send` trait object +pub trait AnySendOwnExt { + /// Returns the boxed value if it is of type `T`, or + /// `Err(Self)` if it isn't. + fn move_send(self) -> Result, Self>; +} + +impl AnySendOwnExt for Box { + #[inline] + fn move_send(self) -> Result, Box> { + if self.is::() { + unsafe { + // Get the raw representation of the trait object + let to: TraitObject = + *mem::transmute::<&Box, &TraitObject>(&self); + + // Prevent destructor on self being run + intrinsics::forget(self); + + // Extract the data pointer + Ok(mem::transmute(to.data)) + } + } else { + Err(self) + } + } +} + impl fmt::Show for Box { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) -- cgit 1.4.1-3-g733a5