about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-06-26 17:37:29 -0700
committerbors <bors@rust-lang.org>2013-06-26 17:37:29 -0700
commit36d7f601d8d419ace8fdf14b2014a9cbf6245896 (patch)
tree47f511bde18a704513fb3b6b74f4b4b434c3cd73
parent32adc0e730636f04d72d31e24fbf1101a495ccb7 (diff)
parentc37ccac9313b52a8f4299b370fe33b0fbe202db4 (diff)
downloadrust-36d7f601d8d419ace8fdf14b2014a9cbf6245896.tar.gz
rust-36d7f601d8d419ace8fdf14b2014a9cbf6245896.zip
auto merge of #7354 : bblum/rust/trait-bounds, r=pcwalton
r? @nikomatsakis
-rw-r--r--src/libextra/io_util.rs6
-rw-r--r--src/libextra/test.rs2
-rw-r--r--src/librustc/metadata/encoder.rs2
-rw-r--r--src/librustc/middle/kind.rs21
-rw-r--r--src/librustc/middle/resolve.rs16
-rw-r--r--src/librustc/middle/ty.rs70
-rw-r--r--src/librustc/middle/typeck/astconv.rs75
-rw-r--r--src/libstd/io.rs13
-rw-r--r--src/libsyntax/ast.rs8
-rw-r--r--src/libsyntax/ext/build.rs10
-rw-r--r--src/libsyntax/ext/deriving/generic.rs2
-rw-r--r--src/libsyntax/ext/deriving/ty.rs4
-rw-r--r--src/libsyntax/ext/pipes/pipec.rs20
-rw-r--r--src/libsyntax/ext/pipes/proto.rs3
-rw-r--r--src/libsyntax/fold.rs11
-rw-r--r--src/libsyntax/parse/mod.rs4
-rw-r--r--src/libsyntax/parse/parser.rs20
-rw-r--r--src/libsyntax/print/pprust.rs27
-rw-r--r--src/libsyntax/visit.rs8
-rw-r--r--src/test/compile-fail/closure-bounds-cant-promote-superkind-in-struct.rs2
-rw-r--r--src/test/compile-fail/closure-bounds-subtype.rs4
-rw-r--r--src/test/compile-fail/kindck-nonsendable-1.rs6
-rw-r--r--src/test/compile-fail/kindck-owned-trait.rs4
-rw-r--r--src/test/compile-fail/kindck-owned.rs3
-rw-r--r--src/test/compile-fail/no-send-res-ports.rs2
-rw-r--r--src/test/compile-fail/trait-bounds-cant-coerce.rs2
-rw-r--r--src/test/compile-fail/trait-bounds-sugar.rs37
-rw-r--r--src/test/run-pass/closure-bounds-copyable-squiggle-closure.rs4
-rw-r--r--src/test/run-pass/closure-bounds-squiggle-closure-as-copyable-typaram.rs4
-rw-r--r--src/test/run-pass/kindck-owned-trait-contains-1.rs4
-rw-r--r--src/test/run-pass/regions-trait.rs4
-rw-r--r--src/test/run-pass/trait-bounds-basic.rs6
-rw-r--r--src/test/run-pass/trait-bounds-in-arc.rs103
33 files changed, 362 insertions, 145 deletions
diff --git a/src/libextra/io_util.rs b/src/libextra/io_util.rs
index 91424ae3ba2..11dea1c3a70 100644
--- a/src/libextra/io_util.rs
+++ b/src/libextra/io_util.rs
@@ -10,6 +10,7 @@
 
 use core::io::{Reader, BytesReader};
 use core::io;
+use core::cast;
 
 /// An implementation of the io::Reader interface which reads a buffer of bytes
 pub struct BufReader {
@@ -29,10 +30,13 @@ impl BufReader {
     }
 
     fn as_bytes_reader<A>(&self, f: &fn(&BytesReader) -> A) -> A {
+        // XXX FIXME(#5723)
+        let bytes = ::core::util::id::<&[u8]>(self.buf);
+        let bytes: &'static [u8] = unsafe { cast::transmute(bytes) };
         // Recreating the BytesReader state every call since
         // I can't get the borrowing to work correctly
         let bytes_reader = BytesReader {
-            bytes: ::core::util::id::<&[u8]>(self.buf),
+            bytes: bytes,
             pos: @mut *self.pos
         };
 
diff --git a/src/libextra/test.rs b/src/libextra/test.rs
index e058a098fa4..ee0d3649467 100644
--- a/src/libextra/test.rs
+++ b/src/libextra/test.rs
@@ -423,7 +423,7 @@ type MonitorMsg = (TestDesc, TestResult);
 
 fn run_tests(opts: &TestOpts,
              tests: ~[TestDescAndFn],
-             callback: @fn(e: TestEvent)) {
+             callback: &fn(e: TestEvent)) {
 
     let filtered_tests = filter_tests(opts, tests);
     let filtered_descs = filtered_tests.map(|t| copy t.desc);
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 9c28da10e40..cb47c88d3d4 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -959,7 +959,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_attributes(ebml_w, item.attrs);
         match ty.node {
             ast::ty_path(path, bounds, _) if path.idents.len() == 1 => {
-                assert!(bounds.is_empty());
+                assert!(bounds.is_none());
                 encode_impl_type_basename(ecx, ebml_w,
                                           ast_util::path_to_ident(path));
             }
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index b0b2a16cf89..a1f595fc896 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -128,7 +128,7 @@ fn check_item(item: @item, (cx, visitor): (Context, visit::vt<Context>)) {
                             // Yes, it's a destructor.
                             match self_type.node {
                                 ty_path(_, bounds, path_node_id) => {
-                                    assert!(bounds.is_empty());
+                                    assert!(bounds.is_none());
                                     let struct_def = cx.tcx.def_map.get_copy(
                                         &path_node_id);
                                     let struct_did =
@@ -169,10 +169,6 @@ fn with_appropriate_checker(cx: Context, id: node_id,
         let id = ast_util::def_id_of_def(fv.def).node;
         let var_t = ty::node_id_to_type(cx.tcx, id);
 
-        // FIXME(#3569): Once closure capabilities are restricted based on their
-        // incoming bounds, make this check conditional based on the bounds.
-        if !check_owned(cx, var_t, fv.span) { return; }
-
         // check that only immutable variables are implicitly copied in
         check_imm_free_var(cx, fv.def, fv.span);
 
@@ -184,10 +180,6 @@ fn with_appropriate_checker(cx: Context, id: node_id,
         let id = ast_util::def_id_of_def(fv.def).node;
         let var_t = ty::node_id_to_type(cx.tcx, id);
 
-        // FIXME(#3569): Once closure capabilities are restricted based on their
-        // incoming bounds, make this check conditional based on the bounds.
-        if !check_durable(cx.tcx, var_t, fv.span) { return; }
-
         // check that only immutable variables are implicitly copied in
         check_imm_free_var(cx, fv.def, fv.span);
 
@@ -293,9 +285,9 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt<Context>)) {
         expr_cast(source, _) => {
             check_cast_for_escaping_regions(cx, source, e);
             match ty::get(ty::expr_ty(cx.tcx, e)).sty {
-                ty::ty_trait(_, _, store, _, bounds) => {
+                ty::ty_trait(_, _, _, _, bounds) => {
                     let source_ty = ty::expr_ty(cx.tcx, source);
-                    check_trait_cast_bounds(cx, e.span, source_ty, bounds, store)
+                    check_trait_cast_bounds(cx, e.span, source_ty, bounds)
                 }
                 _ => { }
             }
@@ -391,7 +383,7 @@ pub fn check_freevar_bounds(cx: Context, sp: span, ty: ty::t,
 }
 
 pub fn check_trait_cast_bounds(cx: Context, sp: span, ty: ty::t,
-                               bounds: ty::BuiltinBounds, store: ty::TraitStore) {
+                               bounds: ty::BuiltinBounds) {
     do check_builtin_bounds(cx, ty, bounds) |missing| {
         cx.tcx.sess.span_err(sp,
             fmt!("cannot pack type `%s`, which does not fulfill \
@@ -399,11 +391,6 @@ pub fn check_trait_cast_bounds(cx: Context, sp: span, ty: ty::t,
                  ty_to_str(cx.tcx, ty), missing.user_string(cx.tcx),
                  bounds.user_string(cx.tcx)));
     }
-    // FIXME(#3569): Remove this check when the corresponding restriction
-    // is made with type contents.
-    if store == ty::UniqTraitStore && !ty::type_is_owned(cx.tcx, ty) {
-        cx.tcx.sess.span_err(sp, "uniquely-owned trait objects must be sendable");
-    }
 }
 
 fn is_nullary_variant(cx: Context, ex: @expr) -> bool {
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index a8626ca89aa..e06fd8f9717 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -4195,15 +4195,19 @@ impl Resolver {
                     }
                 }
 
-                for bounds.iter().advance |bound| {
-                    self.resolve_type_parameter_bound(bound, visitor);
-                }
+                do bounds.map |bound_vec| {
+                    for bound_vec.iter().advance |bound| {
+                        self.resolve_type_parameter_bound(bound, visitor);
+                    }
+                };
             }
 
             ty_closure(c) => {
-                for c.bounds.iter().advance |bound| {
-                    self.resolve_type_parameter_bound(bound, visitor);
-                }
+                do c.bounds.map |bounds| {
+                    for bounds.iter().advance |bound| {
+                        self.resolve_type_parameter_bound(bound, visitor);
+                    }
+                };
                 visit_ty(ty, ((), visitor));
             }
 
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index a7a69d51de2..4cea4c94972 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -2063,20 +2063,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
                 TC_MANAGED + statically_sized(nonowned(tc_mt(cx, mt, cache)))
             }
 
-            ty_trait(_, _, UniqTraitStore, _, _bounds) => {
-                // FIXME(#3569): Make this conditional on the trait's bounds.
-                TC_NONCOPY_TRAIT + TC_OWNED_POINTER
-            }
-
-            ty_trait(_, _, BoxTraitStore, mutbl, _bounds) => {
-                match mutbl {
-                    ast::m_mutbl => TC_MANAGED + TC_MUTABLE,
-                    _ => TC_MANAGED
-                }
-            }
-
-            ty_trait(_, _, RegionTraitStore(r), mutbl, _bounds) => {
-                borrowed_contents(r, mutbl)
+            ty_trait(_, _, store, mutbl, bounds) => {
+                trait_contents(store, mutbl, bounds)
             }
 
             ty_rptr(r, mt) => {
@@ -2261,16 +2249,23 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
     }
 
     fn closure_contents(cty: &ClosureTy) -> TypeContents {
+        // Closure contents are just like trait contents, but with potentially
+        // even more stuff.
         let st = match cty.sigil {
-            ast::BorrowedSigil => TC_BORROWED_POINTER,
-            ast::ManagedSigil => TC_MANAGED,
-            ast::OwnedSigil => if cty.bounds.contains_elem(BoundCopy) {
-                TC_OWNED_POINTER
-            } else {
-                TC_OWNED_POINTER + TC_NONCOPY_TRAIT
-            }
+            ast::BorrowedSigil =>
+                trait_contents(RegionTraitStore(cty.region), m_imm, cty.bounds)
+                    + TC_BORROWED_POINTER, // might be an env packet even if static
+            ast::ManagedSigil =>
+                trait_contents(BoxTraitStore, m_imm, cty.bounds),
+            ast::OwnedSigil =>
+                trait_contents(UniqTraitStore, m_imm, cty.bounds),
         };
+        // FIXME(#3569): This borrowed_contents call should be taken care of in
+        // trait_contents, after ~Traits and @Traits can have region bounds too.
+        // This one here is redundant for &fns but important for ~fns and @fns.
         let rt = borrowed_contents(cty.region, m_imm);
+        // This also prohibits "@once fn" from being copied, which allows it to
+        // be called. Neither way really makes much sense.
         let ot = match cty.onceness {
             ast::Once => TC_ONCE_CLOSURE,
             ast::Many => TC_NONE
@@ -2278,6 +2273,35 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
         st + rt + ot
     }
 
+    fn trait_contents(store: TraitStore, mutbl: ast::mutability,
+                      bounds: BuiltinBounds) -> TypeContents {
+        let st = match store {
+            UniqTraitStore      => TC_OWNED_POINTER,
+            BoxTraitStore       => TC_MANAGED,
+            RegionTraitStore(r) => borrowed_contents(r, mutbl),
+        };
+        let mt = match mutbl { ast::m_mutbl => TC_MUTABLE, _ => TC_NONE };
+        // We get additional "special type contents" for each bound that *isn't*
+        // on the trait. So iterate over the inverse of the bounds that are set.
+        // This is like with typarams below, but less "pessimistic" and also
+        // dependent on the trait store.
+        let mut bt = TC_NONE;
+        for (AllBuiltinBounds() - bounds).each |bound| {
+            bt = bt + match bound {
+                BoundCopy if store == UniqTraitStore
+                            => TC_NONCOPY_TRAIT,
+                BoundCopy   => TC_NONE, // @Trait/&Trait are copyable either way
+                BoundStatic if bounds.contains_elem(BoundOwned)
+                            => TC_NONE, // Owned bound implies static bound.
+                BoundStatic => TC_BORROWED_POINTER, // Useful for "@Trait:'static"
+                BoundOwned  => TC_NON_OWNED,
+                BoundConst  => TC_MUTABLE,
+                BoundSized  => TC_NONE, // don't care if interior is sized
+            };
+        }
+        st + mt + bt
+    }
+
     fn type_param_def_to_contents(cx: ctxt,
                                   type_param_def: &TypeParameterDef) -> TypeContents
     {
@@ -4497,7 +4521,9 @@ pub fn visitor_object_ty(tcx: ctxt) -> (@TraitRef, t) {
     };
     let trait_lang_item = tcx.lang_items.ty_visitor();
     let trait_ref = @TraitRef { def_id: trait_lang_item, substs: substs };
+    let mut static_trait_bound = EmptyBuiltinBounds();
+    static_trait_bound.add(BoundStatic);
     (trait_ref,
      mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs,
-              BoxTraitStore, ast::m_imm, EmptyBuiltinBounds()))
+              BoxTraitStore, ast::m_imm, static_trait_bound))
 }
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 5e6574850f1..997061a61ba 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -303,7 +303,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
                                 ty::BoxTraitStore
                             }
                         };
-                        let bounds = conv_builtin_bounds(this.tcx(), bounds);
+                        let bounds = conv_builtin_bounds(this.tcx(), bounds, trait_store);
                         return ty::mk_trait(tcx,
                                             result.def_id,
                                             copy result.substs,
@@ -386,7 +386,13 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
                                             bf.abis, &bf.lifetimes, &bf.decl))
       }
       ast::ty_closure(ref f) => {
-          let bounds = conv_builtin_bounds(this.tcx(), &f.bounds);
+          let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, match f.sigil {
+              // Use corresponding trait store to figure out default bounds
+              // if none were specified.
+              ast::BorrowedSigil => ty::RegionTraitStore(ty::re_empty), // dummy region
+              ast::OwnedSigil    => ty::UniqTraitStore,
+              ast::ManagedSigil  => ty::BoxTraitStore,
+          });
           let fn_decl = ty_of_closure(this,
                                       rscope,
                                       f.sigil,
@@ -411,7 +417,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
         match a_def {
             // But don't emit the error if the user meant to do a trait anyway.
             ast::def_trait(*) => { },
-            _ if !bounds.is_empty() =>
+            _ if bounds.is_some() =>
                 tcx.sess.span_err(ast_ty.span,
                     "kind bounds can only be used on trait types"),
             _ => { },
@@ -741,8 +747,8 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + 'static>(
     }
 }
 
-fn conv_builtin_bounds(tcx: ty::ctxt,
-                       ast_bounds: &OptVec<ast::TyParamBound>)
+fn conv_builtin_bounds(tcx: ty::ctxt, ast_bounds: &Option<OptVec<ast::TyParamBound>>,
+                       store: ty::TraitStore)
                        -> ty::BuiltinBounds {
     //! Converts a list of bounds from the AST into a `BuiltinBounds`
     //! struct. Reports an error if any of the bounds that appear
@@ -750,32 +756,51 @@ fn conv_builtin_bounds(tcx: ty::ctxt,
     //! like `Copy` or `Owned`. Used to translate the bounds that
     //! appear in closure and trait types, where only builtin bounds are
     //! legal.
-
-    let mut builtin_bounds = ty::EmptyBuiltinBounds();
-    for ast_bounds.iter().advance |ast_bound| {
-        match *ast_bound {
-            ast::TraitTyParamBound(b) => {
-                match lookup_def_tcx(tcx, b.path.span, b.ref_id) {
-                    ast::def_trait(trait_did) => {
-                        if try_add_builtin_trait(tcx,
-                                                 trait_did,
-                                                 &mut builtin_bounds) {
-                            loop; // success
+    //! If no bounds were specified, we choose a "default" bound based on
+    //! the allocation type of the fn/trait, as per issue #7264. The user can
+    //! override this with an empty bounds list, e.g. "~fn:()" or "~Trait:".
+
+    match (ast_bounds, store) {
+        (&Some(ref bound_vec), _) => {
+            let mut builtin_bounds = ty::EmptyBuiltinBounds();
+            for bound_vec.iter().advance |ast_bound| {
+                match *ast_bound {
+                    ast::TraitTyParamBound(b) => {
+                        match lookup_def_tcx(tcx, b.path.span, b.ref_id) {
+                            ast::def_trait(trait_did) => {
+                                if try_add_builtin_trait(tcx,
+                                                         trait_did,
+                                                         &mut builtin_bounds) {
+                                    loop; // success
+                                }
+                            }
+                            _ => { }
                         }
+                        tcx.sess.span_fatal(
+                            b.path.span,
+                            fmt!("only the builtin traits can be used \
+                                  as closure or object bounds"));
+                    }
+                    ast::RegionTyParamBound => {
+                        builtin_bounds.add(ty::BoundStatic);
                     }
-                    _ => { }
                 }
-                tcx.sess.span_fatal(
-                    b.path.span,
-                    fmt!("only the builtin traits can be used \
-                          as closure or object bounds"));
-            }
-            ast::RegionTyParamBound => {
-                builtin_bounds.add(ty::BoundStatic);
             }
+            builtin_bounds
+        },
+        // ~Trait is sugar for ~Trait:Owned.
+        (&None, ty::UniqTraitStore) => {
+            let mut set = ty::EmptyBuiltinBounds(); set.add(ty::BoundOwned); set
+        }
+        // @Trait is sugar for @Trait:'static.
+        // &'static Trait is sugar for &'static Trait:'static.
+        (&None, ty::BoxTraitStore) |
+        (&None, ty::RegionTraitStore(ty::re_static)) => {
+            let mut set = ty::EmptyBuiltinBounds(); set.add(ty::BoundStatic); set
         }
+        // &'r Trait is sugar for &'r Trait:<no-bounds>.
+        (&None, ty::RegionTraitStore(*)) => ty::EmptyBuiltinBounds(),
     }
-    builtin_bounds
 }
 
 pub fn try_add_builtin_trait(tcx: ty::ctxt,
diff --git a/src/libstd/io.rs b/src/libstd/io.rs
index 71a0dd6b9b2..a78be9c8b2b 100644
--- a/src/libstd/io.rs
+++ b/src/libstd/io.rs
@@ -1042,12 +1042,14 @@ pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
 
 
 // Byte readers
-pub struct BytesReader<'self> {
-    bytes: &'self [u8],
+pub struct BytesReader {
+    // FIXME(#5723) see other FIXME below
+    // FIXME(#7268) this should also be parameterized over <'self>
+    bytes: &'static [u8],
     pos: @mut uint
 }
 
-impl<'self> Reader for BytesReader<'self> {
+impl Reader for BytesReader {
     fn read(&self, bytes: &mut [u8], len: uint) -> uint {
         let count = uint::min(len, self.bytes.len() - *self.pos);
 
@@ -1084,6 +1086,10 @@ impl<'self> Reader for BytesReader<'self> {
 }
 
 pub fn with_bytes_reader<T>(bytes: &[u8], f: &fn(@Reader) -> T) -> T {
+    // XXX XXX XXX this is glaringly unsound
+    // FIXME(#5723) Use a &Reader for the callback's argument. Should be:
+    // fn with_bytes_reader<'r, T>(bytes: &'r [u8], f: &fn(&'r Reader) -> T) -> T
+    let bytes: &'static [u8] = unsafe { cast::transmute(bytes) };
     f(@BytesReader {
         bytes: bytes,
         pos: @mut 0
@@ -1091,6 +1097,7 @@ pub fn with_bytes_reader<T>(bytes: &[u8], f: &fn(@Reader) -> T) -> T {
 }
 
 pub fn with_str_reader<T>(s: &str, f: &fn(@Reader) -> T) -> T {
+    // FIXME(#5723): As above.
     with_bytes_reader(s.as_bytes(), f)
 }
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 90b2f131b00..1a7094acf7e 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -771,7 +771,11 @@ pub struct TyClosure {
     purity: purity,
     onceness: Onceness,
     decl: fn_decl,
-    bounds: OptVec<TyParamBound>
+    // Optional optvec distinguishes between "fn()" and "fn:()" so we can
+    // implement issue #7264. None means "fn()", which means infer a default
+    // bound based on pointer sigil during typeck. Some(Empty) means "fn:()",
+    // which means use no bounds (e.g., not even Owned on a ~fn()).
+    bounds: Option<OptVec<TyParamBound>>,
 }
 
 #[deriving(Eq, Encodable, Decodable)]
@@ -795,7 +799,7 @@ pub enum ty_ {
     ty_closure(@TyClosure),
     ty_bare_fn(@TyBareFn),
     ty_tup(~[@Ty]),
-    ty_path(@Path, @OptVec<TyParamBound>, node_id),
+    ty_path(@Path, @Option<OptVec<TyParamBound>>, node_id), // for #7264; see above
     ty_mac(mac),
     // ty_infer means the type should be inferred instead of it having been
     // specified. This should only appear at the "top level" of a type and not
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 02d5991e1a7..2c1b4cfc591 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -46,7 +46,7 @@ pub trait AstBuilder {
     fn ty_mt(&self, ty: @ast::Ty, mutbl: ast::mutability) -> ast::mt;
 
     fn ty(&self, span: span, ty: ast::ty_) -> @ast::Ty;
-    fn ty_path(&self, @ast::Path, @OptVec<ast::TyParamBound>) -> @ast::Ty;
+    fn ty_path(&self, @ast::Path, @Option<OptVec<ast::TyParamBound>>) -> @ast::Ty;
     fn ty_ident(&self, span: span, idents: ast::ident) -> @ast::Ty;
 
     fn ty_rptr(&self, span: span,
@@ -265,7 +265,7 @@ impl AstBuilder for @ExtCtxt {
         }
     }
 
-    fn ty_path(&self, path: @ast::Path, bounds: @OptVec<ast::TyParamBound>)
+    fn ty_path(&self, path: @ast::Path, bounds: @Option<OptVec<ast::TyParamBound>>)
               -> @ast::Ty {
         self.ty(path.span,
                 ast::ty_path(path, bounds, self.next_id()))
@@ -275,7 +275,7 @@ impl AstBuilder for @ExtCtxt {
     // to generate a bounded existential trait type.
     fn ty_ident(&self, span: span, ident: ast::ident)
         -> @ast::Ty {
-        self.ty_path(self.path_ident(span, ident), @opt_vec::Empty)
+        self.ty_path(self.path_ident(span, ident), @None)
     }
 
     fn ty_rptr(&self,
@@ -306,7 +306,7 @@ impl AstBuilder for @ExtCtxt {
                           ],
                           None,
                           ~[ ty ]),
-            @opt_vec::Empty)
+            @None)
     }
 
     fn ty_field_imm(&self, span: span, name: ident, ty: @ast::Ty) -> ast::ty_field {
@@ -344,7 +344,7 @@ impl AstBuilder for @ExtCtxt {
     fn ty_vars_global(&self, ty_params: &OptVec<ast::TyParam>) -> ~[@ast::Ty] {
         opt_vec::take_vec(
             ty_params.map(|p| self.ty_path(
-                self.path_global(dummy_sp(), ~[p.ident]), @opt_vec::Empty)))
+                self.path_global(dummy_sp(), ~[p.ident]), @None)))
     }
 
     fn strip_bounds(&self, generics: &Generics) -> Generics {
diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs
index 17bbe7a333e..10d9f878bc4 100644
--- a/src/libsyntax/ext/deriving/generic.rs
+++ b/src/libsyntax/ext/deriving/generic.rs
@@ -357,7 +357,7 @@ impl<'self> TraitDef<'self> {
         // Create the type of `self`.
         let self_type = cx.ty_path(cx.path_all(span, false, ~[ type_ident ], self_lifetime,
                                                opt_vec::take_vec(self_ty_params)),
-                                   @opt_vec::Empty);
+                                   @None);
 
         let doc_attr = cx.attribute(
             span,
diff --git a/src/libsyntax/ext/deriving/ty.rs b/src/libsyntax/ext/deriving/ty.rs
index 9da6bf27ead..2f21eba11d7 100644
--- a/src/libsyntax/ext/deriving/ty.rs
+++ b/src/libsyntax/ext/deriving/ty.rs
@@ -63,7 +63,7 @@ impl<'self> Path<'self> {
                  self_generics: &Generics)
                  -> @ast::Ty {
         cx.ty_path(self.to_path(cx, span,
-                                self_ty, self_generics), @opt_vec::Empty)
+                                self_ty, self_generics), @None)
     }
     pub fn to_path(&self,
                    cx: @ExtCtxt,
@@ -143,7 +143,7 @@ impl<'self> Ty<'self> {
             Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) }
             Self  => {
                 cx.ty_path(self.to_path(cx, span, self_ty, self_generics),
-                           @opt_vec::Empty)
+                           @None)
             }
             Tuple(ref fields) => {
                 let ty = if fields.is_empty() {
diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs
index a75a20a0fa9..2c5ec0909d9 100644
--- a/src/libsyntax/ext/pipes/pipec.rs
+++ b/src/libsyntax/ext/pipes/pipec.rs
@@ -59,7 +59,7 @@ impl gen_send for message {
 
             let pipe_ty = cx.ty_path(
                 path(~[this.data_name()], span)
-                .add_tys(cx.ty_vars(&this.generics.ty_params)), @opt_vec::Empty);
+                .add_tys(cx.ty_vars(&this.generics.ty_params)), @None);
             let args_ast = vec::append(
                 ~[cx.arg(span, cx.ident_of("pipe"), pipe_ty)],
                 args_ast);
@@ -115,7 +115,7 @@ impl gen_send for message {
 
             let mut rty = cx.ty_path(path(~[next.data_name()],
                                           span)
-                                     .add_tys(copy next_state.tys), @opt_vec::Empty);
+                                     .add_tys(copy next_state.tys), @None);
             if try {
                 rty = cx.ty_option(rty);
             }
@@ -144,7 +144,7 @@ impl gen_send for message {
                              cx.ty_path(
                                  path(~[this.data_name()], span)
                                  .add_tys(cx.ty_vars(
-                                     &this.generics.ty_params)), @opt_vec::Empty))],
+                                     &this.generics.ty_params)), @None))],
                     args_ast);
 
                 let message_args = if arg_names.len() == 0 {
@@ -190,7 +190,7 @@ impl gen_send for message {
 
     fn to_ty(&mut self, cx: @ExtCtxt) -> @ast::Ty {
         cx.ty_path(path(~[cx.ident_of(self.name())], self.span())
-          .add_tys(cx.ty_vars(&self.get_generics().ty_params)), @opt_vec::Empty)
+          .add_tys(cx.ty_vars(&self.get_generics().ty_params)), @None)
     }
 }
 
@@ -224,7 +224,7 @@ impl to_type_decls for state {
                                 cx.ty_path(
                                     path(~[cx.ident_of(dir),
                                            cx.ident_of(next_name)], span)
-                                    .add_tys(copy next_state.tys), @opt_vec::Empty))
+                                    .add_tys(copy next_state.tys), @None))
               }
               None => tys
             };
@@ -277,8 +277,8 @@ impl to_type_decls for state {
                                    self.data_name()],
                                  dummy_sp())
                             .add_tys(cx.ty_vars(
-                                &self.generics.ty_params)), @opt_vec::Empty)),
-                        @opt_vec::Empty),
+                                &self.generics.ty_params)), @None)),
+                        @None),
                     cx.strip_bounds(&self.generics)));
         }
         else {
@@ -297,8 +297,8 @@ impl to_type_decls for state {
                                    self.data_name()],
                                         dummy_sp())
                             .add_tys(cx.ty_vars_global(
-                                &self.generics.ty_params)), @opt_vec::Empty),
-                                   self.proto.buffer_ty_path(cx)]), @opt_vec::Empty),
+                                &self.generics.ty_params)), @None),
+                                   self.proto.buffer_ty_path(cx)]), @None),
                     cx.strip_bounds(&self.generics)));
         };
         items
@@ -383,7 +383,7 @@ impl gen_init for protocol {
         cx.ty_path(path(~[cx.ident_of("super"),
                           cx.ident_of("__Buffer")],
                         copy self.span)
-                   .add_tys(cx.ty_vars_global(&params)), @opt_vec::Empty)
+                   .add_tys(cx.ty_vars_global(&params)), @None)
     }
 
     fn gen_buffer_type(&self, cx: @ExtCtxt) -> @ast::item {
diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs
index e86ced847d7..0525c666478 100644
--- a/src/libsyntax/ext/pipes/proto.rs
+++ b/src/libsyntax/ext/pipes/proto.rs
@@ -13,7 +13,6 @@ use codemap::span;
 use ext::base::ExtCtxt;
 use ext::build::AstBuilder;
 use ext::pipes::ast_builder::{append_types, path};
-use opt_vec;
 
 #[deriving(Eq)]
 pub enum direction { send, recv }
@@ -100,7 +99,7 @@ impl state_ {
     pub fn to_ty(&self, cx: @ExtCtxt) -> @ast::Ty {
         cx.ty_path
             (path(~[cx.ident_of(self.name)],self.span).add_tys(
-                cx.ty_vars(&self.generics.ty_params)), @opt_vec::Empty)
+                cx.ty_vars(&self.generics.ty_params)), @None)
     }
 
     /// Iterate over the states that can be reached in one message
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 2c7c335a841..2fc111da453 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -651,6 +651,12 @@ pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ {
             span: fld.new_span(f.span),
         }
     }
+    fn fold_opt_bounds(b: &Option<OptVec<TyParamBound>>, fld: @ast_fold)
+                        -> Option<OptVec<TyParamBound>> {
+        do b.map |bounds| {
+            do bounds.map |bound| { fold_ty_param_bound(bound, fld) }
+        }
+    }
     match *t {
         ty_nil | ty_bot | ty_infer => copy *t,
         ty_box(ref mt) => ty_box(fold_mt(mt, fld)),
@@ -664,7 +670,7 @@ pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ {
                 purity: f.purity,
                 region: f.region,
                 onceness: f.onceness,
-                bounds: f.bounds.map(|x| fold_ty_param_bound(x, fld)),
+                bounds: fold_opt_bounds(&f.bounds, fld),
                 decl: fold_fn_decl(&f.decl, fld),
                 lifetimes: copy f.lifetimes,
             })
@@ -679,8 +685,7 @@ pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ {
         }
         ty_tup(ref tys) => ty_tup(tys.map(|ty| fld.fold_ty(*ty))),
         ty_path(path, bounds, id) =>
-            ty_path(fld.fold_path(path),
-                    @bounds.map(|x| fold_ty_param_bound(x, fld)), fld.new_id(id)),
+            ty_path(fld.fold_path(path), @fold_opt_bounds(bounds, fld), fld.new_id(id)),
         ty_fixed_length_vec(ref mt, e) => {
             ty_fixed_length_vec(
                 fold_mt(mt, fld),
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index d54c64e7ee6..6dd8d4880e3 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -490,7 +490,7 @@ mod test {
                                         idents:~[str_to_ident("int")],
                                         rp: None,
                                         types: ~[]},
-                                                       @opt_vec::Empty, 2),
+                                                       @None, 2),
                                     span:sp(4,7)},
                        pat: @ast::pat{id:1,
                                       node: ast::pat_ident(ast::bind_infer,
@@ -526,7 +526,7 @@ mod test {
                                         idents:~[str_to_ident("int")],
                                         rp: None,
                                         types: ~[]},
-                                                       @opt_vec::Empty, 2),
+                                                       @None, 2),
                                                 span:sp(10,13)},
                                     pat: @ast::pat{id:1, // fixme
                                                    node: ast::pat_ident(
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index b10005aeaf1..d67771fc435 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1047,8 +1047,8 @@ impl Parser {
 
     // Like the above, but can also parse kind bounds in the case of a
     // path to be used as a type that might be a trait.
-    pub fn parse_type_path(&self) -> (@ast::Path, OptVec<TyParamBound>) {
-        let mut bounds = opt_vec::Empty;
+    pub fn parse_type_path(&self) -> (@ast::Path, Option<OptVec<TyParamBound>>) {
+        let mut bounds = None;
         let path = self.parse_bounded_path_with_tps(false, Some(|| {
             // Note: this closure might not even get called in the case of a
             // macro-generated path. But that's the macro parser's job.
@@ -2884,9 +2884,13 @@ impl Parser {
     // matches optbounds = ( ( : ( boundseq )? )? )
     // where   boundseq  = ( bound + boundseq ) | bound
     // and     bound     = 'static | ty
-    fn parse_optional_ty_param_bounds(&self) -> OptVec<TyParamBound> {
+    // Returns "None" if there's no colon (e.g. "T");
+    // Returns "Some(Empty)" if there's a colon but nothing after (e.g. "T:")
+    // Returns "Some(stuff)" otherwise (e.g. "T:stuff").
+    // NB: The None/Some distinction is important for issue #7264.
+    fn parse_optional_ty_param_bounds(&self) -> Option<OptVec<TyParamBound>> {
         if !self.eat(&token::COLON) {
-            return opt_vec::Empty;
+            return None;
         }
 
         let mut result = opt_vec::Empty;
@@ -2935,13 +2939,15 @@ impl Parser {
             }
         }
 
-        return result;
+        return Some(result);
     }
 
     // matches typaram = IDENT optbounds
     fn parse_ty_param(&self) -> TyParam {
         let ident = self.parse_ident();
-        let bounds = @self.parse_optional_ty_param_bounds();
+        let opt_bounds = self.parse_optional_ty_param_bounds();
+        // For typarams we don't care about the difference b/w "<T>" and "<T:>".
+        let bounds = @opt_bounds.get_or_default(opt_vec::Empty);
         ast::TyParam { ident: ident, id: self.get_id(), bounds: bounds }
     }
 
@@ -3288,7 +3294,7 @@ impl Parser {
         let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
             // New-style trait. Reinterpret the type as a trait.
             let opt_trait_ref = match ty.node {
-                ty_path(path, @opt_vec::Empty, node_id) => {
+                ty_path(path, @None, node_id) => {
                     Some(@trait_ref {
                         path: path,
                         ref_id: node_id
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 277cc6208fb..728a5a3d32a 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -410,14 +410,14 @@ pub fn print_type(s: @ps, ty: @ast::Ty) {
           let generics = ast::Generics {lifetimes: copy f.lifetimes,
                                         ty_params: opt_vec::Empty};
           print_ty_fn(s, Some(f.abis), None, None,
-                      f.purity, ast::Many, &f.decl, None,
+                      f.purity, ast::Many, &f.decl, None, &None,
                       Some(&generics), None);
       }
       ast::ty_closure(f) => {
           let generics = ast::Generics {lifetimes: copy f.lifetimes,
                                         ty_params: opt_vec::Empty};
           print_ty_fn(s, None, Some(f.sigil), f.region,
-                      f.purity, f.onceness, &f.decl, None,
+                      f.purity, f.onceness, &f.decl, None, &f.bounds,
                       Some(&generics), None);
       }
       ast::ty_path(path, bounds, _) => print_bounded_path(s, path, bounds),
@@ -806,7 +806,7 @@ pub fn print_ty_method(s: @ps, m: &ast::ty_method) {
     maybe_print_comment(s, m.span.lo);
     print_outer_attributes(s, m.attrs);
     print_ty_fn(s, None, None, None, m.purity, ast::Many,
-                &m.decl, Some(m.ident), Some(&m.generics),
+                &m.decl, Some(m.ident), &None, Some(&m.generics),
                 Some(/*bad*/ copy m.explicit_self.node));
     word(s.s, ";");
 }
@@ -1488,7 +1488,7 @@ pub fn print_for_decl(s: @ps, loc: @ast::local, coll: @ast::expr) {
 }
 
 fn print_path_(s: @ps, path: @ast::Path, colons_before_params: bool,
-               opt_bounds: Option<@OptVec<ast::TyParamBound>>) {
+               opt_bounds: &Option<OptVec<ast::TyParamBound>>) {
     maybe_print_comment(s, path.span.lo);
     if path.global { word(s.s, "::"); }
     let mut first = true;
@@ -1496,8 +1496,8 @@ fn print_path_(s: @ps, path: @ast::Path, colons_before_params: bool,
         if first { first = false; } else { word(s.s, "::"); }
         print_ident(s, *id);
     }
-    do opt_bounds.map_consume |bounds| {
-        print_bounds(s, bounds);
+    do opt_bounds.map |bounds| {
+        print_bounds(s, bounds, true);
     };
     if path.rp.is_some() || !path.types.is_empty() {
         if colons_before_params { word(s.s, "::"); }
@@ -1520,12 +1520,12 @@ fn print_path_(s: @ps, path: @ast::Path, colons_before_params: bool,
 }
 
 pub fn print_path(s: @ps, path: @ast::Path, colons_before_params: bool) {
-    print_path_(s, path, colons_before_params, None)
+    print_path_(s, path, colons_before_params, &None)
 }
 
 pub fn print_bounded_path(s: @ps, path: @ast::Path,
-                          bounds: @OptVec<ast::TyParamBound>) {
-    print_path_(s, path, false, Some(bounds))
+                          bounds: &Option<OptVec<ast::TyParamBound>>) {
+    print_path_(s, path, false, bounds)
 }
 
 pub fn print_irrefutable_pat(s: @ps, pat: @ast::pat) {
@@ -1737,7 +1737,8 @@ pub fn print_fn_block_args(s: @ps, decl: &ast::fn_decl) {
     maybe_print_comment(s, decl.output.span.lo);
 }
 
-pub fn print_bounds(s: @ps, bounds: @OptVec<ast::TyParamBound>) {
+pub fn print_bounds(s: @ps, bounds: &OptVec<ast::TyParamBound>,
+                    print_colon_anyway: bool) {
     if !bounds.is_empty() {
         word(s.s, ":");
         let mut first = true;
@@ -1754,6 +1755,8 @@ pub fn print_bounds(s: @ps, bounds: @OptVec<ast::TyParamBound>) {
                 RegionTyParamBound => word(s.s, "'static"),
             }
         }
+    } else if print_colon_anyway {
+        word(s.s, ":");
     }
 }
 
@@ -1774,7 +1777,7 @@ pub fn print_generics(s: @ps, generics: &ast::Generics) {
                 let idx = idx - generics.lifetimes.len();
                 let param = generics.ty_params.get(idx);
                 print_ident(s, param.ident);
-                print_bounds(s, param.bounds);
+                print_bounds(s, param.bounds, false);
             }
         }
 
@@ -1917,6 +1920,7 @@ pub fn print_ty_fn(s: @ps,
                    onceness: ast::Onceness,
                    decl: &ast::fn_decl,
                    id: Option<ast::ident>,
+                   opt_bounds: &Option<OptVec<ast::TyParamBound>>,
                    generics: Option<&ast::Generics>,
                    opt_explicit_self: Option<ast::explicit_self_>) {
     ibox(s, indent_unit);
@@ -1930,6 +1934,7 @@ pub fn print_ty_fn(s: @ps,
     print_onceness(s, onceness);
     word(s.s, "fn");
     match id { Some(id) => { word(s.s, " "); print_ident(s, id); } _ => () }
+    do opt_bounds.map |bounds| { print_bounds(s, bounds, true); };
     match generics { Some(g) => print_generics(s, g), _ => () }
     zerobreak(s.s);
 
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 9b816ce5e5b..f0a993dbb94 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -246,7 +246,9 @@ pub fn visit_ty<E: Copy>(t: @Ty, (e, v): (E, vt<E>)) {
         ty_closure(ref f) => {
             for f.decl.inputs.iter().advance |a| { (v.visit_ty)(a.ty, (copy e, v)); }
             (v.visit_ty)(f.decl.output, (copy e, v));
-            visit_ty_param_bounds(&f.bounds, (e, v));
+            do f.bounds.map |bounds| {
+                visit_ty_param_bounds(bounds, (copy e, v));
+            };
         },
         ty_bare_fn(ref f) => {
             for f.decl.inputs.iter().advance |a| { (v.visit_ty)(a.ty, (copy e, v)); }
@@ -254,7 +256,9 @@ pub fn visit_ty<E: Copy>(t: @Ty, (e, v): (E, vt<E>)) {
         },
         ty_path(p, bounds, _) => {
             visit_path(p, (copy e, v));
-            visit_ty_param_bounds(bounds, (e, v));
+            do bounds.map |bounds| {
+                visit_ty_param_bounds(bounds, (copy e, v));
+            };
         },
         ty_fixed_length_vec(ref mt, ex) => {
             (v.visit_ty)(mt.ty, (copy e, v));
diff --git a/src/test/compile-fail/closure-bounds-cant-promote-superkind-in-struct.rs b/src/test/compile-fail/closure-bounds-cant-promote-superkind-in-struct.rs
index c3c8467233c..098a395f017 100644
--- a/src/test/compile-fail/closure-bounds-cant-promote-superkind-in-struct.rs
+++ b/src/test/compile-fail/closure-bounds-cant-promote-superkind-in-struct.rs
@@ -12,7 +12,7 @@ struct X {
     field: @fn:Copy(),
 }
 
-fn foo(blk: @fn()) -> X {
+fn foo(blk: @fn:()) -> X {
     return X { field: blk }; //~ ERROR expected bounds `Copy` but found no bounds
 }
 
diff --git a/src/test/compile-fail/closure-bounds-subtype.rs b/src/test/compile-fail/closure-bounds-subtype.rs
index a975349e730..887346e35e5 100644
--- a/src/test/compile-fail/closure-bounds-subtype.rs
+++ b/src/test/compile-fail/closure-bounds-subtype.rs
@@ -1,5 +1,5 @@
 
-fn take_any(_: &fn()) {
+fn take_any(_: &fn:()) {
 }
 
 fn take_copyable(_: &fn:Copy()) {
@@ -11,7 +11,7 @@ fn take_copyable_owned(_: &fn:Copy+Owned()) {
 fn take_const_owned(_: &fn:Const+Owned()) {
 }
 
-fn give_any(f: &fn()) {
+fn give_any(f: &fn:()) {
     take_any(f);
     take_copyable(f); //~ ERROR expected bounds `Copy` but found no bounds
     take_copyable_owned(f); //~ ERROR expected bounds `Copy+Owned` but found no bounds
diff --git a/src/test/compile-fail/kindck-nonsendable-1.rs b/src/test/compile-fail/kindck-nonsendable-1.rs
index 928abae2423..38983a9aca6 100644
--- a/src/test/compile-fail/kindck-nonsendable-1.rs
+++ b/src/test/compile-fail/kindck-nonsendable-1.rs
@@ -12,7 +12,7 @@ fn foo(_x: @uint) {}
 
 fn main() {
     let x = @3u;
-    let _: ~fn() = || foo(x); //~ ERROR value has non-owned type `@uint`
-    let _: ~fn() = || foo(x); //~ ERROR value has non-owned type `@uint`
-    let _: ~fn() = || foo(x); //~ ERROR value has non-owned type `@uint`
+    let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Owned`
+    let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Owned`
+    let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Owned`
 }
diff --git a/src/test/compile-fail/kindck-owned-trait.rs b/src/test/compile-fail/kindck-owned-trait.rs
index 857c71db72c..c2352e35a46 100644
--- a/src/test/compile-fail/kindck-owned-trait.rs
+++ b/src/test/compile-fail/kindck-owned-trait.rs
@@ -11,7 +11,9 @@
 trait foo { fn foo(&self); }
 
 fn to_foo<T:Copy + foo>(t: T) -> @foo {
-    @t as @foo //~ ERROR value may contain borrowed pointers; add `'static` bound
+    @t as @foo
+    //~^ ERROR value may contain borrowed pointers; add `'static` bound
+    //~^^ ERROR cannot pack type
 }
 
 fn to_foo2<T:Copy + foo + 'static>(t: T) -> @foo {
diff --git a/src/test/compile-fail/kindck-owned.rs b/src/test/compile-fail/kindck-owned.rs
index ec84551f7b0..3f859b7dc84 100644
--- a/src/test/compile-fail/kindck-owned.rs
+++ b/src/test/compile-fail/kindck-owned.rs
@@ -9,8 +9,7 @@
 // except according to those terms.
 
 fn copy1<T:Copy>(t: T) -> @fn() -> T {
-    let result: @fn() -> T = || copy t;
-    //~^ ERROR value may contain borrowed pointers
+    let result: @fn() -> T = || copy t; //~ ERROR does not fulfill `'static`
     result
 }
 
diff --git a/src/test/compile-fail/no-send-res-ports.rs b/src/test/compile-fail/no-send-res-ports.rs
index 1f5b600157f..605e59d56c8 100644
--- a/src/test/compile-fail/no-send-res-ports.rs
+++ b/src/test/compile-fail/no-send-res-ports.rs
@@ -32,7 +32,7 @@ fn main() {
     let x = Cell::new(foo(Port(@())));
 
     do task::spawn {
-        let y = x.take();   //~ ERROR value has non-owned type
+        let y = x.take();   //~ ERROR does not fulfill `Owned`
         error!(y);
     }
 }
diff --git a/src/test/compile-fail/trait-bounds-cant-coerce.rs b/src/test/compile-fail/trait-bounds-cant-coerce.rs
index 88c2d491747..adaea1de9bd 100644
--- a/src/test/compile-fail/trait-bounds-cant-coerce.rs
+++ b/src/test/compile-fail/trait-bounds-cant-coerce.rs
@@ -21,7 +21,7 @@ fn c(x: ~Foo:Const+Owned) {
     b(x); //~ ERROR expected bounds `Copy+Owned`
 }
 
-fn d(x: ~Foo) {
+fn d(x: ~Foo:) {
     a(x); //~ ERROR found no bounds
 }
 
diff --git a/src/test/compile-fail/trait-bounds-sugar.rs b/src/test/compile-fail/trait-bounds-sugar.rs
new file mode 100644
index 00000000000..8c641f4c850
--- /dev/null
+++ b/src/test/compile-fail/trait-bounds-sugar.rs
@@ -0,0 +1,37 @@
+// Copyright 2013 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.
+
+// Tests for "default" bounds inferred for traits with no bounds list.
+
+trait Foo {
+}
+
+fn a(_x: ~Foo) { // should be same as ~Foo:Owned
+}
+
+fn b(_x: @Foo) { // should be same as ~Foo:'static
+}
+
+fn c(_x: &'static Foo) { // should be same as &'static Foo:'static
+}
+
+fn d(x: ~Foo:Const) {
+    a(x); //~ ERROR expected bounds `Owned`
+}
+
+fn e(x: @Foo:Const) {
+    b(x); //~ ERROR expected bounds `'static`
+}
+
+fn f(x: &'static Foo:Const) {
+    c(x); //~ ERROR expected bounds `'static`
+}
+
+fn main() { }
diff --git a/src/test/run-pass/closure-bounds-copyable-squiggle-closure.rs b/src/test/run-pass/closure-bounds-copyable-squiggle-closure.rs
index f39c914916f..8c2ae22e8ed 100644
--- a/src/test/run-pass/closure-bounds-copyable-squiggle-closure.rs
+++ b/src/test/run-pass/closure-bounds-copyable-squiggle-closure.rs
@@ -8,11 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// xfail-pretty
-
 // Tests correct copying of heap closures' environments.
 
-fn foo(x: ~fn:Copy()) -> (~fn(), ~fn()) {
+fn foo(x: ~fn:Copy()) -> (~fn:(), ~fn:()) {
     (copy x, x)
 }
 fn main() {
diff --git a/src/test/run-pass/closure-bounds-squiggle-closure-as-copyable-typaram.rs b/src/test/run-pass/closure-bounds-squiggle-closure-as-copyable-typaram.rs
index 2fdce4e5c7c..88d474a51e1 100644
--- a/src/test/run-pass/closure-bounds-squiggle-closure-as-copyable-typaram.rs
+++ b/src/test/run-pass/closure-bounds-squiggle-closure-as-copyable-typaram.rs
@@ -8,14 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// xfail-pretty
-
 // Tests correct copying of heap closures' environments.
 
 fn bar<T: Copy>(x: T) -> (T, T) {
     (copy x, x)
 }
-fn foo(x: ~fn:Copy()) -> (~fn(), ~fn()) {
+fn foo(x: ~fn:Copy()) -> (~fn:(), ~fn:()) {
     bar(x)
 }
 fn main() {
diff --git a/src/test/run-pass/kindck-owned-trait-contains-1.rs b/src/test/run-pass/kindck-owned-trait-contains-1.rs
index c51094d26c8..e733400527b 100644
--- a/src/test/run-pass/kindck-owned-trait-contains-1.rs
+++ b/src/test/run-pass/kindck-owned-trait-contains-1.rs
@@ -14,9 +14,9 @@ impl<A:Copy> repeat<A> for @A {
     fn get(&self) -> A { copy **self }
 }
 
-fn repeater<A:Copy>(v: @A) -> @repeat<A> {
+fn repeater<A:Copy>(v: @A) -> @repeat:<A> {
     // Note: owned kind is not necessary as A appears in the trait type
-    @v as @repeat<A> // No
+    @v as @repeat:<A> // No
 }
 
 pub fn main() {
diff --git a/src/test/run-pass/regions-trait.rs b/src/test/run-pass/regions-trait.rs
index b5b13efa634..049d5305ca4 100644
--- a/src/test/run-pass/regions-trait.rs
+++ b/src/test/run-pass/regions-trait.rs
@@ -22,7 +22,7 @@ impl<'self> get_ctxt<'self> for HasCtxt<'self> {
     }
 }
 
-fn get_v(gc: @get_ctxt) -> uint {
+fn get_v(gc: @get_ctxt:) -> uint {
     gc.get_ctxt().v
 }
 
@@ -30,5 +30,5 @@ pub fn main() {
     let ctxt = Ctxt { v: 22 };
     let hc = HasCtxt { c: &ctxt };
 
-    assert_eq!(get_v(@hc as @get_ctxt), 22);
+    assert_eq!(get_v(@hc as @get_ctxt:), 22);
 }
diff --git a/src/test/run-pass/trait-bounds-basic.rs b/src/test/run-pass/trait-bounds-basic.rs
index b9251c038af..5bfbf84d8ac 100644
--- a/src/test/run-pass/trait-bounds-basic.rs
+++ b/src/test/run-pass/trait-bounds-basic.rs
@@ -11,7 +11,7 @@
 trait Foo {
 }
 
-fn a(_x: ~Foo) {
+fn a(_x: ~Foo:) {
 }
 
 fn b(_x: ~Foo:Owned) {
@@ -25,4 +25,8 @@ fn d(x: ~Foo:Owned+Copy) {
     b(x);
 }
 
+fn e(x: ~Foo) { // sugar for ~Foo:Owned
+    b(x);
+}
+
 fn main() { }
diff --git a/src/test/run-pass/trait-bounds-in-arc.rs b/src/test/run-pass/trait-bounds-in-arc.rs
new file mode 100644
index 00000000000..585c2185a7e
--- /dev/null
+++ b/src/test/run-pass/trait-bounds-in-arc.rs
@@ -0,0 +1,103 @@
+// Copyright 2013 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.
+
+// Tests that a heterogeneous list of existential types can be put inside an ARC
+// and shared between tasks as long as all types fulfill Const+Owned.
+
+// xfail-fast
+
+extern mod extra;
+use extra::arc;
+use std::comm;
+use std::task;
+use std::cell;
+
+trait Pet {
+    fn name(&self, blk: &fn(&str));
+    fn num_legs(&self) -> uint;
+    fn of_good_pedigree(&self) -> bool;
+}
+
+struct Catte {
+    num_whiskers: uint,
+    name: ~str,
+}
+
+struct Dogge {
+    bark_decibels: uint,
+    tricks_known: uint,
+    name: ~str,
+}
+
+struct Goldfyshe {
+    swim_speed: uint,
+    name: ~str,
+}
+
+impl Pet for Catte {
+    fn name(&self, blk: &fn(&str)) { blk(self.name) }
+    fn num_legs(&self) -> uint { 4 }
+    fn of_good_pedigree(&self) -> bool { self.num_whiskers >= 4 }
+}
+impl Pet for Dogge {
+    fn name(&self, blk: &fn(&str)) { blk(self.name) }
+    fn num_legs(&self) -> uint { 4 }
+    fn of_good_pedigree(&self) -> bool {
+        self.bark_decibels < 70 || self.tricks_known > 20
+    }
+}
+impl Pet for Goldfyshe {
+    fn name(&self, blk: &fn(&str)) { blk(self.name) }
+    fn num_legs(&self) -> uint { 0 }
+    fn of_good_pedigree(&self) -> bool { self.swim_speed >= 500 }
+}
+
+fn main() {
+    let catte = Catte { num_whiskers: 7, name: ~"alonzo_church" };
+    let dogge1 = Dogge { bark_decibels: 100, tricks_known: 42, name: ~"alan_turing" };
+    let dogge2 = Dogge { bark_decibels: 55,  tricks_known: 11, name: ~"albert_einstein" };
+    let fishe = Goldfyshe { swim_speed: 998, name: ~"alec_guinness" };
+    let arc = arc::ARC(~[~catte  as ~Pet:Const+Owned,
+                         ~dogge1 as ~Pet:Const+Owned,
+                         ~fishe  as ~Pet:Const+Owned,
+                         ~dogge2 as ~Pet:Const+Owned]);
+    let (p1,c1) = comm::stream();
+    let arc1 = cell::Cell::new(arc.clone());
+    do task::spawn { check_legs(arc1.take()); c1.send(()); }
+    let (p2,c2) = comm::stream();
+    let arc2 = cell::Cell::new(arc.clone());
+    do task::spawn { check_names(arc2.take()); c2.send(()); }
+    let (p3,c3) = comm::stream();
+    let arc3 = cell::Cell::new(arc.clone());
+    do task::spawn { check_pedigree(arc3.take()); c3.send(()); }
+    p1.recv();
+    p2.recv();
+    p3.recv();
+}
+
+fn check_legs(arc: arc::ARC<~[~Pet:Const+Owned]>) {
+    let mut legs = 0;
+    for arc.get().iter().advance |pet| {
+        legs += pet.num_legs();
+    }
+    assert!(legs == 12);
+}
+fn check_names(arc: arc::ARC<~[~Pet:Const+Owned]>) {
+    for arc.get().iter().advance |pet| {
+        do pet.name |name| {
+            assert!(name[0] == 'a' as u8 && name[1] == 'l' as u8);
+        }
+    }
+}
+fn check_pedigree(arc: arc::ARC<~[~Pet:Const+Owned]>) {
+    for arc.get().iter().advance |pet| {
+        assert!(pet.of_good_pedigree());
+    }
+}