librustc: Match trait self types exactly.
This can break code that looked like:
impl Foo for Box<Any> {
fn f(&self) { ... }
}
let x: Box<Any + Send> = ...;
x.f();
Change such code to:
impl Foo for Box<Any> {
fn f(&self) { ... }
}
let x: Box<Any> = ...;
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<Any>` is no longer showable, and only `Box<Any+Send>` 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]
This commit is contained in:
@@ -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<Any> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<T: 'static>(self) -> Result<Box<T>, Self>;
|
||||
}
|
||||
|
||||
impl AnySendOwnExt for Box<Any+Send> {
|
||||
#[inline]
|
||||
fn move_send<T: 'static>(self) -> Result<Box<T>, Box<Any+Send>> {
|
||||
if self.is::<T>() {
|
||||
unsafe {
|
||||
// Get the raw representation of the trait object
|
||||
let to: TraitObject =
|
||||
*mem::transmute::<&Box<Any+Send>, &TraitObject>(&self);
|
||||
|
||||
// Prevent destructor on self being run
|
||||
intrinsics::forget(self);
|
||||
|
||||
// Extract the data pointer
|
||||
Ok(mem::transmute(to.data))
|
||||
}
|
||||
} else {
|
||||
Err(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Show> fmt::Show for Box<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
(**self).fmt(f)
|
||||
|
||||
Reference in New Issue
Block a user