about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-10-30 06:32:11 +0000
committerbors <bors@rust-lang.org>2014-10-30 06:32:11 +0000
commit2d27bfaeb6522d386d0a2735cb3f75cc5707314a (patch)
tree0b27f013ab6f65b62150aed544c1a98f561792c6
parentd1fc2dec79689fe6bd37c95f3fe5b7acd476fff6 (diff)
parent88a250d194d7a7995c0740d706d9eb19007a85ee (diff)
downloadrust-2d27bfaeb6522d386d0a2735cb3f75cc5707314a.tar.gz
rust-2d27bfaeb6522d386d0a2735cb3f75cc5707314a.zip
auto merge of #17704 : nick29581/rust/object-safety, r=nikomatsakis
r? @nikomatsakis 
-rw-r--r--src/librustc/diagnostics.rs1
-rw-r--r--src/librustc/middle/typeck/check/method.rs88
-rw-r--r--src/librustc/middle/typeck/check/mod.rs1
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs105
-rw-r--r--src/libstd/io/extensions.rs2
-rw-r--r--src/libstd/io/mod.rs50
-rw-r--r--src/libstd/io/util.rs2
-rw-r--r--src/libterm/lib.rs63
-rw-r--r--src/libterm/terminfo/mod.rs91
-rw-r--r--src/libterm/win.rs44
-rw-r--r--src/test/compile-fail/region-object-lifetime-in-coercion.rs15
-rw-r--r--src/test/compile-fail/selftype-traittype.rs20
-rw-r--r--src/test/compile-fail/trait-objects.rs43
-rw-r--r--src/test/compile-fail/trait-test-2.rs2
-rw-r--r--src/test/run-fail/by-value-self-objects-fail.rs51
-rw-r--r--src/test/run-pass/by-value-self-objects.rs77
-rw-r--r--src/test/run-pass/issue-11267.rs7
-rw-r--r--src/test/run-pass/issue-15763.rs8
-rw-r--r--src/test/run-pass/trait-cast-generic.rs30
-rw-r--r--src/test/run-pass/trait-default-method-xc.rs3
20 files changed, 309 insertions, 394 deletions
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index f405e9df51d..c4e21379088 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -53,7 +53,6 @@ register_diagnostics!(
     E0035,
     E0036,
     E0038,
-    E0039,
     E0040,
     E0044,
     E0045,
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 7527160c825..cd3cc43b853 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -619,14 +619,12 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
 
         let tcx = self.tcx();
 
-        // It is illegal to invoke a method on a trait instance that
-        // refers to the `Self` type. An error will be reported by
-        // `enforce_object_limitations()` if the method refers to the
-        // `Self` type anywhere other than the receiver. Here, we use
-        // a substitution that replaces `Self` with the object type
-        // itself. Hence, a `&self` method will wind up with an
-        // argument type like `&Trait`.
+        // It is illegal to invoke a method on a trait instance that refers to
+        // the `Self` type.  Here, we use a substitution that replaces `Self`
+        // with the object type itself. Hence, a `&self` method will wind up
+        // with an argument type like `&Trait`.
         let rcvr_substs = substs.with_self_ty(self_ty);
+
         let trait_ref = Rc::new(TraitRef {
             def_id: did,
             substs: rcvr_substs.clone()
@@ -1336,16 +1334,7 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
                self.ty_to_string(rcvr_ty),
                candidate.repr(self.tcx()));
 
-        let mut rcvr_substs = candidate.rcvr_substs.clone();
-
-        if !self.enforce_object_limitations(candidate) {
-            // Here we change `Self` from `Trait` to `err` in the case that
-            // this is an illegal object method. This is necessary to prevent
-            // the user from getting strange, derivative errors when the method
-            // takes an argument/return-type of type `Self` etc.
-            rcvr_substs.types.get_mut_slice(SelfSpace)[0] = ty::mk_err();
-        }
-
+        let rcvr_substs = candidate.rcvr_substs.clone();
         self.enforce_drop_trait_limitations(candidate);
 
         // Determine the values for the generic parameters of the method.
@@ -1554,71 +1543,6 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
         }
     }
 
-    fn enforce_object_limitations(&self, candidate: &Candidate) -> bool {
-        /*!
-         * There are some limitations to calling functions through an
-         * object, because (a) the self type is not known
-         * (that's the whole point of a trait instance, after all, to
-         * obscure the self type) and (b) the call must go through a
-         * vtable and hence cannot be monomorphized.
-         */
-
-        match candidate.origin {
-            MethodStatic(..) |
-            MethodTypeParam(..) |
-            MethodStaticUnboxedClosure(..) => {
-                return true; // not a call to a trait instance
-            }
-            MethodTraitObject(..) => {}
-        }
-
-        match candidate.method_ty.explicit_self {
-            ty::StaticExplicitSelfCategory => { // reason (a) above
-                self.tcx().sess.span_err(
-                    self.span,
-                    "cannot call a method without a receiver \
-                     through an object");
-                return false;
-            }
-
-            ty::ByValueExplicitSelfCategory |
-            ty::ByReferenceExplicitSelfCategory(..) |
-            ty::ByBoxExplicitSelfCategory => {}
-        }
-
-        // reason (a) above
-        let check_for_self_ty = |ty| -> bool {
-            if ty::type_has_self(ty) {
-                span_err!(self.tcx().sess, self.span, E0038,
-                    "cannot call a method whose type contains a \
-                     self-type through an object");
-                false
-            } else {
-                true
-            }
-        };
-        let ref sig = candidate.method_ty.fty.sig;
-        for &input_ty in sig.inputs[1..].iter() {
-            if !check_for_self_ty(input_ty) {
-                return false;
-            }
-        }
-        if let ty::FnConverging(result_type) = sig.output {
-            if !check_for_self_ty(result_type) {
-                return false;
-            }
-        }
-
-        if candidate.method_ty.generics.has_type_params(subst::FnSpace) {
-            // reason (b) above
-            span_err!(self.tcx().sess, self.span, E0039,
-                "cannot call a generic method through an object");
-            return false;
-        }
-
-        true
-    }
-
     fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
         // No code can call the finalize method explicitly.
         let bad = match candidate.origin {
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 8843be3cf81..94c4d7c25e0 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -1687,6 +1687,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.register_unsize_obligations(span, &**u)
             }
             ty::UnsizeVtable(ref ty_trait, self_ty) => {
+                vtable::check_object_safety(self.tcx(), ty_trait, span);
                 // If the type is `Foo+'a`, ensures that the type
                 // being cast to `Foo+'a` implements `Foo`:
                 vtable::register_object_cast_obligations(self,
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index a5624dcc2fc..b7195734e8b 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use middle::subst::{SelfSpace};
+use middle::subst::{SelfSpace, FnSpace};
 use middle::traits;
 use middle::traits::{SelectionError, OutputTypeParameterMismatch, Overflow, Unimplemented};
 use middle::traits::{Obligation, obligation_for_builtin_bound};
@@ -21,8 +21,7 @@ use middle::typeck::infer;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::codemap::Span;
-use util::ppaux::UserString;
-use util::ppaux::Repr;
+use util::ppaux::{UserString, Repr, ty_to_string};
 
 pub fn check_object_cast(fcx: &FnCtxt,
                          cast_expr: &ast::Expr,
@@ -46,6 +45,7 @@ pub fn check_object_cast(fcx: &FnCtxt,
 
             // Ensure that if ~T is cast to ~Trait, then T : Trait
             push_cast_obligation(fcx, cast_expr, object_trait, referent_ty);
+            check_object_safety(fcx.tcx(), object_trait, source_expr.span);
         }
 
         (&ty::ty_rptr(referent_region, ty::mt { ty: referent_ty,
@@ -68,6 +68,8 @@ pub fn check_object_cast(fcx: &FnCtxt,
                                infer::RelateObjectBound(source_expr.span),
                                target_region,
                                referent_region);
+
+                check_object_safety(fcx.tcx(), object_trait, source_expr.span);
             }
         }
 
@@ -128,6 +130,103 @@ pub fn check_object_cast(fcx: &FnCtxt,
     }
 }
 
+// Check that a trait is 'object-safe'. This should be checked whenever a trait object
+// is created (by casting or coercion, etc.). A trait is object-safe if all its
+// methods are object-safe. A trait method is object-safe if it does not take
+// self by value, has no type parameters and does not use the `Self` type, except
+// in self position.
+pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Span) {
+    // Skip the fn_once lang item trait since only the compiler should call
+    // `call_once` which is the method which takes self by value. What could go
+    // wrong?
+    match tcx.lang_items.fn_once_trait() {
+        Some(def_id) if def_id == object_trait.def_id => return,
+        _ => {}
+    }
+
+    let trait_items = ty::trait_items(tcx, object_trait.def_id);
+
+    let mut errors = Vec::new();
+    for item in trait_items.iter() {
+        match *item {
+            ty::MethodTraitItem(ref m) => {
+                errors.push(check_object_safety_of_method(tcx, &**m))
+            }
+            ty::TypeTraitItem(_) => {}
+        }
+    }
+
+    let mut errors = errors.iter().flat_map(|x| x.iter()).peekable();
+    if errors.peek().is_some() {
+        let trait_name = ty::item_path_str(tcx, object_trait.def_id);
+        span_err!(tcx.sess, span, E0038,
+            "cannot convert to a trait object because trait `{}` is not object-safe",
+            trait_name);
+
+        for msg in errors {
+            tcx.sess.note(msg.as_slice());
+        }
+    }
+
+    // Returns a vec of error messages. If hte vec is empty - no errors!
+    fn check_object_safety_of_method(tcx: &ty::ctxt, method: &ty::Method) -> Vec<String> {
+        /*!
+         * There are some limitations to calling functions through an
+         * object, because (a) the self type is not known
+         * (that's the whole point of a trait instance, after all, to
+         * obscure the self type) and (b) the call must go through a
+         * vtable and hence cannot be monomorphized.
+         */
+        let mut msgs = Vec::new();
+
+        let method_name = method.name.repr(tcx);
+
+        match method.explicit_self {
+            ty::ByValueExplicitSelfCategory => { // reason (a) above
+                msgs.push(format!("cannot call a method (`{}`) with a by-value \
+                                   receiver through a trait object", method_name))
+            }
+
+            ty::StaticExplicitSelfCategory |
+            ty::ByReferenceExplicitSelfCategory(..) |
+            ty::ByBoxExplicitSelfCategory => {}
+        }
+
+        // reason (a) above
+        let check_for_self_ty = |ty| {
+            if ty::type_has_self(ty) {
+                Some(format!(
+                    "cannot call a method (`{}`) whose type contains \
+                     a self-type (`{}`) through a trait object",
+                    method_name, ty_to_string(tcx, ty)))
+            } else {
+                None
+            }
+        };
+        let ref sig = method.fty.sig;
+        for &input_ty in sig.inputs[1..].iter() {
+            match check_for_self_ty(input_ty) {
+                Some(msg) => msgs.push(msg),
+                _ => {}
+            }
+        }
+        if let ty::FnConverging(result_type) = sig.output {
+            match check_for_self_ty(result_type) {
+                Some(msg) => msgs.push(msg),
+                _ => {}
+            }
+        }
+
+        if method.generics.has_type_params(FnSpace) {
+            // reason (b) above
+            msgs.push(format!("cannot call a generic method (`{}`) through a trait object",
+                              method_name));
+        }
+
+        msgs
+    }
+}
+
 pub fn register_object_cast_obligations(fcx: &FnCtxt,
                                         span: Span,
                                         object_trait: &ty::TyTrait,
diff --git a/src/libstd/io/extensions.rs b/src/libstd/io/extensions.rs
index a595921fcf7..078a9a014c9 100644
--- a/src/libstd/io/extensions.rs
+++ b/src/libstd/io/extensions.rs
@@ -172,7 +172,7 @@ pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 {
 mod test {
     use prelude::*;
     use io;
-    use io::{MemReader, MemWriter};
+    use io::{MemReader, MemWriter, BytesReader};
 
     struct InitialZeroByteReader {
         count: int,
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 7826a6dd9c6..d22650107a3 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -712,17 +712,6 @@ pub trait Reader {
         })
     }
 
-    /// Create an iterator that reads a single byte on
-    /// each iteration, until EOF.
-    ///
-    /// # Error
-    ///
-    /// Any error other than `EndOfFile` that is produced by the underlying Reader
-    /// is returned by the iterator and should be handled by the caller.
-    fn bytes<'r>(&'r mut self) -> extensions::Bytes<'r, Self> {
-        extensions::Bytes::new(self)
-    }
-
     // Byte conversion helpers
 
     /// Reads `n` little-endian unsigned integer bytes.
@@ -932,16 +921,41 @@ pub trait Reader {
     fn read_i8(&mut self) -> IoResult<i8> {
         self.read_byte().map(|i| i as i8)
     }
+}
 
+/// A reader which can be converted to a RefReader.
+pub trait AsRefReader {
     /// Creates a wrapper around a mutable reference to the reader.
     ///
     /// This is useful to allow applying adaptors while still
     /// retaining ownership of the original value.
-    fn by_ref<'a>(&'a mut self) -> RefReader<'a, Self> {
+    fn by_ref<'a>(&'a mut self) -> RefReader<'a, Self>;
+}
+
+impl<T: Reader> AsRefReader for T {
+    fn by_ref<'a>(&'a mut self) -> RefReader<'a, T> {
         RefReader { inner: self }
     }
 }
 
+/// A reader which can be converted to bytes.
+pub trait BytesReader {
+    /// Create an iterator that reads a single byte on
+    /// each iteration, until EOF.
+    ///
+    /// # Error
+    ///
+    /// Any error other than `EndOfFile` that is produced by the underlying Reader
+    /// is returned by the iterator and should be handled by the caller.
+    fn bytes<'r>(&'r mut self) -> extensions::Bytes<'r, Self>;
+}
+
+impl<T: Reader> BytesReader for T {
+    fn bytes<'r>(&'r mut self) -> extensions::Bytes<'r, T> {
+        extensions::Bytes::new(self)
+    }
+}
+
 impl<'a> Reader for Box<Reader+'a> {
     fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
         let reader: &mut Reader = &mut **self;
@@ -986,6 +1000,7 @@ unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec<T>, start: uint, end: uint) -
 /// # fn process_input<R: Reader>(r: R) {}
 /// # fn foo() {
 /// use std::io;
+/// use std::io::AsRefReader;
 /// use std::io::util::LimitReader;
 ///
 /// let mut stream = io::stdin();
@@ -1268,13 +1283,20 @@ pub trait Writer {
     fn write_i8(&mut self, n: i8) -> IoResult<()> {
         self.write([n as u8])
     }
+}
 
+/// A writer which can be converted to a RefWriter.
+pub trait AsRefWriter {
     /// Creates a wrapper around a mutable reference to the writer.
     ///
     /// This is useful to allow applying wrappers while still
     /// retaining ownership of the original value.
     #[inline]
-    fn by_ref<'a>(&'a mut self) -> RefWriter<'a, Self> {
+    fn by_ref<'a>(&'a mut self) -> RefWriter<'a, Self>;
+}
+
+impl<T: Writer> AsRefWriter for T {
+    fn by_ref<'a>(&'a mut self) -> RefWriter<'a, T> {
         RefWriter { inner: self }
     }
 }
@@ -1309,7 +1331,7 @@ impl<'a> Writer for &'a mut Writer+'a {
 /// # fn process_input<R: Reader>(r: R) {}
 /// # fn foo () {
 /// use std::io::util::TeeReader;
-/// use std::io::{stdin, MemWriter};
+/// use std::io::{stdin, MemWriter, AsRefWriter};
 ///
 /// let mut output = MemWriter::new();
 ///
diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs
index 820ae931f32..5694565b4ea 100644
--- a/src/libstd/io/util.rs
+++ b/src/libstd/io/util.rs
@@ -265,7 +265,7 @@ impl<T: Iterator<u8>> Reader for IterReader<T> {
 
 #[cfg(test)]
 mod test {
-    use io::{MemReader, MemWriter, BufReader};
+    use io::{MemReader, MemWriter, BufReader, AsRefReader};
     use io;
     use boxed::Box;
     use super::*;
diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs
index fbf17b76d62..2e93f6badf2 100644
--- a/src/libterm/lib.rs
+++ b/src/libterm/lib.rs
@@ -89,30 +89,25 @@ impl Writer for WriterWrapper {
 /// Return a Terminal wrapping stdout, or None if a terminal couldn't be
 /// opened.
 pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
-    let ti: Option<TerminfoTerminal<WriterWrapper>>
-        = Terminal::new(WriterWrapper {
-            wrapped: box std::io::stdout() as Box<Writer + Send>,
-        });
-    ti.map(|t| box t as Box<Terminal<WriterWrapper> + Send>)
+    TerminfoTerminal::new(WriterWrapper {
+        wrapped: box std::io::stdout() as Box<Writer + Send>,
+    })
 }
 
 #[cfg(windows)]
 /// Return a Terminal wrapping stdout, or None if a terminal couldn't be
 /// opened.
 pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
-    let ti: Option<TerminfoTerminal<WriterWrapper>>
-        = Terminal::new(WriterWrapper {
-            wrapped: box std::io::stdout() as Box<Writer + Send>,
-        });
+    let ti = TerminfoTerminal::new(WriterWrapper {
+        wrapped: box std::io::stdout() as Box<Writer + Send>,
+    });
 
     match ti {
-        Some(t) => Some(box t as Box<Terminal<WriterWrapper> + Send>),
+        Some(t) => Some(t),
         None => {
-            let wc: Option<WinConsole<WriterWrapper>>
-                = Terminal::new(WriterWrapper {
-                    wrapped: box std::io::stdout() as Box<Writer + Send>,
-                });
-            wc.map(|w| box w as Box<Terminal<WriterWrapper> + Send>)
+            WinConsole::new(WriterWrapper {
+                wrapped: box std::io::stdout() as Box<Writer + Send>,
+            })
         }
     }
 }
@@ -121,30 +116,25 @@ pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
 /// Return a Terminal wrapping stderr, or None if a terminal couldn't be
 /// opened.
 pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send> + Send> {
-    let ti: Option<TerminfoTerminal<WriterWrapper>>
-        = Terminal::new(WriterWrapper {
-            wrapped: box std::io::stderr() as Box<Writer + Send>,
-        });
-    ti.map(|t| box t as Box<Terminal<WriterWrapper> + Send>)
+    TerminfoTerminal::new(WriterWrapper {
+        wrapped: box std::io::stderr() as Box<Writer + Send>,
+    })
 }
 
 #[cfg(windows)]
 /// Return a Terminal wrapping stderr, or None if a terminal couldn't be
 /// opened.
 pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send> + Send> {
-    let ti: Option<TerminfoTerminal<WriterWrapper>>
-        = Terminal::new(WriterWrapper {
-            wrapped: box std::io::stderr() as Box<Writer + Send>,
-        });
+    let ti = TerminfoTerminal::new(WriterWrapper {
+        wrapped: box std::io::stderr() as Box<Writer + Send>,
+    });
 
     match ti {
-        Some(t) => Some(box t as Box<Terminal<WriterWrapper> + Send>),
+        Some(t) => Some(t),
         None => {
-            let wc: Option<WinConsole<WriterWrapper>>
-                = Terminal::new(WriterWrapper {
-                    wrapped: box std::io::stderr() as Box<Writer + Send>,
-                });
-            wc.map(|w| box w as Box<Terminal<WriterWrapper> + Send>)
+            WinConsole::new(WriterWrapper {
+                wrapped: box std::io::stderr() as Box<Writer + Send>,
+            })
         }
     }
 }
@@ -208,10 +198,6 @@ pub mod attr {
 /// A terminal with similar capabilities to an ANSI Terminal
 /// (foreground/background colors etc).
 pub trait Terminal<T: Writer>: Writer {
-    /// Returns `None` whenever the terminal cannot be created for some
-    /// reason.
-    fn new(out: T) -> Option<Self>;
-
     /// Sets the foreground color to the given color.
     ///
     /// If the color is a bright color, but the terminal only supports 8 colors,
@@ -242,12 +228,15 @@ pub trait Terminal<T: Writer>: Writer {
     /// Returns `Ok()`.
     fn reset(&mut self) -> IoResult<()>;
 
-    /// Returns the contained stream, destroying the `Terminal`
-    fn unwrap(self) -> T;
-
     /// Gets an immutable reference to the stream inside
     fn get_ref<'a>(&'a self) -> &'a T;
 
     /// Gets a mutable reference to the stream inside
     fn get_mut<'a>(&'a mut self) -> &'a mut T;
 }
+
+/// A terminal which can be unwrapped.
+pub trait UnwrappableTerminal<T: Writer>: Terminal<T> {
+    /// Returns the contained stream, destroying the `Terminal`
+    fn unwrap(self) -> T;
+}
diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs
index 36883c8fcf4..73edcf94892 100644
--- a/src/libterm/terminfo/mod.rs
+++ b/src/libterm/terminfo/mod.rs
@@ -17,6 +17,7 @@ use std::os;
 use attr;
 use color;
 use Terminal;
+use UnwrappableTerminal;
 use self::searcher::open;
 use self::parser::compiled::{parse, msys_terminfo};
 use self::parm::{expand, Number, Variables};
@@ -71,44 +72,7 @@ pub struct TerminfoTerminal<T> {
     ti: Box<TermInfo>
 }
 
-impl<T: Writer> Terminal<T> for TerminfoTerminal<T> {
-    fn new(out: T) -> Option<TerminfoTerminal<T>> {
-        let term = match os::getenv("TERM") {
-            Some(t) => t,
-            None => {
-                debug!("TERM environment variable not defined");
-                return None;
-            }
-        };
-
-        let entry = open(term.as_slice());
-        if entry.is_err() {
-            if os::getenv("MSYSCON").map_or(false, |s| {
-                    "mintty.exe" == s.as_slice()
-                }) {
-                // msys terminal
-                return Some(TerminfoTerminal {out: out, ti: msys_terminfo(), num_colors: 8});
-            }
-            debug!("error finding terminfo entry: {}", entry.err().unwrap());
-            return None;
-        }
-
-        let mut file = entry.unwrap();
-        let ti = parse(&mut file, false);
-        if ti.is_err() {
-            debug!("error parsing terminfo entry: {}", ti.unwrap_err());
-            return None;
-        }
-
-        let inf = ti.unwrap();
-        let nc = if inf.strings.find_equiv(&("setaf")).is_some()
-                 && inf.strings.find_equiv(&("setab")).is_some() {
-                     inf.numbers.find_equiv(&("colors")).map_or(0, |&n| n)
-                 } else { 0 };
-
-        return Some(TerminfoTerminal {out: out, ti: inf, num_colors: nc});
-    }
-
+impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
     fn fg(&mut self, color: color::Color) -> IoResult<bool> {
         let color = self.dim_if_necessary(color);
         if self.num_colors > color {
@@ -195,14 +159,59 @@ impl<T: Writer> Terminal<T> for TerminfoTerminal<T> {
         Ok(())
     }
 
-    fn unwrap(self) -> T { self.out }
-
     fn get_ref<'a>(&'a self) -> &'a T { &self.out }
 
     fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.out }
 }
 
-impl<T: Writer> TerminfoTerminal<T> {
+impl<T: Writer+Send> UnwrappableTerminal<T> for TerminfoTerminal<T> {
+    fn unwrap(self) -> T { self.out }
+}
+
+impl<T: Writer+Send> TerminfoTerminal<T> {
+    /// Returns `None` whenever the terminal cannot be created for some
+    /// reason.
+    pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
+        let term = match os::getenv("TERM") {
+            Some(t) => t,
+            None => {
+                debug!("TERM environment variable not defined");
+                return None;
+            }
+        };
+
+        let entry = open(term.as_slice());
+        if entry.is_err() {
+            if os::getenv("MSYSCON").map_or(false, |s| {
+                    "mintty.exe" == s.as_slice()
+                }) {
+                // msys terminal
+                return Some(box TerminfoTerminal {out: out,
+                                                  ti: msys_terminfo(),
+                                                  num_colors: 8} as Box<Terminal<T>+Send>);
+            }
+            debug!("error finding terminfo entry: {}", entry.err().unwrap());
+            return None;
+        }
+
+        let mut file = entry.unwrap();
+        let ti = parse(&mut file, false);
+        if ti.is_err() {
+            debug!("error parsing terminfo entry: {}", ti.unwrap_err());
+            return None;
+        }
+
+        let inf = ti.unwrap();
+        let nc = if inf.strings.find_equiv(&("setaf")).is_some()
+                 && inf.strings.find_equiv(&("setab")).is_some() {
+                     inf.numbers.find_equiv(&("colors")).map_or(0, |&n| n)
+                 } else { 0 };
+
+        return Some(box TerminfoTerminal {out: out,
+                                          ti: inf,
+                                          num_colors: nc} as Box<Terminal<T>+Send>);
+    }
+
     fn dim_if_necessary(&self, color: color::Color) -> color::Color {
         if color >= self.num_colors && color >= 8 && color < 16 {
             color-8
diff --git a/src/libterm/win.rs b/src/libterm/win.rs
index d4f06403c1a..7ce6fb658b5 100644
--- a/src/libterm/win.rs
+++ b/src/libterm/win.rs
@@ -18,7 +18,7 @@ use std::io::IoResult;
 
 use attr;
 use color;
-use Terminal;
+use {Terminal,UnwrappableTerminal};
 
 /// A Terminal implementation which uses the Win32 Console API.
 pub struct WinConsole<T> {
@@ -91,7 +91,7 @@ fn bits_to_color(bits: u16) -> color::Color {
     }
 }
 
-impl<T: Writer> WinConsole<T> {
+impl<T: Writer+Send> WinConsole<T> {
     fn apply(&mut self) {
         let _unused = self.buf.flush();
         let mut accum: libc::WORD = 0;
@@ -112,20 +112,10 @@ impl<T: Writer> WinConsole<T> {
             SetConsoleTextAttribute(out, accum);
         }
     }
-}
-
-impl<T: Writer> Writer for WinConsole<T> {
-    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
-        self.buf.write(buf)
-    }
-
-    fn flush(&mut self) -> IoResult<()> {
-        self.buf.flush()
-    }
-}
 
-impl<T: Writer> Terminal<T> for WinConsole<T> {
-    fn new(out: T) -> Option<WinConsole<T>> {
+    /// Returns `None` whenever the terminal cannot be created for some
+    /// reason.
+    pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
         let fg;
         let bg;
         unsafe {
@@ -138,11 +128,23 @@ impl<T: Writer> Terminal<T> for WinConsole<T> {
                 bg = color::BLACK;
             }
         }
-        Some(WinConsole { buf: out,
-                          def_foreground: fg, def_background: bg,
-                          foreground: fg, background: bg } )
+        Some(box WinConsole { buf: out,
+                              def_foreground: fg, def_background: bg,
+                              foreground: fg, background: bg } as Box<Terminal<T>+Send>)
     }
+}
 
+impl<T: Writer> Writer for WinConsole<T> {
+    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
+        self.buf.write(buf)
+    }
+
+    fn flush(&mut self) -> IoResult<()> {
+        self.buf.flush()
+    }
+}
+
+impl<T: Writer+Send> Terminal<T> for WinConsole<T> {
     fn fg(&mut self, color: color::Color) -> IoResult<bool> {
         self.foreground = color;
         self.apply();
@@ -190,9 +192,11 @@ impl<T: Writer> Terminal<T> for WinConsole<T> {
         Ok(())
     }
 
-    fn unwrap(self) -> T { self.buf }
-
     fn get_ref<'a>(&'a self) -> &'a T { &self.buf }
 
     fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf }
 }
+
+impl<T: Writer+Send> UnwrappableTerminal<T> for WinConsole<T> {
+    fn unwrap(self) -> T { self.buf }
+}
diff --git a/src/test/compile-fail/region-object-lifetime-in-coercion.rs b/src/test/compile-fail/region-object-lifetime-in-coercion.rs
index 6791b7c5870..dfeba041092 100644
--- a/src/test/compile-fail/region-object-lifetime-in-coercion.rs
+++ b/src/test/compile-fail/region-object-lifetime-in-coercion.rs
@@ -11,24 +11,27 @@
 // Test that attempts to implicitly coerce a value into an
 // object respect the lifetime bound on the object type.
 
-fn a(v: &[u8]) -> Box<Clone + 'static> {
-    let x: Box<Clone + 'static> = box v; //~ ERROR does not outlive
+trait Foo {}
+impl<'a> Foo for &'a [u8] {}
+
+fn a(v: &[u8]) -> Box<Foo + 'static> {
+    let x: Box<Foo + 'static> = box v; //~ ERROR does not outlive
     x
 }
 
-fn b(v: &[u8]) -> Box<Clone + 'static> {
+fn b(v: &[u8]) -> Box<Foo + 'static> {
     box v //~ ERROR does not outlive
 }
 
-fn c(v: &[u8]) -> Box<Clone> {
+fn c(v: &[u8]) -> Box<Foo> {
     box v // OK thanks to lifetime elision
 }
 
-fn d<'a,'b>(v: &'a [u8]) -> Box<Clone+'b> {
+fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
     box v //~ ERROR does not outlive
 }
 
-fn e<'a:'b,'b>(v: &'a [u8]) -> Box<Clone+'b> {
+fn e<'a:'b,'b>(v: &'a [u8]) -> Box<Foo+'b> {
     box v // OK, thanks to 'a:'b
 }
 
diff --git a/src/test/compile-fail/selftype-traittype.rs b/src/test/compile-fail/selftype-traittype.rs
deleted file mode 100644
index 44ee5002dce..00000000000
--- a/src/test/compile-fail/selftype-traittype.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-
-trait add {
-    fn plus(&self, x: Self) -> Self;
-}
-
-fn do_add(x: Box<add+'static>, y: Box<add+'static>) -> Box<add+'static> {
-    x.plus(y) //~ ERROR E0038
-}
-
-fn main() {}
diff --git a/src/test/compile-fail/trait-objects.rs b/src/test/compile-fail/trait-objects.rs
new file mode 100644
index 00000000000..88b907a5cb9
--- /dev/null
+++ b/src/test/compile-fail/trait-objects.rs
@@ -0,0 +1,43 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo {
+    fn foo(self);
+}
+
+trait Bar {
+    fn bar(&self, x: &Self);
+}
+
+trait Baz {
+    fn baz<T>(&self, x: &T);
+}
+
+impl Foo for int {
+    fn foo(self) {}
+}
+
+impl Bar for int {
+    fn bar(&self, _x: &int) {}
+}
+
+impl Baz for int {
+    fn baz<T>(&self, _x: &T) {}
+}
+
+fn main() {
+    let _: &Foo = &42i; //~ ERROR cannot convert to a trait object
+    let _: &Bar = &42i; //~ ERROR cannot convert to a trait object
+    let _: &Baz = &42i; //~ ERROR cannot convert to a trait object
+
+    let _ = &42i as &Foo; //~ ERROR cannot convert to a trait object
+    let _ = &42i as &Bar; //~ ERROR cannot convert to a trait object
+    let _ = &42i as &Baz; //~ ERROR cannot convert to a trait object
+}
diff --git a/src/test/compile-fail/trait-test-2.rs b/src/test/compile-fail/trait-test-2.rs
index 3dce0178597..a24f7710d7b 100644
--- a/src/test/compile-fail/trait-test-2.rs
+++ b/src/test/compile-fail/trait-test-2.rs
@@ -16,5 +16,5 @@ impl bar for uint { fn dup(&self) -> uint { *self } fn blah<X>(&self) {} }
 fn main() {
     10i.dup::<int>(); //~ ERROR does not take type parameters
     10i.blah::<int, int>(); //~ ERROR incorrect number of type parameters
-    (box 10i as Box<bar>).dup(); //~ ERROR contains a self-type
+    (box 10i as Box<bar>).dup(); //~ ERROR cannot convert to a trait object
 }
diff --git a/src/test/run-fail/by-value-self-objects-fail.rs b/src/test/run-fail/by-value-self-objects-fail.rs
deleted file mode 100644
index 6b000866d3a..00000000000
--- a/src/test/run-fail/by-value-self-objects-fail.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern:explicit panic
-
-trait Foo {
-    fn foo(self, x: int);
-}
-
-struct S {
-    x: int,
-    y: int,
-    z: int,
-    s: String,
-}
-
-impl Foo for S {
-    fn foo(self, x: int) {
-        panic!()
-    }
-}
-
-impl Drop for S {
-    fn drop(&mut self) {
-        println!("bye 1!");
-    }
-}
-
-fn f() {
-    let s = S {
-        x: 2,
-        y: 3,
-        z: 4,
-        s: "hello".to_string(),
-    };
-    let st = box s as Box<Foo>;
-    st.foo(5);
-}
-
-fn main() {
-    f();
-}
-
-
diff --git a/src/test/run-pass/by-value-self-objects.rs b/src/test/run-pass/by-value-self-objects.rs
deleted file mode 100644
index 3a588367a97..00000000000
--- a/src/test/run-pass/by-value-self-objects.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-static mut destructor_count: uint = 0;
-
-trait Foo {
-    fn foo(self, x: int);
-}
-
-struct S {
-    x: int,
-    y: int,
-    z: int,
-    s: String,
-}
-
-impl Foo for S {
-    fn foo(self, x: int) {
-        assert!(self.x == 2);
-        assert!(self.y == 3);
-        assert!(self.z == 4);
-        assert!(self.s.as_slice() == "hello");
-        assert!(x == 5);
-    }
-}
-
-impl Drop for S {
-    fn drop(&mut self) {
-        println!("bye 1!");
-        unsafe {
-            destructor_count += 1;
-        }
-    }
-}
-
-impl Foo for int {
-    fn foo(self, x: int) {
-        println!("{}", x * x);
-    }
-}
-
-fn f() {
-    let s = S {
-        x: 2,
-        y: 3,
-        z: 4,
-        s: "hello".to_string(),
-    };
-    let st = box s as Box<Foo>;
-    st.foo(5);
-    println!("bye 2!");
-}
-
-fn g() {
-    let s = 2i;
-    let st = box s as Box<Foo>;
-    st.foo(3);
-    println!("bye 3!");
-}
-
-fn main() {
-    f();
-
-    unsafe {
-        assert!(destructor_count == 1);
-    }
-
-    g();
-}
-
diff --git a/src/test/run-pass/issue-11267.rs b/src/test/run-pass/issue-11267.rs
index 53659a72132..f08805fe49c 100644
--- a/src/test/run-pass/issue-11267.rs
+++ b/src/test/run-pass/issue-11267.rs
@@ -12,11 +12,14 @@
 
 struct Empty;
 
-impl Iterator<int> for Empty {
+trait T<U> {
+    fn next(&mut self) -> Option<U>;
+}
+impl T<int> for Empty {
     fn next(&mut self) -> Option<int> { None }
 }
 
-fn do_something_with(a : &mut Iterator<int>) {
+fn do_something_with(a : &mut T<int>) {
     println!("{}", a.next())
 }
 
diff --git a/src/test/run-pass/issue-15763.rs b/src/test/run-pass/issue-15763.rs
index 6e3599bda14..0c09e456930 100644
--- a/src/test/run-pass/issue-15763.rs
+++ b/src/test/run-pass/issue-15763.rs
@@ -60,16 +60,16 @@ fn dd() -> Result<int, int> {
 }
 
 trait A {
-    fn aaa(self) -> int {
+    fn aaa(&self) -> int {
         3
     }
-    fn bbb(self) -> int {
+    fn bbb(&self) -> int {
         return 3;
     }
-    fn ccc(self) -> Result<int, int> {
+    fn ccc(&self) -> Result<int, int> {
         Ok(3)
     }
-    fn ddd(self) -> Result<int, int> {
+    fn ddd(&self) -> Result<int, int> {
         return Ok(3);
     }
 }
diff --git a/src/test/run-pass/trait-cast-generic.rs b/src/test/run-pass/trait-cast-generic.rs
deleted file mode 100644
index 8f0ec5ec7a1..00000000000
--- a/src/test/run-pass/trait-cast-generic.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Testing casting of a generic Struct to a Trait with a generic method.
-// This is test for issue 10955.
-#![allow(unused_variable)]
-
-trait Foo {
-    fn f<A>(a: A) -> A {
-        a
-    }
-}
-
-struct Bar<T> {
-    x: T,
-}
-
-impl<T> Foo for Bar<T> { }
-
-pub fn main() {
-    let a = Bar { x: 1u };
-    let b = &a as &Foo;
-}
diff --git a/src/test/run-pass/trait-default-method-xc.rs b/src/test/run-pass/trait-default-method-xc.rs
index f88522facdf..c4880e97c45 100644
--- a/src/test/run-pass/trait-default-method-xc.rs
+++ b/src/test/run-pass/trait-default-method-xc.rs
@@ -72,9 +72,6 @@ pub fn main() {
     assert_eq!(g(0i, 3.14f64, 1i), (3.14f64, 1i));
     assert_eq!(g(false, 3.14f64, 1i), (3.14, 1));
 
-    let obj = box 0i as Box<A>;
-    assert_eq!(obj.h(), 11);
-
 
     // Trying out a real one
     assert!(12i.test_neq(&10i));