diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs
index 5d84d0c7797..159c2a505d5 100644
--- a/src/libcore/clone.rs
+++ b/src/libcore/clone.rs
@@ -25,7 +25,7 @@ use kinds::Sized;
 
 /// A common trait for cloning an object.
 #[stable]
-pub trait Clone {
+pub trait Clone : Sized {
     /// Returns a copy of the value.
     #[stable]
     fn clone(&self) -> Self;
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index f2439d515b4..13fbf5232f8 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -74,7 +74,26 @@ pub trait Writer {
     ///
     /// This method should generally not be invoked manually, but rather through
     /// the `write!` macro itself.
-    fn write_fmt(&mut self, args: Arguments) -> Result { write(self, args) }
+    fn write_fmt(&mut self, args: Arguments) -> Result {
+        // This Adapter is needed to allow `self` (of type `&mut
+        // Self`) to be cast to a FormatWriter (below) without
+        // requiring a `Sized` bound.
+        struct Adapter<'a,Sized? T:'a>(&'a mut T);
+
+        impl<'a, Sized? T> Writer for Adapter<'a, T>
+            where T: Writer
+        {
+            fn write_str(&mut self, s: &str) -> Result {
+                self.0.write_str(s)
+            }
+
+            fn write_fmt(&mut self, args: Arguments) -> Result {
+                self.0.write_fmt(args)
+            }
+        }
+
+        write(&mut Adapter(self), args)
+    }
 }
 
 /// A struct to represent both where to emit formatting strings to and how they
@@ -579,9 +598,6 @@ impl<'a, Sized? T: Show> Show for &'a T {
 impl<'a, Sized? T: Show> Show for &'a mut T {
     fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) }
 }
-impl<'a> Show for &'a (Show+'a) {
-    fn fmt(&self, f: &mut Formatter) -> Result { (*self).fmt(f) }
-}
 
 impl Show for bool {
     fn fmt(&self, f: &mut Formatter) -> Result {
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 4a7a681255f..53b5c617300 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -65,6 +65,7 @@ use num::{ToPrimitive, Int};
 use ops::{Add, Deref, FnMut};
 use option::Option;
 use option::Option::{Some, None};
+use std::kinds::Sized;
 use uint;
 
 #[deprecated = "renamed to Extend"] pub use self::Extend as Extendable;
@@ -109,7 +110,7 @@ pub trait Extend<A> {
 
 #[unstable = "new convention for extension traits"]
 /// An extension trait providing numerous methods applicable to all iterators.
-pub trait IteratorExt<A>: Iterator<A> {
+pub trait IteratorExt<A>: Iterator<A> + Sized {
     /// Chain this iterator with another, returning a new iterator that will
     /// finish iterating over the current iterator, and then iterate
     /// over the other specified iterator.
@@ -692,7 +693,7 @@ impl<A, I> IteratorExt<A> for I where I: Iterator<A> {}
 
 /// Extention trait for iterators of pairs.
 #[unstable = "newly added trait, likely to be merged with IteratorExt"]
-pub trait IteratorPairExt<A, B>: Iterator<(A, B)> {
+pub trait IteratorPairExt<A, B>: Iterator<(A, B)> + Sized {
     /// Converts an iterator of pairs into a pair of containers.
     ///
     /// Loops through the entire iterator, collecting the first component of
@@ -738,7 +739,7 @@ pub trait DoubleEndedIterator<A>: Iterator<A> {
 
 /// Extension methods for double-ended iterators.
 #[unstable = "new extension trait convention"]
-pub trait DoubleEndedIteratorExt<A>: DoubleEndedIterator<A> {
+pub trait DoubleEndedIteratorExt<A>: DoubleEndedIterator<A> + Sized {
     /// Change the direction of the iterator
     ///
     /// The flipped iterator swaps the ends on an iterator that can already
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 0d2ce4f6071..d16478dd6cc 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -980,7 +980,7 @@ impl_to_primitive_float! { f64 }
 
 /// A generic trait for converting a number to a value.
 #[experimental = "trait is likely to be removed"]
-pub trait FromPrimitive {
+pub trait FromPrimitive : ::kinds::Sized {
     /// Convert an `int` to return an optional value of this type. If the
     /// value cannot be represented by this value, the `None` is returned.
     #[inline]
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index faf1d781465..38e47a5ad33 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -92,7 +92,7 @@ use mem;
 use clone::Clone;
 use intrinsics;
 use option::Option::{mod, Some, None};
-use kinds::{Send, Sync};
+use kinds::{Send, Sized, Sync};
 
 use cmp::{PartialEq, Eq, Ord, PartialOrd, Equiv};
 use cmp::Ordering::{mod, Less, Equal, Greater};
@@ -243,7 +243,7 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
 
 /// Methods on raw pointers
 #[stable]
-pub trait PtrExt<T> {
+pub trait PtrExt<T> : Sized {
     /// Returns the null pointer.
     #[deprecated = "call ptr::null instead"]
     fn null() -> Self;
diff --git a/src/librand/lib.rs b/src/librand/lib.rs
index 568d2459118..bbcd99afdea 100644
--- a/src/librand/lib.rs
+++ b/src/librand/lib.rs
@@ -52,14 +52,14 @@ pub mod reseeding;
 mod rand_impls;
 
 /// A type that can be randomly generated using an `Rng`.
-pub trait Rand {
+pub trait Rand : Sized {
     /// Generates a random instance of this type using the specified source of
     /// randomness.
     fn rand<R: Rng>(rng: &mut R) -> Self;
 }
 
 /// A random number generator.
-pub trait Rng {
+pub trait Rng : Sized {
     /// Return the next random u32.
     ///
     /// This rarely needs to be called directly, prefer `r.gen()` to
diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs
index e0bcdfc6d8d..ab6f6b601f6 100644
--- a/src/librustc/middle/infer/combine.rs
+++ b/src/librustc/middle/infer/combine.rs
@@ -57,7 +57,7 @@ use syntax::ast;
 use syntax::abi;
 use syntax::codemap::Span;
 
-pub trait Combine<'tcx> {
+pub trait Combine<'tcx> : Sized {
     fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx>;
     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.infcx().tcx }
     fn tag(&self) -> String;
diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs
index 3c5459ff3bc..97e74b9f6bb 100644
--- a/src/librustc/middle/subst.rs
+++ b/src/librustc/middle/subst.rs
@@ -519,7 +519,7 @@ impl<'a,T> Iterator<(ParamSpace, uint, &'a T)> for EnumeratedItems<'a,T> {
 // `foo`. Or use `foo.subst_spanned(tcx, substs, Some(span))` when
 // there is more information available (for better errors).
 
-pub trait Subst<'tcx> {
+pub trait Subst<'tcx> : Sized {
     fn subst(&self, tcx: &ty::ctxt<'tcx>, substs: &Substs<'tcx>) -> Self {
         self.subst_spanned(tcx, substs, None)
     }
diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs
index fc2eb43c8a5..c83898bcd8a 100644
--- a/src/librustc/middle/traits/mod.rs
+++ b/src/librustc/middle/traits/mod.rs
@@ -31,20 +31,27 @@ pub use self::fulfill::{FulfillmentContext, RegionObligation};
 pub use self::project::MismatchedProjectionTypes;
 pub use self::project::normalize;
 pub use self::project::Normalized;
+pub use self::object_safety::is_object_safe;
+pub use self::object_safety::object_safety_violations;
+pub use self::object_safety::ObjectSafetyViolation;
+pub use self::object_safety::MethodViolationCode;
 pub use self::select::SelectionContext;
 pub use self::select::SelectionCache;
 pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch};
 pub use self::select::{MethodMatchedData}; // intentionally don't export variants
 pub use self::util::elaborate_predicates;
+pub use self::util::get_vtable_index_of_object_method;
 pub use self::util::trait_ref_for_builtin_bound;
 pub use self::util::supertraits;
 pub use self::util::Supertraits;
 pub use self::util::transitive_bounds;
+pub use self::util::upcast;
 
 mod coherence;
 mod error_reporting;
 mod fulfill;
 mod project;
+mod object_safety;
 mod select;
 mod util;
 
@@ -212,6 +219,9 @@ pub enum Vtable<'tcx, N> {
     /// for some type parameter.
     VtableParam,
 
+    /// Virtual calls through an object
+    VtableObject(VtableObjectData<'tcx>),
+
     /// Successful resolution for a builtin trait.
     VtableBuiltin(VtableBuiltinData<N>),
 
@@ -247,6 +257,13 @@ pub struct VtableBuiltinData<N> {
     pub nested: subst::VecPerParamSpace<N>
 }
 
+/// A vtable for some object-safe trait `Foo` automatically derived
+/// for the object type `Foo`.
+#[deriving(PartialEq,Eq,Clone)]
+pub struct VtableObjectData<'tcx> {
+    pub object_ty: Ty<'tcx>,
+}
+
 /// True if there exist types that satisfy both of the two given impls.
 pub fn overlapping_impls(infcx: &InferCtxt,
                          impl1_def_id: ast::DefId,
@@ -358,6 +375,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
             VtableFnPointer(..) => (&[]).iter(),
             VtableUnboxedClosure(..) => (&[]).iter(),
             VtableParam => (&[]).iter(),
+            VtableObject(_) => (&[]).iter(),
             VtableBuiltin(ref i) => i.iter_nested(),
         }
     }
@@ -368,6 +386,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
             VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()),
             VtableUnboxedClosure(d, ref s) => VtableUnboxedClosure(d, s.clone()),
             VtableParam => VtableParam,
+            VtableObject(ref p) => VtableObject(p.clone()),
             VtableBuiltin(ref b) => VtableBuiltin(b.map_nested(op)),
         }
     }
@@ -380,6 +399,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
             VtableFnPointer(sig) => VtableFnPointer(sig),
             VtableUnboxedClosure(d, s) => VtableUnboxedClosure(d, s),
             VtableParam => VtableParam,
+            VtableObject(p) => VtableObject(p),
             VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)),
         }
     }
diff --git a/src/librustc/middle/traits/object_safety.rs b/src/librustc/middle/traits/object_safety.rs
new file mode 100644
index 00000000000..6b7bf82af92
--- /dev/null
+++ b/src/librustc/middle/traits/object_safety.rs
@@ -0,0 +1,301 @@
+// 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.
+
+//! "Object safety" refers to the ability for a trait to be converted
+//! to an object. In general, traits may only be converted to an
+//! object if all of their methods meet certain criteria. In particular,
+//! they must:
+//!
+//!   - have a suitable receiver from which we can extract a vtable;
+//!   - not reference the erased type `Self` except for in this receiver;
+//!   - not have generic type parameters
+
+use super::supertraits;
+use super::elaborate_predicates;
+
+use middle::subst::{mod, SelfSpace};
+use middle::traits;
+use middle::ty::{mod, Ty};
+use std::rc::Rc;
+use syntax::ast;
+use util::ppaux::Repr;
+
+pub enum ObjectSafetyViolation<'tcx> {
+    /// Self : Sized declared on the trait
+    SizedSelf,
+
+    /// Method has someting illegal
+    Method(Rc<ty::Method<'tcx>>, MethodViolationCode),
+}
+
+/// Reasons a method might not be object-safe.
+#[deriving(Copy,Clone,Show)]
+pub enum MethodViolationCode {
+    /// e.g., `fn(self)`
+    ByValueSelf,
+
+    /// e.g., `fn foo()`
+    StaticMethod,
+
+    /// e.g., `fn foo(&self, x: Self)` or `fn foo(&self) -> Self`
+    ReferencesSelf,
+
+    /// e.g., `fn foo<A>()`
+    Generic,
+}
+
+pub fn is_object_safe<'tcx>(tcx: &ty::ctxt<'tcx>,
+                            trait_ref: ty::PolyTraitRef<'tcx>)
+                            -> bool
+{
+    // Because we query yes/no results frequently, we keep a cache:
+    let cached_result =
+        tcx.object_safety_cache.borrow().get(&trait_ref.def_id()).map(|&r| r);
+
+    let result =
+        cached_result.unwrap_or_else(|| {
+            let result = object_safety_violations(tcx, trait_ref.clone()).is_empty();
+
+            // Record just a yes/no result in the cache; this is what is
+            // queried most frequently. Note that this may overwrite a
+            // previous result, but always with the same thing.
+            tcx.object_safety_cache.borrow_mut().insert(trait_ref.def_id(), result);
+
+            result
+        });
+
+    debug!("is_object_safe({}) = {}", trait_ref.repr(tcx), result);
+
+    result
+}
+
+pub fn object_safety_violations<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                      sub_trait_ref: ty::PolyTraitRef<'tcx>)
+                                      -> Vec<ObjectSafetyViolation<'tcx>>
+{
+    supertraits(tcx, sub_trait_ref)
+        .flat_map(|tr| object_safety_violations_for_trait(tcx, tr.def_id()).into_iter())
+        .collect()
+}
+
+fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                            trait_def_id: ast::DefId)
+                                            -> Vec<ObjectSafetyViolation<'tcx>>
+{
+    // Check methods for violations.
+    let mut violations: Vec<_> =
+        ty::trait_items(tcx, trait_def_id).iter()
+        .flat_map(|item| {
+            match *item {
+                ty::MethodTraitItem(ref m) => {
+                    object_safety_violations_for_method(tcx, trait_def_id, &**m)
+                        .map(|code| ObjectSafetyViolation::Method(m.clone(), code))
+                        .into_iter()
+                }
+                ty::TypeTraitItem(_) => {
+                    None.into_iter()
+                }
+            }
+        })
+        .collect();
+
+    // Check the trait itself.
+    if trait_has_sized_self(tcx, trait_def_id) {
+        violations.push(ObjectSafetyViolation::SizedSelf);
+    }
+
+    debug!("object_safety_violations_for_trait(trait_def_id={}) = {}",
+           trait_def_id.repr(tcx),
+           violations.repr(tcx));
+
+    violations
+}
+
+fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
+                              trait_def_id: ast::DefId)
+                              -> bool
+{
+    let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
+    let param_env = ty::construct_parameter_environment(tcx,
+                                                        &trait_def.generics,
+                                                        ast::DUMMY_NODE_ID);
+    let predicates = param_env.caller_bounds.predicates.as_slice().to_vec();
+    let sized_def_id = match tcx.lang_items.sized_trait() {
+        Some(def_id) => def_id,
+        None => { return false; /* No Sized trait, can't require it! */ }
+    };
+
+    // Search for a predicate like `Self : Sized` amongst the trait bounds.
+    elaborate_predicates(tcx, predicates)
+        .any(|predicate| {
+            match predicate {
+                ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
+                    let self_ty = trait_pred.0.self_ty();
+                    match self_ty.sty {
+                        ty::ty_param(ref data) => data.space == subst::SelfSpace,
+                        _ => false,
+                    }
+                }
+                ty::Predicate::Projection(..) |
+                ty::Predicate::Trait(..) |
+                ty::Predicate::Equate(..) |
+                ty::Predicate::RegionOutlives(..) |
+                ty::Predicate::TypeOutlives(..) => {
+                    false
+                }
+            }
+        })
+}
+
+fn object_safety_violations_for_method<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                             trait_def_id: ast::DefId,
+                                             method: &ty::Method<'tcx>)
+                                             -> Option<MethodViolationCode>
+{
+    // The method's first parameter must be something that derefs to
+    // `&self`. For now, we only accept `&self` and `Box<Self>`.
+    match method.explicit_self {
+        ty::ByValueExplicitSelfCategory => {
+            return Some(MethodViolationCode::ByValueSelf);
+        }
+
+        ty::StaticExplicitSelfCategory => {
+            return Some(MethodViolationCode::StaticMethod);
+        }
+
+        ty::ByReferenceExplicitSelfCategory(..) |
+        ty::ByBoxExplicitSelfCategory => {
+        }
+    }
+
+    // The `Self` type is erased, so it should not appear in list of
+    // arguments or return type apart from the receiver.
+    let ref sig = method.fty.sig;
+    for &input_ty in sig.0.inputs[1..].iter() {
+        if contains_illegal_self_type_reference(tcx, trait_def_id, input_ty) {
+            return Some(MethodViolationCode::ReferencesSelf);
+        }
+    }
+    if let ty::FnConverging(result_type) = sig.0.output {
+        if contains_illegal_self_type_reference(tcx, trait_def_id, result_type) {
+            return Some(MethodViolationCode::ReferencesSelf);
+        }
+    }
+
+    // We can't monomorphize things like `fn foo<A>(...)`.
+    if !method.generics.types.is_empty_in(subst::FnSpace) {
+        return Some(MethodViolationCode::Generic);
+    }
+
+    None
+}
+
+fn contains_illegal_self_type_reference<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                              trait_def_id: ast::DefId,
+                                              ty: Ty<'tcx>)
+                                              -> bool
+{
+    // This is somewhat subtle. In general, we want to forbid
+    // references to `Self` in the argument and return types,
+    // since the value of `Self` is erased. However, there is one
+    // exception: it is ok to reference `Self` in order to access
+    // an associated type of the current trait, since we retain
+    // the value of those associated types in the object type
+    // itself.
+    //
+    // ```rust
+    // trait SuperTrait {
+    //     type X;
+    // }
+    //
+    // trait Trait : SuperTrait {
+    //     type Y;
+    //     fn foo(&self, x: Self) // bad
+    //     fn foo(&self) -> Self // bad
+    //     fn foo(&self) -> Option<Self> // bad
+    //     fn foo(&self) -> Self::Y // OK, desugars to next example
+    //     fn foo(&self) -> <Self as Trait>::Y // OK
+    //     fn foo(&self) -> Self::X // OK, desugars to next example
+    //     fn foo(&self) -> <Self as SuperTrait>::X // OK
+    // }
+    // ```
+    //
+    // However, it is not as simple as allowing `Self` in a projected
+    // type, because there are illegal ways to use `Self` as well:
+    //
+    // ```rust
+    // trait Trait : SuperTrait {
+    //     ...
+    //     fn foo(&self) -> <Self as SomeOtherTrait>::X;
+    // }
+    // ```
+    //
+    // Here we will not have the type of `X` recorded in the
+    // object type, and we cannot resolve `Self as SomeOtherTrait`
+    // without knowing what `Self` is.
+
+    let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None;
+    let mut error = false;
+    ty::maybe_walk_ty(ty, |ty| {
+        match ty.sty {
+            ty::ty_param(ref param_ty) => {
+                if param_ty.space == SelfSpace {
+                    error = true;
+                }
+
+                false // no contained types to walk
+            }
+
+            ty::ty_projection(ref data) => {
+                // This is a projected type `<Foo as SomeTrait>::X`.
+
+                // Compute supertraits of current trait lazilly.
+                if supertraits.is_none() {
+                    let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
+                    let trait_ref = ty::Binder(trait_def.trait_ref.clone());
+                    supertraits = Some(traits::supertraits(tcx, trait_ref).collect());
+                }
+
+                // Determine whether the trait reference `Foo as
+                // SomeTrait` is in fact a supertrait of the
+                // current trait. In that case, this type is
+                // legal, because the type `X` will be specified
+                // in the object type.  Note that we can just use
+                // direct equality here because all of these types
+                // are part of the formal parameter listing, and
+                // hence there should be no inference variables.
+                let projection_trait_ref = ty::Binder(data.trait_ref.clone());
+                let is_supertrait_of_current_trait =
+                    supertraits.as_ref().unwrap().contains(&projection_trait_ref);
+
+                if is_supertrait_of_current_trait {
+                    false // do not walk contained types, do not report error, do collect $200
+                } else {
+                    true // DO walk contained types, POSSIBLY reporting an error
+                }
+            }
+
+            _ => true, // walk contained types, if any
+        }
+    });
+
+    error
+}
+
+impl<'tcx> Repr<'tcx> for ObjectSafetyViolation<'tcx> {
+    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+        match *self {
+            ObjectSafetyViolation::SizedSelf =>
+                format!("SizedSelf"),
+            ObjectSafetyViolation::Method(ref m, code) =>
+                format!("Method({},{})", m.repr(tcx), code),
+        }
+    }
+}
diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs
index c84f31bf6c3..0544e32b62c 100644
--- a/src/librustc/middle/traits/project.rs
+++ b/src/librustc/middle/traits/project.rs
@@ -377,20 +377,14 @@ fn project_type<'cx,'tcx>(
         ambiguous: false,
     };
 
-    assemble_candidates_from_object_type(selcx,
-                                         obligation,
-                                         &mut candidates);
+    assemble_candidates_from_param_env(selcx,
+                                       obligation,
+                                       &mut candidates);
 
-    if candidates.vec.is_empty() {
-        assemble_candidates_from_param_env(selcx,
-                                           obligation,
-                                           &mut candidates);
-
-        if let Err(e) = assemble_candidates_from_impls(selcx,
-                                                       obligation,
-                                                       &mut candidates) {
-            return Err(ProjectionTyError::TraitSelectionError(e));
-        }
+    if let Err(e) = assemble_candidates_from_impls(selcx,
+                                                   obligation,
+                                                   &mut candidates) {
+        return Err(ProjectionTyError::TraitSelectionError(e));
     }
 
     debug!("{} candidates, ambiguous={}",
@@ -467,18 +461,22 @@ fn assemble_candidates_from_predicates<'cx,'tcx>(
 fn assemble_candidates_from_object_type<'cx,'tcx>(
     selcx: &mut SelectionContext<'cx,'tcx>,
     obligation:  &ProjectionTyObligation<'tcx>,
-    candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
+    object_ty: Ty<'tcx>)
 {
     let infcx = selcx.infcx();
-    let trait_ref = infcx.resolve_type_vars_if_possible(&obligation.predicate.trait_ref);
-    debug!("assemble_candidates_from_object_type(trait_ref={})",
-           trait_ref.repr(infcx.tcx));
-    let self_ty = trait_ref.self_ty();
-    let data = match self_ty.sty {
+    debug!("assemble_candidates_from_object_type(object_ty={})",
+           object_ty.repr(infcx.tcx));
+    let data = match object_ty.sty {
         ty::ty_trait(ref data) => data,
-        _ => { return; }
+        _ => {
+            selcx.tcx().sess.span_bug(
+                obligation.cause.span,
+                format!("assemble_candidates_from_object_type called with non-object: {}",
+                        object_ty.repr(selcx.tcx()))[]);
+        }
     };
-    let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), self_ty);
+    let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), object_ty);
     let env_predicates = projection_bounds.iter()
                                           .map(|p| p.as_predicate())
                                           .collect();
@@ -515,6 +513,10 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
             candidate_set.vec.push(
                 ProjectionTyCandidate::Impl(data));
         }
+        super::VtableObject(data) => {
+            assemble_candidates_from_object_type(
+                selcx, obligation, candidate_set, data.object_ty);
+        }
         super::VtableParam(..) => {
             // This case tell us nothing about the value of an
             // associated type. Consider:
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index f9dced088f8..ca4bf7863be 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -24,8 +24,10 @@ use super::{ObligationCauseCode, BuiltinDerivedObligation};
 use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
 use super::{Selection};
 use super::{SelectionResult};
-use super::{VtableBuiltin, VtableImpl, VtableParam, VtableUnboxedClosure, VtableFnPointer};
-use super::{VtableImplData, VtableBuiltinData};
+use super::{VtableBuiltin, VtableImpl, VtableParam, VtableUnboxedClosure,
+            VtableFnPointer, VtableObject};
+use super::{VtableImplData, VtableObjectData, VtableBuiltinData};
+use super::object_safety;
 use super::{util};
 
 use middle::fast_reject;
@@ -147,6 +149,8 @@ enum SelectionCandidate<'tcx> {
     /// types generated for a fn pointer type (e.g., `fn(int)->int`)
     FnPointerCandidate,
 
+    ObjectCandidate,
+
     ErrorCandidate,
 }
 
@@ -717,6 +721,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 try!(self.assemble_unboxed_closure_candidates(obligation, &mut candidates));
                 try!(self.assemble_fn_pointer_candidates(obligation, &mut candidates));
                 try!(self.assemble_candidates_from_impls(obligation, &mut candidates.vec));
+                self.assemble_candidates_from_object_ty(obligation, &mut candidates);
             }
         }
 
@@ -878,7 +883,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let matching_bounds =
             all_bounds.filter(
                 |bound| self.infcx.probe(
-                    |_| self.match_where_clause(obligation, bound.clone())).is_ok());
+                    |_| self.match_poly_trait_ref(obligation, bound.clone())).is_ok());
 
         let param_candidates =
             matching_bounds.map(|bound| ParamCandidate(bound));
@@ -945,7 +950,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
         match self_ty.sty {
-            ty::ty_infer(..) => {
+            ty::ty_infer(ty::TyVar(_)) => {
                 candidates.ambiguous = true; // could wind up being a fn() type
             }
 
@@ -991,6 +996,62 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         Ok(())
     }
 
+    /// Search for impls that might apply to `obligation`.
+    fn assemble_candidates_from_object_ty(&mut self,
+                                          obligation: &TraitObligation<'tcx>,
+                                          candidates: &mut SelectionCandidateSet<'tcx>)
+    {
+        let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
+
+        debug!("assemble_candidates_from_object_ty(self_ty={})",
+               self_ty.repr(self.tcx()));
+
+        // Object-safety candidates are only applicable to object-safe
+        // traits. Including this check is useful because it helps
+        // inference in cases of traits like `BorrowFrom`, which are
+        // not object-safe, and which rely on being able to infer the
+        // self-type from one of the other inputs. Without this check,
+        // these cases wind up being considered ambiguous due to a
+        // (spurious) ambiguity introduced here.
+        if !object_safety::is_object_safe(self.tcx(), obligation.predicate.to_poly_trait_ref()) {
+            return;
+        }
+
+        let poly_trait_ref = match self_ty.sty {
+            ty::ty_trait(ref data) => {
+                data.principal_trait_ref_with_self_ty(self.tcx(), self_ty)
+            }
+            ty::ty_infer(ty::TyVar(_)) => {
+                debug!("assemble_candidates_from_object_ty: ambiguous");
+                candidates.ambiguous = true; // could wind up being an object type
+                return;
+            }
+            _ => {
+                return;
+            }
+        };
+
+        debug!("assemble_candidates_from_object_ty: poly_trait_ref={}",
+               poly_trait_ref.repr(self.tcx()));
+
+        // see whether the object trait can be upcast to the trait we are looking for
+        let obligation_def_id = obligation.predicate.def_id();
+        let upcast_trait_ref = match util::upcast(self.tcx(), poly_trait_ref, obligation_def_id) {
+            Some(r) => r,
+            None => { return; }
+        };
+
+        debug!("assemble_candidates_from_object_ty: upcast_trait_ref={}",
+               upcast_trait_ref.repr(self.tcx()));
+
+        // check whether the upcast version of the trait-ref matches what we are looking for
+        if let Ok(()) = self.infcx.probe(|_| self.match_poly_trait_ref(obligation,
+                                                                       upcast_trait_ref.clone())) {
+            debug!("assemble_candidates_from_object_ty: matched, pushing candidate");
+            candidates.vec.push(ObjectCandidate);
+        }
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // WINNOW
     //
@@ -1544,6 +1605,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 Ok(VtableUnboxedClosure(closure_def_id, substs))
             }
 
+            ObjectCandidate => {
+                let data = self.confirm_object_candidate(obligation);
+                Ok(VtableObject(data))
+            }
+
             FnPointerCandidate => {
                 let fn_type =
                     try!(self.confirm_fn_pointer_candidate(obligation));
@@ -1727,6 +1793,48 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                          nested: impl_predicates }
     }
 
+    fn confirm_object_candidate(&mut self,
+                                obligation: &TraitObligation<'tcx>)
+                                -> VtableObjectData<'tcx>
+    {
+        debug!("confirm_object_candidate({})",
+               obligation.repr(self.tcx()));
+
+        let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
+        let poly_trait_ref = match self_ty.sty {
+            ty::ty_trait(ref data) => {
+                data.principal_trait_ref_with_self_ty(self.tcx(), self_ty)
+            }
+            _ => {
+                self.tcx().sess.span_bug(obligation.cause.span,
+                                         "object candidate with non-object");
+            }
+        };
+
+        let obligation_def_id = obligation.predicate.def_id();
+        let upcast_trait_ref = match util::upcast(self.tcx(),
+                                                  poly_trait_ref.clone(),
+                                                  obligation_def_id) {
+            Some(r) => r,
+            None => {
+                self.tcx().sess.span_bug(obligation.cause.span,
+                                         format!("unable to upcast from {} to {}",
+                                                 poly_trait_ref.repr(self.tcx()),
+                                                 obligation_def_id.repr(self.tcx())).as_slice());
+            }
+        };
+
+        match self.match_poly_trait_ref(obligation, upcast_trait_ref) {
+            Ok(()) => { }
+            Err(()) => {
+                self.tcx().sess.span_bug(obligation.cause.span,
+                                         "failed to match trait refs");
+            }
+        }
+
+        VtableObjectData { object_ty: self_ty }
+    }
+
     fn confirm_fn_pointer_candidate(&mut self,
                                     obligation: &TraitObligation<'tcx>)
                                     -> Result<ty::Ty<'tcx>,SelectionError<'tcx>>
@@ -1962,12 +2070,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             })
     }
 
-    fn match_where_clause(&mut self,
-                          obligation: &TraitObligation<'tcx>,
-                          where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
-                        -> Result<(),()>
+    fn match_poly_trait_ref(&mut self,
+                            obligation: &TraitObligation<'tcx>,
+                            where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
+                            -> Result<(),()>
     {
-        debug!("match_where_clause: obligation={} where_clause_trait_ref={}",
+        debug!("match_poly_trait_ref: obligation={} where_clause_trait_ref={}",
                obligation.repr(self.tcx()),
                where_clause_trait_ref.repr(self.tcx()));
 
@@ -2161,6 +2269,9 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> {
             ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)),
             ProjectionCandidate => format!("ProjectionCandidate"),
             FnPointerCandidate => format!("FnPointerCandidate"),
+            ObjectCandidate => {
+                format!("ObjectCandidate")
+            }
             UnboxedClosureCandidate(c, ref s) => {
                 format!("UnboxedClosureCandidate({},{})", c, s.repr(tcx))
             }
diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs
index 109810fc7ee..41a59d6a5d8 100644
--- a/src/librustc/middle/traits/util.rs
+++ b/src/librustc/middle/traits/util.rs
@@ -238,6 +238,12 @@ impl<'tcx, N> fmt::Show for VtableImplData<'tcx, N> {
     }
 }
 
+impl<'tcx> fmt::Show for super::VtableObjectData<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "VtableObject(...)")
+    }
+}
+
 /// See `super::obligations_for_generics`
 pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
                                      cause: ObligationCause<'tcx>,
@@ -291,6 +297,58 @@ pub fn predicate_for_builtin_bound<'tcx>(
     })
 }
 
+/// Cast a trait reference into a reference to one of its super
+/// traits; returns `None` if `target_trait_def_id` is not a
+/// supertrait.
+pub fn upcast<'tcx>(tcx: &ty::ctxt<'tcx>,
+                    source_trait_ref: ty::PolyTraitRef<'tcx>,
+                    target_trait_def_id: ast::DefId)
+                    -> Option<ty::PolyTraitRef<'tcx>>
+{
+    if source_trait_ref.def_id() == target_trait_def_id {
+        return Some(source_trait_ref); // shorcut the most common case
+    }
+
+    for super_trait_ref in supertraits(tcx, source_trait_ref) {
+        if super_trait_ref.def_id() == target_trait_def_id {
+            return Some(super_trait_ref);
+        }
+    }
+
+    None
+}
+
+/// Given an object of type `object_trait_ref`, returns the index of
+/// the method `n_method` found in the trait `trait_def_id` (which
+/// should be a supertrait of `object_trait_ref`) within the vtable
+/// for `object_trait_ref`.
+pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                               object_trait_ref: ty::PolyTraitRef<'tcx>,
+                                               trait_def_id: ast::DefId,
+                                               method_index_in_trait: uint) -> uint {
+    // We need to figure the "real index" of the method in a
+    // listing of all the methods of an object. We do this by
+    // iterating down the supertraits of the object's trait until
+    // we find the trait the method came from, counting up the
+    // methods from them.
+    let mut method_count = 0;
+    ty::each_bound_trait_and_supertraits(tcx, &[object_trait_ref], |bound_ref| {
+        if bound_ref.def_id() == trait_def_id {
+            false
+        } else {
+            let trait_items = ty::trait_items(tcx, bound_ref.def_id());
+            for trait_item in trait_items.iter() {
+                match *trait_item {
+                    ty::MethodTraitItem(_) => method_count += 1,
+                    ty::TypeTraitItem(_) => {}
+                }
+            }
+            true
+        }
+    });
+    method_count + method_index_in_trait
+}
+
 impl<'tcx,O:Repr<'tcx>> Repr<'tcx> for super::Obligation<'tcx, O> {
     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         format!("Obligation(predicate={},depth={})",
@@ -314,6 +372,10 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> {
                 format!("VtableFnPointer({})",
                         d.repr(tcx)),
 
+            super::VtableObject(ref d) =>
+                format!("VtableObject({})",
+                        d.repr(tcx)),
+
             super::VtableParam =>
                 format!("VtableParam"),
 
@@ -339,6 +401,13 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableBuiltinData<N> {
     }
 }
 
+impl<'tcx> Repr<'tcx> for super::VtableObjectData<'tcx> {
+    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+        format!("VtableObject(object_ty={})",
+                self.object_ty.repr(tcx))
+    }
+}
+
 impl<'tcx> Repr<'tcx> for super::SelectionError<'tcx> {
     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         match *self {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 26a9cc5464e..0a03a8e836b 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -828,6 +828,9 @@ pub struct ctxt<'tcx> {
     /// parameters are never placed into this cache, because their
     /// results are dependent on the parameter environment.
     pub type_impls_sized_cache: RefCell<HashMap<Ty<'tcx>,bool>>,
+
+    /// Caches whether traits are object safe
+    pub object_safety_cache: RefCell<DefIdMap<bool>>,
 }
 
 // Flags that we track on types. These flags are propagated upwards
@@ -2385,6 +2388,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
         repr_hint_cache: RefCell::new(DefIdMap::new()),
         type_impls_copy_cache: RefCell::new(HashMap::new()),
         type_impls_sized_cache: RefCell::new(HashMap::new()),
+        object_safety_cache: RefCell::new(DefIdMap::new()),
    }
 }
 
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 83d2f6fb0e6..abbf530529b 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -56,7 +56,7 @@ pub trait TypeFoldable<'tcx> {
 /// default implementation that does an "identity" fold. Within each
 /// identity fold, it should invoke `foo.fold_with(self)` to fold each
 /// sub-item.
-pub trait TypeFolder<'tcx> {
+pub trait TypeFolder<'tcx> : Sized {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
 
     /// Invoked by the `super_*` routines when we enter a region
@@ -503,6 +503,15 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N>
             }
             traits::VtableParam => traits::VtableParam,
             traits::VtableBuiltin(ref d) => traits::VtableBuiltin(d.fold_with(folder)),
+            traits::VtableObject(ref d) => traits::VtableObject(d.fold_with(folder)),
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableObjectData<'tcx> {
+        traits::VtableObjectData {
+            object_ty: self.object_ty.fold_with(folder)
         }
     }
 }
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 773ea30d401..a046d9d5d39 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -154,7 +154,7 @@ trait PrinterSupport<'ast>: pprust::PpAnn {
     ///
     /// (Rust does not yet support upcasting from a trait object to
     /// an object for one of its super-traits.)
-    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn }
+    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn;
 }
 
 struct NoAnn<'ast> {
@@ -168,6 +168,8 @@ impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> {
     fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>> {
         self.ast_map.as_ref()
     }
+
+    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self }
 }
 
 impl<'ast> pprust::PpAnn for NoAnn<'ast> {}
@@ -183,6 +185,8 @@ impl<'ast> PrinterSupport<'ast> for IdentifiedAnnotation<'ast> {
     fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>> {
         self.ast_map.as_ref()
     }
+
+    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self }
 }
 
 impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> {
@@ -232,6 +236,8 @@ impl<'ast> PrinterSupport<'ast> for HygieneAnnotation<'ast> {
     fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>> {
         self.ast_map.as_ref()
     }
+
+    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self }
 }
 
 impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> {
@@ -265,6 +271,8 @@ impl<'tcx> PrinterSupport<'tcx> for TypedAnnotation<'tcx> {
     fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'tcx>> {
         Some(&self.analysis.ty_cx.map)
     }
+
+    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self }
 }
 
 impl<'tcx> pprust::PpAnn for TypedAnnotation<'tcx> {
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs
index 9535ffaec0e..99624f1b1e7 100644
--- a/src/librustc_trans/trans/meth.rs
+++ b/src/librustc_trans/trans/meth.rs
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
+use arena::TypedArena;
 use back::abi;
-use llvm;
-use llvm::ValueRef;
+use back::link;
+use llvm::{mod, ValueRef, get_param};
 use metadata::csearch;
-use middle::subst::{Substs};
+use middle::subst::{Subst, Substs};
 use middle::subst::VecPerParamSpace;
 use middle::subst;
 use middle::traits;
@@ -370,6 +370,10 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let llfn = trans_fn_pointer_shim(bcx.ccx(), fn_ty);
             Callee { bcx: bcx, data: Fn(llfn) }
         }
+        traits::VtableObject(ref data) => {
+            let llfn = trans_object_shim(bcx.ccx(), data.object_ty, trait_id, n_method);
+            Callee { bcx: bcx, data: Fn(llfn) }
+        }
         traits::VtableBuiltin(..) |
         traits::VtableParam(..) => {
             bcx.sess().bug(
@@ -503,6 +507,137 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     };
 }
 
+/// Generate a shim function that allows an object type like `SomeTrait` to
+/// implement the type `SomeTrait`. Imagine a trait definition:
+///
+///    trait SomeTrait { fn get(&self) -> int; ... }
+///
+/// And a generic bit of code:
+///
+///    fn foo<T:SomeTrait>(t: &T) {
+///        let x = SomeTrait::get;
+///        x(t)
+///    }
+///
+/// What is the value of `x` when `foo` is invoked with `T=SomeTrait`?
+/// The answer is that it it is a shim function generate by this
+/// routine:
+///
+///    fn shim(t: &SomeTrait) -> int {
+///        // ... call t.get() virtually ...
+///    }
+///
+/// In fact, all virtual calls can be thought of as normal trait calls
+/// that go through this shim function.
+pub fn trans_object_shim<'a, 'tcx>(
+    ccx: &'a CrateContext<'a, 'tcx>,
+    object_ty: Ty<'tcx>,
+    trait_id: ast::DefId,
+    method_offset_in_trait: uint)
+    -> ValueRef
+{
+    let _icx = push_ctxt("trans_object_shim");
+    let tcx = ccx.tcx();
+
+    debug!("trans_object_shim(object_ty={}, trait_id={}, n_method={})",
+           object_ty.repr(tcx),
+           trait_id.repr(tcx),
+           method_offset_in_trait);
+
+    let object_trait_ref =
+        match object_ty.sty {
+            ty::ty_trait(ref data) => {
+                data.principal_trait_ref_with_self_ty(tcx, object_ty)
+            }
+            _ => {
+                tcx.sess.bug(format!("trans_object_shim() called on non-object: {}",
+                                     object_ty.repr(tcx)).as_slice());
+            }
+        };
+
+    // Upcast to the trait in question and extract out the substitutions.
+    let upcast_trait_ref = traits::upcast(ccx.tcx(), object_trait_ref.clone(), trait_id).unwrap();
+    let object_substs = upcast_trait_ref.substs().clone().erase_regions();
+    debug!("trans_object_shim: object_substs={}", object_substs.repr(tcx));
+
+    // Lookup the type of this method as deeclared in the trait and apply substitutions.
+    let method_ty = match ty::trait_item(tcx, trait_id, method_offset_in_trait) {
+        ty::MethodTraitItem(method) => method,
+        ty::TypeTraitItem(_) => {
+            tcx.sess.bug("can't create a method shim for an associated type")
+        }
+    };
+    let fty = method_ty.fty.subst(tcx, &object_substs);
+    let fty = tcx.mk_bare_fn(fty);
+    debug!("trans_object_shim: fty={}", fty.repr(tcx));
+
+    //
+    let method_bare_fn_ty =
+        ty::mk_bare_fn(tcx, None, fty);
+    let function_name =
+        link::mangle_internal_name_by_type_and_seq(ccx, method_bare_fn_ty, "object_shim");
+    let llfn =
+        decl_internal_rust_fn(ccx, method_bare_fn_ty, function_name.as_slice());
+
+    //
+    let block_arena = TypedArena::new();
+    let empty_substs = Substs::trans_empty();
+    let fcx = new_fn_ctxt(ccx,
+                          llfn,
+                          ast::DUMMY_NODE_ID,
+                          false,
+                          fty.sig.0.output,
+                          &empty_substs,
+                          None,
+                          &block_arena);
+    let mut bcx = init_function(&fcx, false, fty.sig.0.output);
+
+    // the first argument (`self`) will be a trait object
+    let llobject = get_param(fcx.llfn, fcx.arg_pos(0) as u32);
+
+    debug!("trans_object_shim: llobject={}",
+           bcx.val_to_string(llobject));
+
+    // the remaining arguments will be, well, whatever they are
+    let llargs: Vec<_> =
+        fty.sig.0.inputs[1..].iter()
+        .enumerate()
+        .map(|(i, _)| {
+            let llarg = get_param(fcx.llfn, fcx.arg_pos(i+1) as u32);
+            debug!("trans_object_shim: input #{} == {}",
+                   i, bcx.val_to_string(llarg));
+            llarg
+        })
+        .collect();
+    assert!(!fcx.needs_ret_allocas);
+
+    let dest =
+        fcx.llretslotptr.get().map(
+            |_| expr::SaveIn(fcx.get_ret_slot(bcx, fty.sig.0.output, "ret_slot")));
+
+    let method_offset_in_vtable =
+        traits::get_vtable_index_of_object_method(bcx.tcx(),
+                                                  object_trait_ref.clone(),
+                                                  trait_id,
+                                                  method_offset_in_trait);
+    debug!("trans_object_shim: method_offset_in_vtable={}",
+           method_offset_in_vtable);
+
+    bcx = trans_call_inner(bcx,
+                           None,
+                           method_bare_fn_ty,
+                           |bcx, _| trans_trait_callee_from_llval(bcx,
+                                                                  method_bare_fn_ty,
+                                                                  method_offset_in_vtable,
+                                                                  llobject),
+                           ArgVals(llargs.as_slice()),
+                           dest).bcx;
+
+    finish_fn(&fcx, bcx, fty.sig.0.output);
+
+    llfn
+}
+
 /// Creates a returns a dynamic vtable for the given type and vtable origin.
 /// This is used only for objects.
 ///
@@ -560,6 +695,14 @@ pub fn get_vtable<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 let llfn = vec![trans_fn_pointer_shim(bcx.ccx(), bare_fn_ty)];
                 llfn.into_iter()
             }
+            traits::VtableObject(ref data) => {
+                // this would imply that the Self type being erased is
+                // an object type; this cannot happen because we
+                // cannot cast an unsized type into a trait object
+                bcx.sess().bug(
+                    format!("cannot get vtable for an object type: {}",
+                            data.repr(bcx.tcx())).as_slice());
+            }
             traits::VtableParam => {
                 bcx.sess().bug(
                     format!("resolved vtable for {} to bad vtable {} in trans",
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index a751b65a0f8..ee859bbe8f5 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -633,17 +633,16 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
               target_trait_def_id: ast::DefId)
               -> ty::PolyTraitRef<'tcx>
     {
-        for super_trait_ref in traits::supertraits(self.tcx(), source_trait_ref.clone()) {
-            if super_trait_ref.def_id() == target_trait_def_id {
-                return super_trait_ref;
+        match traits::upcast(self.tcx(), source_trait_ref.clone(), target_trait_def_id) {
+            Some(super_trait_ref) => super_trait_ref,
+            None => {
+                self.tcx().sess.span_bug(
+                    self.span,
+                    format!("cannot upcast `{}` to `{}`",
+                            source_trait_ref.repr(self.tcx()),
+                            target_trait_def_id.repr(self.tcx()))[]);
             }
         }
-
-        self.tcx().sess.span_bug(
-            self.span,
-            format!("cannot upcast `{}` to `{}`",
-                    source_trait_ref.repr(self.tcx()),
-                    target_trait_def_id.repr(self.tcx()))[]);
     }
 
     fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &ty::Binder<T>) -> T
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index b8920ffde58..52860abb6f9 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -310,7 +310,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(), self_ty);
         self.elaborate_bounds(&[trait_ref.clone()], false, |this, new_trait_ref, m, method_num| {
             let vtable_index =
-                get_method_index(tcx, &new_trait_ref, trait_ref.clone(), method_num);
+                traits::get_vtable_index_of_object_method(tcx,
+                                                          trait_ref.clone(),
+                                                          new_trait_ref.def_id(),
+                                                          method_num);
 
             let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs());
 
@@ -999,35 +1002,6 @@ fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>,
         .and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m)))
 }
 
-// Determine the index of a method in the list of all methods belonging
-// to a trait and its supertraits.
-fn get_method_index<'tcx>(tcx: &ty::ctxt<'tcx>,
-                          trait_ref: &ty::PolyTraitRef<'tcx>,
-                          subtrait: ty::PolyTraitRef<'tcx>,
-                          n_method: uint) -> uint {
-    // We need to figure the "real index" of the method in a
-    // listing of all the methods of an object. We do this by
-    // iterating down the supertraits of the object's trait until
-    // we find the trait the method came from, counting up the
-    // methods from them.
-    let mut method_count = n_method;
-    ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| {
-        if bound_ref.def_id() == trait_ref.def_id() {
-            false
-        } else {
-            let trait_items = ty::trait_items(tcx, bound_ref.def_id());
-            for trait_item in trait_items.iter() {
-                match *trait_item {
-                    ty::MethodTraitItem(_) => method_count += 1,
-                    ty::TypeTraitItem(_) => {}
-                }
-            }
-            true
-        }
-    });
-    method_count
-}
-
 impl<'tcx> Candidate<'tcx> {
     fn to_unadjusted_pick(&self) -> Pick<'tcx> {
         Pick {
diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs
index c85b542b6ca..1ef6c114032 100644
--- a/src/librustc_typeck/check/vtable.rs
+++ b/src/librustc_typeck/check/vtable.rs
@@ -9,8 +9,7 @@
 // except according to those terms.
 
 use check::{FnCtxt, structurally_resolved_type};
-use middle::subst::{FnSpace, SelfSpace};
-use middle::traits;
+use middle::traits::{mod, ObjectSafetyViolation, MethodViolationCode};
 use middle::traits::{Obligation, ObligationCause};
 use middle::traits::report_fulfillment_errors;
 use middle::ty::{mod, Ty, AsPredicate};
@@ -133,217 +132,56 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
                                  object_trait: &ty::TyTrait<'tcx>,
                                  span: Span)
 {
-    // Also check that the type `object_trait` specifies all
-    // associated types for all supertraits.
-    let mut associated_types: FnvHashSet<(ast::DefId, ast::Name)> = FnvHashSet::new();
-
     let object_trait_ref =
         object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err);
-    for tr in traits::supertraits(tcx, object_trait_ref.clone()) {
-        check_object_safety_inner(tcx, &tr, span);
 
-        let trait_def = ty::lookup_trait_def(tcx, object_trait_ref.def_id());
-        for &associated_type_name in trait_def.associated_type_names.iter() {
-            associated_types.insert((object_trait_ref.def_id(), associated_type_name));
-        }
+    if traits::is_object_safe(tcx, object_trait_ref.clone()) {
+        return;
     }
 
-    for projection_bound in object_trait.bounds.projection_bounds.iter() {
-        let pair = (projection_bound.0.projection_ty.trait_ref.def_id,
-                    projection_bound.0.projection_ty.item_name);
-        associated_types.remove(&pair);
-    }
+    span_err!(tcx.sess, span, E0038,
+              "cannot convert to a trait object because trait `{}` is not object-safe",
+              ty::item_path_str(tcx, object_trait_ref.def_id()));
 
-    for (trait_def_id, name) in associated_types.into_iter() {
-        tcx.sess.span_err(
-            span,
-            format!("the value of the associated type `{}` (from the trait `{}`) must be specified",
-                    name.user_string(tcx),
-                    ty::item_path_str(tcx, trait_def_id)).as_slice());
-    }
-}
-
-fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                   object_trait: &ty::PolyTraitRef<'tcx>,
-                                   span: Span) {
-    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, object_trait, &**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[]);
-        }
-    }
-
-    /// Returns a vec of error messages. If the vec is empty - no errors!
-    ///
-    /// 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), (b) the call must go through a vtable and hence cannot be monomorphized and
-    /// (c) the trait contains static methods which can't be called because we don't know the
-    /// concrete type.
-    fn check_object_safety_of_method<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                           object_trait: &ty::PolyTraitRef<'tcx>,
-                                           method: &ty::Method<'tcx>)
-                                           -> Vec<String> {
-        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))
+    let violations = traits::object_safety_violations(tcx, object_trait_ref.clone());
+    for violation in violations.into_iter() {
+        match violation {
+            ObjectSafetyViolation::SizedSelf => {
+                tcx.sess.span_note(
+                    span,
+                    "the trait cannot require that `Self : Sized`");
             }
 
-            ty::StaticExplicitSelfCategory => {
-                // Static methods are never object safe (reason (c)).
-                msgs.push(format!("cannot call a static method (`{}`) \
-                                   through a trait object",
-                                  method_name));
-                return msgs;
+            ObjectSafetyViolation::Method(method, MethodViolationCode::ByValueSelf) => {
+                tcx.sess.span_note(
+                    span,
+                    format!("method `{}` has a receiver type of `Self`, \
+                             which cannot be used with a trait object",
+                            method.name.user_string(tcx)).as_slice());
             }
-            ty::ByReferenceExplicitSelfCategory(..) |
-            ty::ByBoxExplicitSelfCategory => {}
-        }
 
-        // reason (a) above
-        let check_for_self_ty = |&: ty| {
-            if contains_illegal_self_type_reference(tcx, object_trait.def_id(), ty) {
-                Some(format!(
-                    "cannot call a method (`{}`) whose type contains \
-                     a self-type (`{}`) through a trait object",
-                    method_name, ty.user_string(tcx)))
-            } else {
-                None
+            ObjectSafetyViolation::Method(method, MethodViolationCode::StaticMethod) => {
+                tcx.sess.span_note(
+                    span,
+                    format!("method `{}` has no receiver",
+                            method.name.user_string(tcx)).as_slice());
             }
-        };
-        let ref sig = method.fty.sig;
-        for &input_ty in sig.0.inputs[1..].iter() {
-            if let Some(msg) = check_for_self_ty(input_ty) {
-                msgs.push(msg);
+
+            ObjectSafetyViolation::Method(method, MethodViolationCode::ReferencesSelf) => {
+                tcx.sess.span_note(
+                    span,
+                    format!("method `{}` references the `Self` type \
+                             in its arguments or return type",
+                            method.name.user_string(tcx)).as_slice());
+            }
+
+            ObjectSafetyViolation::Method(method, MethodViolationCode::Generic) => {
+                tcx.sess.span_note(
+                    span,
+                    format!("method `{}` has generic type parameters",
+                            method.name.user_string(tcx)).as_slice());
             }
         }
-        if let ty::FnConverging(result_type) = sig.0.output {
-            if let Some(msg) = check_for_self_ty(result_type) {
-                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
-    }
-
-    fn contains_illegal_self_type_reference<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                                  trait_def_id: ast::DefId,
-                                                  ty: Ty<'tcx>)
-                                                  -> bool
-    {
-        // This is somewhat subtle. In general, we want to forbid
-        // references to `Self` in the argument and return types,
-        // since the value of `Self` is erased. However, there is one
-        // exception: it is ok to reference `Self` in order to access
-        // an associated type of the current trait, since we retain
-        // the value of those associated types in the object type
-        // itself.
-        //
-        // ```rust
-        // trait SuperTrait {
-        //     type X;
-        // }
-        //
-        // trait Trait : SuperTrait {
-        //     type Y;
-        //     fn foo(&self, x: Self) // bad
-        //     fn foo(&self) -> Self // bad
-        //     fn foo(&self) -> Option<Self> // bad
-        //     fn foo(&self) -> Self::Y // OK, desugars to next example
-        //     fn foo(&self) -> <Self as Trait>::Y // OK
-        //     fn foo(&self) -> Self::X // OK, desugars to next example
-        //     fn foo(&self) -> <Self as SuperTrait>::X // OK
-        // }
-        // ```
-        //
-        // However, it is not as simple as allowing `Self` in a projected
-        // type, because there are illegal ways to use `Self` as well:
-        //
-        // ```rust
-        // trait Trait : SuperTrait {
-        //     ...
-        //     fn foo(&self) -> <Self as SomeOtherTrait>::X;
-        // }
-        // ```
-        //
-        // Here we will not have the type of `X` recorded in the
-        // object type, and we cannot resolve `Self as SomeOtherTrait`
-        // without knowing what `Self` is.
-
-        let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None;
-        let mut error = false;
-        ty::maybe_walk_ty(ty, |ty| {
-            match ty.sty {
-                ty::ty_param(ref param_ty) => {
-                    if param_ty.space == SelfSpace {
-                        error = true;
-                    }
-
-                    false // no contained types to walk
-                }
-
-                ty::ty_projection(ref data) => {
-                    // This is a projected type `<Foo as SomeTrait>::X`.
-
-                    // Compute supertraits of current trait lazilly.
-                    if supertraits.is_none() {
-                        let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
-                        let trait_ref = ty::Binder(trait_def.trait_ref.clone());
-                        supertraits = Some(traits::supertraits(tcx, trait_ref).collect());
-                    }
-
-                    // Determine whether the trait reference `Foo as
-                    // SomeTrait` is in fact a supertrait of the
-                    // current trait. In that case, this type is
-                    // legal, because the type `X` will be specified
-                    // in the object type.  Note that we can just use
-                    // direct equality here because all of these types
-                    // are part of the formal parameter listing, and
-                    // hence there should be no inference variables.
-                    let projection_trait_ref = ty::Binder(data.trait_ref.clone());
-                    let is_supertrait_of_current_trait =
-                        supertraits.as_ref().unwrap().contains(&projection_trait_ref);
-
-                    if is_supertrait_of_current_trait {
-                        false // do not walk contained types, do not report error, do collect $200
-                    } else {
-                        true // DO walk contained types, POSSIBLY reporting an error
-                    }
-                }
-
-                _ => true, // walk contained types, if any
-            }
-        });
-
-        error
     }
 }
 
@@ -392,7 +230,7 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             cause.clone());
     }
 
-    // Finally, create obligations for the projection predicates.
+    // Create obligations for the projection predicates.
     let projection_bounds =
         object_trait.projection_bounds_with_self_ty(fcx.tcx(), referent_ty);
     for projection_bound in projection_bounds.iter() {
@@ -401,9 +239,47 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         fcx.register_predicate(projection_obligation);
     }
 
+    // Finally, check that there IS a projection predicate for every associated type.
+    check_object_type_binds_all_associated_types(fcx.tcx(),
+                                                 span,
+                                                 object_trait);
+
     object_trait_ref
 }
 
+fn check_object_type_binds_all_associated_types<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                                      span: Span,
+                                                      object_trait: &ty::TyTrait<'tcx>)
+{
+    let object_trait_ref =
+        object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err);
+
+    let mut associated_types: FnvHashSet<(ast::DefId, ast::Name)> =
+        traits::supertraits(tcx, object_trait_ref.clone())
+        .flat_map(|tr| {
+            let trait_def = ty::lookup_trait_def(tcx, tr.def_id());
+            trait_def.associated_type_names
+                .clone()
+                .into_iter()
+                .map(move |associated_type_name| (tr.def_id(), associated_type_name))
+        })
+        .collect();
+
+    for projection_bound in object_trait.bounds.projection_bounds.iter() {
+        let pair = (projection_bound.0.projection_ty.trait_ref.def_id,
+                    projection_bound.0.projection_ty.item_name);
+        associated_types.remove(&pair);
+    }
+
+    for (trait_def_id, name) in associated_types.into_iter() {
+        tcx.sess.span_err(
+            span,
+            format!("the value of the associated type `{}` (from the trait `{}`) must be specified",
+                    name.user_string(tcx),
+                    ty::item_path_str(tcx, trait_def_id)).as_slice());
+    }
+}
+
 pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) {
     debug!("select_all_fcx_obligations_or_error");
 
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 9e184db3b84..fe61b3de2cf 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -843,6 +843,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let bounds = compute_bounds(ccx,
                                 self_param_ty.to_ty(ccx.tcx),
                                 bounds.as_slice(),
+                                SizedByDefault::No,
                                 it.span);
 
     let associated_type_names: Vec<_> =
@@ -1098,6 +1099,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 let bounds = compute_bounds(ccx,
                                             assoc_ty,
                                             assoc_type_def.bounds.as_slice(),
+                                            SizedByDefault::Yes,
                                             assoc_type_def.span);
 
                 ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter()
@@ -1306,6 +1308,7 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
     let bounds = compute_bounds(this,
                                 param_ty.to_ty(this.tcx()),
                                 param.bounds[],
+                                SizedByDefault::Yes,
                                 param.span);
     let default = match param.default {
         None => None,
@@ -1342,29 +1345,35 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
     def
 }
 
+enum SizedByDefault { Yes, No }
+
 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
 /// built-in trait (formerly known as kind): Send.
 fn compute_bounds<'tcx,AC>(this: &AC,
                            param_ty: ty::Ty<'tcx>,
                            ast_bounds: &[ast::TyParamBound],
+                           sized_by_default: SizedByDefault,
                            span: Span)
                            -> ty::ParamBounds<'tcx>
-                           where AC: AstConv<'tcx> {
+                           where AC: AstConv<'tcx>
+{
     let mut param_bounds = conv_param_bounds(this,
                                              span,
                                              param_ty,
                                              ast_bounds);
 
-    add_unsized_bound(this,
-                      &mut param_bounds.builtin_bounds,
-                      ast_bounds,
-                      span);
+    if let SizedByDefault::Yes = sized_by_default {
+        add_unsized_bound(this,
+                          &mut param_bounds.builtin_bounds,
+                          ast_bounds,
+                          span);
 
-    check_bounds_compatible(this.tcx(),
-                            param_ty,
-                            &param_bounds,
-                            span);
+        check_bounds_compatible(this.tcx(),
+                                param_ty,
+                                &param_bounds,
+                                span);
+    }
 
     param_bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
 
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index 5623c0f0e53..4f277cc868a 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -12,7 +12,7 @@ use clean::*;
 use std::iter::Extend;
 use std::mem::{replace, swap};
 
-pub trait DocFolder {
+pub trait DocFolder : Sized {
     fn fold_item(&mut self, item: Item) -> Option<Item> {
         self.fold_item_recur(item)
     }
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 539fcb23bb0..8f7de1c4dca 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -232,6 +232,7 @@ use error::{FromError, Error};
 use fmt;
 use int;
 use iter::{Iterator, IteratorExt};
+use kinds::Sized;
 use mem::transmute;
 use ops::FnOnce;
 use option::Option;
@@ -1030,11 +1031,25 @@ pub trait Writer {
     fn write_fmt(&mut self, fmt: fmt::Arguments) -> IoResult<()> {
         // Create a shim which translates a Writer to a fmt::Writer and saves
         // off I/O errors. instead of discarding them
-        struct Adaptor<'a, T:'a> {
+        struct Adaptor<'a, Sized? T:'a> {
             inner: &'a mut T,
             error: IoResult<()>,
         }
 
+        #[cfg(not(stage0))]
+        impl<'a, Sized? T: Writer> fmt::Writer for Adaptor<'a, T> {
+            fn write_str(&mut self, s: &str) -> fmt::Result {
+                match self.inner.write(s.as_bytes()) {
+                    Ok(()) => Ok(()),
+                    Err(e) => {
+                        self.error = Err(e);
+                        Err(fmt::Error)
+                    }
+                }
+            }
+        }
+
+        #[cfg(stage0)]
         impl<'a, T: Writer> fmt::Writer for Adaptor<'a, T> {
             fn write_str(&mut self, s: &str) -> fmt::Result {
                 match self.inner.write(s.as_bytes()) {
@@ -1629,16 +1644,24 @@ pub trait Acceptor<T> {
 /// `Some`. The `Some` contains the `IoResult` representing whether the
 /// connection attempt was successful.  A successful connection will be wrapped
 /// in `Ok`. A failed connection is represented as an `Err`.
-pub struct IncomingConnections<'a, A:'a> {
+pub struct IncomingConnections<'a, Sized? A:'a> {
     inc: &'a mut A,
 }
 
+#[cfg(stage0)]
 impl<'a, T, A: Acceptor<T>> Iterator<IoResult<T>> for IncomingConnections<'a, A> {
     fn next(&mut self) -> Option<IoResult<T>> {
         Some(self.inc.accept())
     }
 }
 
+#[cfg(not(stage0))]
+impl<'a, T, Sized? A: Acceptor<T>> Iterator<IoResult<T>> for IncomingConnections<'a, A> {
+    fn next(&mut self) -> Option<IoResult<T>> {
+        Some(self.inc.accept())
+    }
+}
+
 /// Creates a standard error for a commonly used flavor of error. The `detail`
 /// field of the returned error will always be `None`.
 ///
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index c134b11a0eb..3d3068f6868 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -53,7 +53,7 @@ impl<T> MoveMap<T> for OwnedSlice<T> {
     }
 }
 
-pub trait Folder {
+pub trait Folder : Sized {
     // Any additions to this trait should happen in form
     // of a call to a public `noop_*` function that only calls
     // out to the folder again, not other `noop_*` functions.
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index e532c76347f..a1fe63e3f6f 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -54,8 +54,7 @@ pub enum FnKind<'a> {
 /// explicitly, you need to override each method.  (And you also need
 /// to monitor future changes to `Visitor` in case a new method with a
 /// new default implementation gets introduced.)
-pub trait Visitor<'v> {
-
+pub trait Visitor<'v> : Sized {
     fn visit_name(&mut self, _span: Span, _name: Name) {
         // Nothing to do.
     }
diff --git a/src/test/auxiliary/method_self_arg2.rs b/src/test/auxiliary/method_self_arg2.rs
index e1e79b59e3e..eb4d62b01ad 100644
--- a/src/test/auxiliary/method_self_arg2.rs
+++ b/src/test/auxiliary/method_self_arg2.rs
@@ -32,7 +32,7 @@ impl Foo {
     }
 }
 
-pub trait Bar {
+pub trait Bar : Sized {
     fn foo1(&self);
     fn foo2(self);
     fn foo3(self: Box<Self>);
diff --git a/src/test/compile-fail/dst-sized-trait-param.rs b/src/test/compile-fail/dst-sized-trait-param.rs
index 750b475adb2..ea5becbf229 100644
--- a/src/test/compile-fail/dst-sized-trait-param.rs
+++ b/src/test/compile-fail/dst-sized-trait-param.rs
@@ -12,7 +12,7 @@
 // parameter, the corresponding value must be sized. Also that the
 // self type must be sized if appropriate.
 
-trait Foo<T> { fn take(self, x: &T) { } } // Note: T is sized
+trait Foo<T> : Sized { fn take(self, x: &T) { } } // Note: T is sized
 
 impl Foo<[int]> for uint { }
 //~^ ERROR the trait `core::kinds::Sized` is not implemented for the type `[int]`
diff --git a/src/test/compile-fail/issue-18959.rs b/src/test/compile-fail/issue-18959.rs
index 3d126790335..1a792eb6e76 100644
--- a/src/test/compile-fail/issue-18959.rs
+++ b/src/test/compile-fail/issue-18959.rs
@@ -21,6 +21,6 @@ impl Foo for Thing {
 
 fn main() {
     let mut thing = Thing;
-    let test: &Bar = &mut thing; //~ ERROR cannot convert to a trait object because trait `Foo`
+    let test: &Bar = &mut thing; //~ ERROR cannot convert to a trait object
     foo(test);
 }
diff --git a/src/test/compile-fail/issue-5543.rs b/src/test/compile-fail/issue-5543.rs
index bbd41b28f03..f970cdb1b83 100644
--- a/src/test/compile-fail/issue-5543.rs
+++ b/src/test/compile-fail/issue-5543.rs
@@ -15,5 +15,4 @@ fn main() {
     let r: Box<Foo> = box 5;
     let _m: Box<Foo> = r as Box<Foo>;
     //~^ ERROR `core::kinds::Sized` is not implemented for the type `Foo`
-    //~| ERROR `Foo` is not implemented for the type `Foo`
 }
diff --git a/src/test/compile-fail/object-safety-by-value-self.rs b/src/test/compile-fail/object-safety-by-value-self.rs
new file mode 100644
index 00000000000..5ebcc8516ca
--- /dev/null
+++ b/src/test/compile-fail/object-safety-by-value-self.rs
@@ -0,0 +1,47 @@
+// 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.
+
+// Check that we correctly prevent users from making trait objects
+// from traits with a `fn(self)` method.
+
+trait Bar {
+    fn bar(self);
+}
+
+trait Baz {
+    fn baz(self: Self);
+}
+
+fn make_bar<T:Bar>(t: &T) -> &Bar {
+    t
+        //~^ ERROR `Bar` is not object-safe
+        //~| NOTE method `bar` has a receiver type of `Self`
+}
+
+fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
+    t as &Bar
+        //~^ ERROR `Bar` is not object-safe
+        //~| NOTE method `bar` has a receiver type of `Self`
+}
+
+fn make_baz<T:Baz>(t: &T) -> &Baz {
+    t
+        //~^ ERROR `Baz` is not object-safe
+        //~| NOTE method `baz` has a receiver type of `Self`
+}
+
+fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
+    t as &Baz
+        //~^ ERROR `Baz` is not object-safe
+        //~| NOTE method `baz` has a receiver type of `Self`
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass/issue-7320.rs b/src/test/compile-fail/object-safety-generics.rs
similarity index 50%
rename from src/test/run-pass/issue-7320.rs
rename to src/test/compile-fail/object-safety-generics.rs
index c7087f8e3a8..0ca706404c1 100644
--- a/src/test/run-pass/issue-7320.rs
+++ b/src/test/compile-fail/object-safety-generics.rs
@@ -8,11 +8,24 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// Check that we correctly prevent users from making trait objects
+// from traits with generic methods.
 
-trait Foo {
-    fn foo(self: Box<Self>) { bar(self as Box<Foo>); }
+trait Bar {
+    fn bar<T>(&self, t: T);
 }
 
-fn bar(_b: Box<Foo>) { }
+fn make_bar<T:Bar>(t: &T) -> &Bar {
+    t
+        //~^ ERROR `Bar` is not object-safe
+        //~| NOTE method `bar` has generic type parameters
+}
 
-fn main() {}
+fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
+    t as &Bar
+        //~^ ERROR `Bar` is not object-safe
+        //~| NOTE method `bar` has generic type parameters
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/object-safety-mentions-Self.rs b/src/test/compile-fail/object-safety-mentions-Self.rs
new file mode 100644
index 00000000000..df0f44c1391
--- /dev/null
+++ b/src/test/compile-fail/object-safety-mentions-Self.rs
@@ -0,0 +1,47 @@
+// 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.
+
+// Check that we correctly prevent users from making trait objects
+// form traits that make use of `Self` in an argument or return position.
+
+trait Bar {
+    fn bar(&self, x: &Self);
+}
+
+trait Baz {
+    fn bar(&self) -> Self;
+}
+
+fn make_bar<T:Bar>(t: &T) -> &Bar {
+    t
+        //~^ ERROR `Bar` is not object-safe
+        //~| NOTE method `bar` references the `Self` type in its arguments or return type
+}
+
+fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
+    t as &Bar
+        //~^ ERROR `Bar` is not object-safe
+        //~| NOTE method `bar` references the `Self` type in its arguments or return type
+}
+
+fn make_baz<T:Baz>(t: &T) -> &Baz {
+    t
+        //~^ ERROR `Baz` is not object-safe
+        //~| NOTE method `bar` references the `Self` type in its arguments or return type
+}
+
+fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
+    t as &Baz
+        //~^ ERROR `Baz` is not object-safe
+        //~| NOTE method `bar` references the `Self` type in its arguments or return type
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/object-safety-no-static.rs b/src/test/compile-fail/object-safety-no-static.rs
new file mode 100644
index 00000000000..6a010d49692
--- /dev/null
+++ b/src/test/compile-fail/object-safety-no-static.rs
@@ -0,0 +1,31 @@
+// 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.
+
+// Check that we correctly prevent users from making trait objects
+// from traits with static methods.
+
+trait Foo {
+    fn foo();
+}
+
+fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<Foo+'static> {
+    b
+        //~^ ERROR cannot convert to a trait object
+        //~| NOTE method `foo` has no receiver
+}
+
+fn foo_explicit<T:Foo+'static>(b: Box<T>) -> Box<Foo+'static> {
+    b as Box<Foo>
+        //~^ ERROR cannot convert to a trait object
+        //~| NOTE method `foo` has no receiver
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/object-safety-sized-2.rs b/src/test/compile-fail/object-safety-sized-2.rs
new file mode 100644
index 00000000000..3a02461bbb2
--- /dev/null
+++ b/src/test/compile-fail/object-safety-sized-2.rs
@@ -0,0 +1,33 @@
+// 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.
+
+// Check that we correctly prevent users from making trait objects
+// from traits where `Self : Sized`.
+
+trait Bar
+    where Self : Sized
+{
+    fn bar<T>(&self, t: T);
+}
+
+fn make_bar<T:Bar>(t: &T) -> &Bar {
+    t
+        //~^ ERROR `Bar` is not object-safe
+        //~| NOTE the trait cannot require that `Self : Sized`
+}
+
+fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
+    t as &Bar
+        //~^ ERROR `Bar` is not object-safe
+        //~| NOTE the trait cannot require that `Self : Sized`
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/object-safety-sized.rs b/src/test/compile-fail/object-safety-sized.rs
new file mode 100644
index 00000000000..bc214f6f3d9
--- /dev/null
+++ b/src/test/compile-fail/object-safety-sized.rs
@@ -0,0 +1,31 @@
+// 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.
+
+// Check that we correctly prevent users from making trait objects
+// from traits where `Self : Sized`.
+
+trait Bar : Sized {
+    fn bar<T>(&self, t: T);
+}
+
+fn make_bar<T:Bar>(t: &T) -> &Bar {
+    t
+        //~^ ERROR `Bar` is not object-safe
+        //~| NOTE the trait cannot require that `Self : Sized`
+}
+
+fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
+    t as &Bar
+        //~^ ERROR `Bar` is not object-safe
+        //~| NOTE the trait cannot require that `Self : Sized`
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/regions-infer-bound-from-trait-self.rs b/src/test/compile-fail/regions-infer-bound-from-trait-self.rs
index 25fd20b6ec5..aeb003ca5d0 100644
--- a/src/test/compile-fail/regions-infer-bound-from-trait-self.rs
+++ b/src/test/compile-fail/regions-infer-bound-from-trait-self.rs
@@ -23,12 +23,12 @@ fn check_bound<'a,A:'a>(x: Inv<'a>, a: A) { }
 
 // In these case, `Self` inherits `'static`.
 
-trait InheritsFromStatic : 'static {
+trait InheritsFromStatic : Sized + 'static {
     fn foo1<'a>(self, x: Inv<'a>) {
         check_bound(x, self)
     }
 }
-trait InheritsFromStaticIndirectly : Static {
+trait InheritsFromStaticIndirectly : Sized + Static {
     fn foo1<'a>(self, x: Inv<'a>) {
         check_bound(x, self)
     }
@@ -37,13 +37,13 @@ trait InheritsFromStaticIndirectly : Static {
 
 // In these case, `Self` inherits `'a`.
 
-trait InheritsFromIs<'a> : 'a {
+trait InheritsFromIs<'a> : Sized + 'a {
     fn foo(self, x: Inv<'a>) {
         check_bound(x, self)
     }
 }
 
-trait InheritsFromIsIndirectly<'a> : Is<'a> {
+trait InheritsFromIsIndirectly<'a> : Sized + Is<'a> {
     fn foo(self, x: Inv<'a>) {
         check_bound(x, self)
     }
@@ -51,7 +51,7 @@ trait InheritsFromIsIndirectly<'a> : Is<'a> {
 
 // In this case, `Self` inherits nothing.
 
-trait InheritsFromNothing<'a> {
+trait InheritsFromNothing<'a> : Sized {
     fn foo(self, x: Inv<'a>) {
         check_bound(x, self)
             //~^ ERROR parameter type `Self` may not live long enough
diff --git a/src/test/compile-fail/trait-matching-lifetimes.rs b/src/test/compile-fail/trait-matching-lifetimes.rs
index f1b30166b5e..333730e0c4b 100644
--- a/src/test/compile-fail/trait-matching-lifetimes.rs
+++ b/src/test/compile-fail/trait-matching-lifetimes.rs
@@ -16,7 +16,7 @@ struct Foo<'a,'b> {
     y: &'b int,
 }
 
-trait Tr {
+trait Tr : Sized {
     fn foo(x: Self) {}
 }
 
diff --git a/src/test/compile-fail/trait-objects.rs b/src/test/compile-fail/trait-objects.rs
deleted file mode 100644
index 88b907a5cb9..00000000000
--- a/src/test/compile-fail/trait-objects.rs
+++ /dev/null
@@ -1,43 +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.
-
-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-safety-fn-body.rs b/src/test/compile-fail/trait-safety-fn-body.rs
index d174092e4d0..f894e2ee28e 100644
--- a/src/test/compile-fail/trait-safety-fn-body.rs
+++ b/src/test/compile-fail/trait-safety-fn-body.rs
@@ -11,7 +11,7 @@
 // Check that an unsafe impl does not imply that unsafe actions are
 // legal in the methods.
 
-unsafe trait UnsafeTrait {
+unsafe trait UnsafeTrait : Sized {
     fn foo(self) { }
 }
 
diff --git a/src/test/compile-fail/type-params-in-different-spaces-2.rs b/src/test/compile-fail/type-params-in-different-spaces-2.rs
index 9be64bf5346..3a4cc9e874e 100644
--- a/src/test/compile-fail/type-params-in-different-spaces-2.rs
+++ b/src/test/compile-fail/type-params-in-different-spaces-2.rs
@@ -11,7 +11,7 @@
 // Test static calls to make sure that we align the Self and input
 // type parameters on a trait correctly.
 
-trait Tr<T> {
+trait Tr<T> : Sized {
     fn op(T) -> Self;
 }
 
diff --git a/src/test/compile-fail/type-params-in-different-spaces-3.rs b/src/test/compile-fail/type-params-in-different-spaces-3.rs
index a3d69d53ba9..c113e1b7815 100644
--- a/src/test/compile-fail/type-params-in-different-spaces-3.rs
+++ b/src/test/compile-fail/type-params-in-different-spaces-3.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-trait Tr {
+trait Tr : Sized {
     fn test<X>(u: X) -> Self {
         u   //~ ERROR mismatched types
     }
diff --git a/src/test/compile-fail/unsized4.rs b/src/test/compile-fail/unsized4.rs
index 0537fc1f94a..f9ece8e6843 100644
--- a/src/test/compile-fail/unsized4.rs
+++ b/src/test/compile-fail/unsized4.rs
@@ -10,8 +10,7 @@
 
 // Test that bounds are sized-compatible.
 
-trait T {}
-
+trait T : Sized {}
 fn f<Sized? Y: T>() {
 //~^ERROR incompatible bounds on `Y`, bound `T` does not allow unsized type
 }
diff --git a/src/test/debuginfo/issue7712.rs b/src/test/debuginfo/issue7712.rs
index 948048ec272..94458a7fb4b 100644
--- a/src/test/debuginfo/issue7712.rs
+++ b/src/test/debuginfo/issue7712.rs
@@ -11,7 +11,7 @@
 // compile-flags:--debuginfo=1
 // min-lldb-version: 310
 
-pub trait TraitWithDefaultMethod {
+pub trait TraitWithDefaultMethod : Sized {
     fn method(self) {
         ()
     }
diff --git a/src/test/debuginfo/self-in-default-method.rs b/src/test/debuginfo/self-in-default-method.rs
index f8ef5b3d2fc..87884d2f956 100644
--- a/src/test/debuginfo/self-in-default-method.rs
+++ b/src/test/debuginfo/self-in-default-method.rs
@@ -118,7 +118,7 @@ struct Struct {
     x: int
 }
 
-trait Trait {
+trait Trait : Sized {
     fn self_by_ref(&self, arg1: int, arg2: int) -> int {
         zzz(); // #break
         arg1 + arg2
diff --git a/src/test/debuginfo/self-in-generic-default-method.rs b/src/test/debuginfo/self-in-generic-default-method.rs
index c2594df7d35..62b5e6872ee 100644
--- a/src/test/debuginfo/self-in-generic-default-method.rs
+++ b/src/test/debuginfo/self-in-generic-default-method.rs
@@ -118,7 +118,7 @@ struct Struct {
     x: int
 }
 
-trait Trait {
+trait Trait : Sized {
 
     fn self_by_ref<T>(&self, arg1: int, arg2: T) -> int {
         zzz(); // #break
diff --git a/src/test/run-pass/associated-types-impl-redirect.rs b/src/test/run-pass/associated-types-impl-redirect.rs
index a28cf346336..ce7f5dde2ad 100644
--- a/src/test/run-pass/associated-types-impl-redirect.rs
+++ b/src/test/run-pass/associated-types-impl-redirect.rs
@@ -19,6 +19,7 @@
 #![feature(associated_types, lang_items, unboxed_closures)]
 #![no_implicit_prelude]
 
+use std::kinds::Sized;
 use std::option::Option::{None, Some, mod};
 
 trait Iterator {
@@ -27,7 +28,7 @@ trait Iterator {
     fn next(&mut self) -> Option<Self::Item>;
 }
 
-trait IteratorExt: Iterator {
+trait IteratorExt: Iterator + Sized {
     fn by_ref(&mut self) -> ByRef<Self> {
         ByRef(self)
     }
diff --git a/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs b/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs
index 83686d92a7c..92daee5225d 100644
--- a/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs
+++ b/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs
@@ -21,7 +21,7 @@ trait Not {
     fn not(self) -> Self::Result;
 }
 
-trait Int: Not<Result=Self> {
+trait Int: Not<Result=Self> + Sized {
     fn count_ones(self) -> uint;
     fn count_zeros(self) -> uint {
         // neither works
diff --git a/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs b/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs
index 062d37556ec..7afaf290424 100644
--- a/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs
+++ b/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs
@@ -19,6 +19,7 @@
 #![feature(associated_types, lang_items, unboxed_closures)]
 #![no_implicit_prelude]
 
+use std::kinds::Sized;
 use std::option::Option::{None, Some, mod};
 
 trait Iterator {
@@ -27,7 +28,7 @@ trait Iterator {
     fn next(&mut self) -> Option<Self::Item>;
 }
 
-trait IteratorExt: Iterator {
+trait IteratorExt: Iterator + Sized {
     fn by_ref(&mut self) -> ByRef<Self> {
         ByRef(self)
     }
diff --git a/src/test/run-pass/bug-7183-generics.rs b/src/test/run-pass/bug-7183-generics.rs
index 8c4d10a2d59..bf8d303f341 100644
--- a/src/test/run-pass/bug-7183-generics.rs
+++ b/src/test/run-pass/bug-7183-generics.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-trait Speak {
+trait Speak : Sized {
     fn say(&self, s:&str) -> String;
     fn hi(&self) -> String { hello(self) }
 }
diff --git a/src/test/run-pass/builtin-superkinds-self-type.rs b/src/test/run-pass/builtin-superkinds-self-type.rs
index bf06bf8b8c6..d0db2542ccc 100644
--- a/src/test/run-pass/builtin-superkinds-self-type.rs
+++ b/src/test/run-pass/builtin-superkinds-self-type.rs
@@ -13,7 +13,7 @@
 
 use std::sync::mpsc::{Sender, channel};
 
-trait Foo : Send {
+trait Foo : Send + Sized {
     fn foo(self, tx: Sender<Self>) {
         tx.send(self).unwrap();
     }
diff --git a/src/test/run-pass/default-method-supertrait-vtable.rs b/src/test/run-pass/default-method-supertrait-vtable.rs
index 1b2b17f9917..727cada21fa 100644
--- a/src/test/run-pass/default-method-supertrait-vtable.rs
+++ b/src/test/run-pass/default-method-supertrait-vtable.rs
@@ -21,7 +21,7 @@ trait Y {
 }
 
 
-trait Z: Y {
+trait Z: Y + Sized {
     fn x(self) -> int {
         require_y(self)
     }
diff --git a/src/test/run-pass/issue-8171-default-method-self-inherit-builtin-trait.rs b/src/test/run-pass/issue-8171-default-method-self-inherit-builtin-trait.rs
index aaf2ecb7129..3238c24163e 100644
--- a/src/test/run-pass/issue-8171-default-method-self-inherit-builtin-trait.rs
+++ b/src/test/run-pass/issue-8171-default-method-self-inherit-builtin-trait.rs
@@ -16,7 +16,7 @@
 
 fn require_send<T: Send>(_: T){}
 
-trait TragicallySelfIsNotSend: Send {
+trait TragicallySelfIsNotSend: Send + Sized {
     fn x(self) {
         require_send(self);
     }
diff --git a/src/test/run-pass/method-self-arg-trait.rs b/src/test/run-pass/method-self-arg-trait.rs
index 36dfe83a9eb..29d100beb06 100644
--- a/src/test/run-pass/method-self-arg-trait.rs
+++ b/src/test/run-pass/method-self-arg-trait.rs
@@ -16,7 +16,7 @@ struct Foo;
 
 impl Copy for Foo {}
 
-trait Bar {
+trait Bar : Sized {
     fn foo1(&self);
     fn foo2(self);
     fn foo3(self: Box<Self>);
diff --git a/src/test/run-pass/self-in-mut-slot-default-method.rs b/src/test/run-pass/self-in-mut-slot-default-method.rs
index b4a46f34015..bced8012b68 100644
--- a/src/test/run-pass/self-in-mut-slot-default-method.rs
+++ b/src/test/run-pass/self-in-mut-slot-default-method.rs
@@ -13,7 +13,7 @@ struct X {
     a: int
 }
 
-trait Changer {
+trait Changer : Sized {
     fn change(mut self) -> Self {
         self.set_to(55);
         self
diff --git a/src/test/run-pass/trait-object-safety.rs b/src/test/run-pass/unboxed-closures-call-sugar-object.rs
similarity index 56%
rename from src/test/run-pass/trait-object-safety.rs
rename to src/test/run-pass/unboxed-closures-call-sugar-object.rs
index ed7284a8353..2dec53cc13a 100644
--- a/src/test/run-pass/trait-object-safety.rs
+++ b/src/test/run-pass/unboxed-closures-call-sugar-object.rs
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,19 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Check that object-safe methods are identified as such.
+#![feature(unboxed_closures)]
 
-trait Tr {
-    fn foo(&self);
+use std::ops::FnMut;
+
+fn make_adder(x: int) -> Box<FnMut(int)->int + 'static> {
+    box move |y| { x + y }
 }
 
-struct St;
-
-impl Tr for St {
-    fn foo(&self) {}
+pub fn main() {
+    let mut adder = make_adder(3);
+    let z = (*adder)(2);
+    println!("{}", z);
+    assert_eq!(z, 5);
 }
 
-fn main() {
-    let s: &Tr = &St;
-    s.foo();
-}