about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-11-26 09:44:43 -0800
committerAlex Crichton <alex@alexcrichton.com>2014-11-26 16:49:46 -0800
commitf4a775639ca846f29abeed16a7b4e8e1c8819626 (patch)
treead6c9a0c61140ae68169fca89e8641af83c92e33
parent702127f6f1b099f8a34804ddb71f821444b7b64e (diff)
parent21d5d139fc6e04781b7f9d9eeab0f8f0255ac06b (diff)
rollup merge of #19298: nikomatsakis/unboxed-closure-parse-the-plus
Implements RFC 438.

Fixes #19092.

This is a [breaking-change]: change types like `&Foo+Send` or `&'a mut Foo+'a` to `&(Foo+Send)` and `&'a mut (Foo+'a)`, respectively.

r? @brson
-rw-r--r--src/libcore/fmt/mod.rs6
-rw-r--r--src/librustc/diagnostics.rs3
-rw-r--r--src/librustc/lint/builtin.rs2
-rw-r--r--src/librustc/metadata/encoder.rs3
-rw-r--r--src/librustc/middle/expr_use_visitor.rs2
-rw-r--r--src/librustc/middle/privacy.rs10
-rw-r--r--src/librustc/middle/resolve.rs110
-rw-r--r--src/librustc/middle/resolve_lifetime.rs9
-rw-r--r--src/librustc/middle/traits/select.rs2
-rw-r--r--src/librustc/middle/typeck/astconv.rs175
-rw-r--r--src/librustc/middle/typeck/infer/error_reporting.rs4
-rw-r--r--src/librustc/middle/typeck/rscope.rs4
-rw-r--r--src/librustc_trans/save/mod.rs4
-rw-r--r--src/librustdoc/clean/mod.rs23
-rw-r--r--src/librustrt/unwind.rs2
-rw-r--r--src/libserialize/json.rs4
-rw-r--r--src/libstd/comm/select.rs2
-rw-r--r--src/libstd/failure.rs2
-rw-r--r--src/libstd/io/mod.rs4
-rw-r--r--src/libstd/rt/backtrace.rs2
-rw-r--r--src/libsyntax/ast.rs4
-rw-r--r--src/libsyntax/ast_util.rs2
-rw-r--r--src/libsyntax/ext/build.rs23
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs2
-rw-r--r--src/libsyntax/ext/deriving/generic/ty.rs4
-rw-r--r--src/libsyntax/ext/format.rs2
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs4
-rw-r--r--src/libsyntax/fold.rs10
-rw-r--r--src/libsyntax/parse/mod.rs2
-rw-r--r--src/libsyntax/parse/parser.rs192
-rw-r--r--src/libsyntax/print/pprust.rs52
-rw-r--r--src/libsyntax/test.rs3
-rw-r--r--src/libsyntax/visit.rs12
-rw-r--r--src/libterm/lib.rs2
-rw-r--r--src/test/compile-fail/dst-index.rs2
-rw-r--r--src/test/compile-fail/hrtb-precedence-of-plus-error-message.rs35
-rw-r--r--src/test/compile-fail/issue-12470.rs2
-rw-r--r--src/test/compile-fail/issue-14285.rs2
-rw-r--r--src/test/compile-fail/kindck-copy.rs6
-rw-r--r--src/test/compile-fail/kindck-send-object.rs4
-rw-r--r--src/test/compile-fail/kindck-send-object1.rs4
-rw-r--r--src/test/compile-fail/kindck-send-object2.rs2
-rw-r--r--src/test/compile-fail/region-object-lifetime-1.rs4
-rw-r--r--src/test/compile-fail/regions-bounded-by-send.rs4
-rw-r--r--src/test/compile-fail/regions-close-object-into-object.rs2
-rw-r--r--src/test/compile-fail/regions-trait-variance.rs2
-rw-r--r--src/test/compile-fail/trait-bounds-not-on-impl.rs2
-rw-r--r--src/test/compile-fail/trait-bounds-not-on-struct.rs2
-rw-r--r--src/test/compile-fail/trait-bounds-sugar.rs4
-rw-r--r--src/test/run-pass/colorful-write-macros.rs2
-rw-r--r--src/test/run-pass/dst-index.rs2
-rw-r--r--src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs27
-rw-r--r--src/test/run-pass/hrtb-precedence-of-plus.rs21
-rw-r--r--src/test/run-pass/issue-10902.rs4
-rw-r--r--src/test/run-pass/issue-11205.rs4
-rw-r--r--src/test/run-pass/issue-14901.rs2
-rw-r--r--src/test/run-pass/issue-14958.rs2
-rw-r--r--src/test/run-pass/issue-14959.rs4
-rw-r--r--src/test/run-pass/issue-5708.rs4
-rw-r--r--src/test/run-pass/issue-8249.rs2
-rw-r--r--src/test/run-pass/issue-9719.rs6
-rw-r--r--src/test/run-pass/parameterized-trait-with-bounds.rs2
-rw-r--r--src/test/run-pass/regions-early-bound-trait-param.rs4
63 files changed, 478 insertions, 372 deletions
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 605148beb90..1d6906c13a8 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -85,7 +85,7 @@ pub struct Formatter<'a> {
     width: Option<uint>,
     precision: Option<uint>,
 
-    buf: &'a mut FormatWriter+'a,
+    buf: &'a mut (FormatWriter+'a),
     curarg: slice::Items<'a, Argument<'a>>,
     args: &'a [Argument<'a>],
 }
@@ -565,7 +565,7 @@ 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 {
+impl<'a> Show for &'a (Show+'a) {
     fn fmt(&self, f: &mut Formatter) -> Result { (*self).fmt(f) }
 }
 
@@ -724,7 +724,7 @@ macro_rules! tuple (
 
 tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
 
-impl<'a> Show for &'a any::Any+'a {
+impl<'a> Show for &'a (any::Any+'a) {
     fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") }
 }
 
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 28504210a3f..1873213fadf 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -146,5 +146,6 @@ register_diagnostics!(
     E0167,
     E0168,
     E0169,
-    E0170
+    E0170,
+    E0171
 )
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 9fe7a21243f..1dbd170a0d9 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -421,7 +421,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> {
     fn visit_ty(&mut self, ty: &ast::Ty) {
         match ty.node {
-            ast::TyPath(_, _, id) => self.check_def(ty.span, ty.id, id),
+            ast::TyPath(_, id) => self.check_def(ty.span, ty.id, id),
             _ => (),
         }
         visit::walk_ty(self, ty);
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 7e4d2621f18..8c21e559ec1 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -1230,10 +1230,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_name(rbml_w, item.ident.name);
         encode_attributes(rbml_w, item.attrs.as_slice());
         match ty.node {
-            ast::TyPath(ref path, ref bounds, _) if path.segments
+            ast::TyPath(ref path, _) if path.segments
                                                         .len() == 1 => {
                 let ident = path.segments.last().unwrap().identifier;
-                assert!(bounds.is_none());
                 encode_impl_type_basename(rbml_w, ident);
             }
             _ => {}
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 656feb51a1d..5ab3978b8a8 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -295,7 +295,7 @@ impl OverloadedCallType {
 pub struct ExprUseVisitor<'d,'t,'tcx,TYPER:'t> {
     typer: &'t TYPER,
     mc: mc::MemCategorizationContext<'t,TYPER>,
-    delegate: &'d mut Delegate<'tcx>+'d,
+    delegate: &'d mut (Delegate<'tcx>+'d),
 }
 
 // If the TYPER results in an error, it's because the type check
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 66c782877f9..ec939d19b72 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -243,7 +243,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
             // * Private trait impls for private types can be completely ignored
             ast::ItemImpl(_, _, ref ty, ref impl_items) => {
                 let public_ty = match ty.node {
-                    ast::TyPath(_, _, id) => {
+                    ast::TyPath(_, id) => {
                         match self.tcx.def_map.borrow()[id].clone() {
                             def::DefPrimTy(..) => true,
                             def => {
@@ -311,7 +311,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
 
             ast::ItemTy(ref ty, _) if public_first => {
                 match ty.node {
-                    ast::TyPath(_, _, id) => {
+                    ast::TyPath(_, id) => {
                         match self.tcx.def_map.borrow()[id].clone() {
                             def::DefPrimTy(..) | def::DefTyParam(..) => {},
                             def => {
@@ -616,7 +616,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                     // was private.
                     ast::ItemImpl(_, _, ref ty, _) => {
                         let id = match ty.node {
-                            ast::TyPath(_, _, id) => id,
+                            ast::TyPath(_, id) => id,
                             _ => return Some((err_span, err_msg, None)),
                         };
                         let def = self.tcx.def_map.borrow()[id].clone();
@@ -1292,7 +1292,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
 impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
     fn visit_ty(&mut self, ty: &ast::Ty) {
         match ty.node {
-            ast::TyPath(_, _, path_id) => {
+            ast::TyPath(_, path_id) => {
                 if self.inner.path_is_private_type(path_id) {
                     self.contains_private = true;
                     // found what we're looking for so let's stop
@@ -1493,7 +1493,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
 
     fn visit_ty(&mut self, t: &ast::Ty) {
         match t.node {
-            ast::TyPath(ref p, _, path_id) => {
+            ast::TyPath(ref p, path_id) => {
                 if !self.tcx.sess.features.borrow().visible_private_types &&
                         self.path_is_private_type(path_id) {
                     self.tcx.sess.span_err(p.span,
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 3fcaa43c243..ae32a10f314 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -63,7 +63,7 @@ use syntax::ast::{PolyTraitRef, PrimTy, Public, SelfExplicit, SelfStatic};
 use syntax::ast::{RegionTyParamBound, StmtDecl, StructField};
 use syntax::ast::{StructVariantKind, TraitRef, TraitTyParamBound};
 use syntax::ast::{TupleVariantKind, Ty, TyBool, TyChar, TyClosure, TyF32};
-use syntax::ast::{TyF64, TyFloat, TyI, TyI8, TyI16, TyI32, TyI64, TyInt};
+use syntax::ast::{TyF64, TyFloat, TyI, TyI8, TyI16, TyI32, TyI64, TyInt, TyObjectSum};
 use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyPolyTraitRef, TyProc, TyQPath};
 use syntax::ast::{TyRptr, TyStr, TyU, TyU8, TyU16, TyU32, TyU64, TyUint};
 use syntax::ast::{TypeImplItem, UnnamedField};
@@ -1392,29 +1392,53 @@ impl<'a> Resolver<'a> {
                 // methods within to a new module, if the type was defined
                 // within this module.
 
-                // Create the module and add all methods.
-                match ty.node {
-                    TyPath(ref path, _, _) if path.segments.len() == 1 => {
+                let mod_name = match ty.node {
+                    TyPath(ref path, _) if path.segments.len() == 1 => {
                         // FIXME(18446) we should distinguish between the name of
                         // a trait and the name of an impl of that trait.
-                        let mod_name = path.segments.last().unwrap().identifier.name;
+                        Some(path.segments.last().unwrap().identifier.name)
+                    }
+                    TyObjectSum(ref lhs_ty, _) => {
+                        match lhs_ty.node {
+                            TyPath(ref path, _) if path.segments.len() == 1 => {
+                                Some(path.segments.last().unwrap().identifier.name)
+                            }
+                            _ => {
+                                None
+                            }
+                        }
+                    }
+                    _ => {
+                        None
+                    }
+                };
 
+                match mod_name {
+                    None => {
+                        self.resolve_error(ty.span,
+                                           "inherent implementations may \
+                                            only be implemented in the same \
+                                            module as the type they are \
+                                            implemented for")
+                    }
+                    Some(mod_name) => {
+                        // Create the module and add all methods.
                         let parent_opt = parent.module().children.borrow()
-                                               .get(&mod_name).cloned();
+                            .get(&mod_name).cloned();
                         let new_parent = match parent_opt {
                             // It already exists
                             Some(ref child) if child.get_module_if_available()
-                                                .is_some() &&
-                                           (child.get_module().kind.get() == ImplModuleKind ||
-                                            child.get_module().kind.get() == TraitModuleKind) => {
-                                ModuleReducedGraphParent(child.get_module())
-                            }
+                                .is_some() &&
+                                (child.get_module().kind.get() == ImplModuleKind ||
+                                 child.get_module().kind.get() == TraitModuleKind) => {
+                                    ModuleReducedGraphParent(child.get_module())
+                                }
                             Some(ref child) if child.get_module_if_available()
-                                                .is_some() &&
-                                           child.get_module().kind.get() ==
-                                                EnumModuleKind => {
-                                ModuleReducedGraphParent(child.get_module())
-                            }
+                                .is_some() &&
+                                child.get_module().kind.get() ==
+                                EnumModuleKind => {
+                                    ModuleReducedGraphParent(child.get_module())
+                                }
                             // Create the module
                             _ => {
                                 let name_bindings =
@@ -1429,7 +1453,7 @@ impl<'a> Resolver<'a> {
                                 let ns = TypeNS;
                                 let is_public =
                                     !name_bindings.defined_in_namespace(ns) ||
-                                     name_bindings.defined_in_public_namespace(ns);
+                                    name_bindings.defined_in_public_namespace(ns);
 
                                 name_bindings.define_module(parent_link,
                                                             Some(def_id),
@@ -1455,21 +1479,21 @@ impl<'a> Resolver<'a> {
                                                        ForbidDuplicateValues,
                                                        method.span);
                                     let def = match method.pe_explicit_self()
-                                                          .node {
-                                        SelfStatic => {
-                                            // Static methods become
-                                            // `DefStaticMethod`s.
-                                            DefStaticMethod(local_def(method.id),
-                                                            FromImpl(local_def(item.id)))
-                                        }
-                                        _ => {
-                                            // Non-static methods become
-                                            // `DefMethod`s.
-                                            DefMethod(local_def(method.id),
-                                                      None,
-                                                      FromImpl(local_def(item.id)))
-                                        }
-                                    };
+                                        .node {
+                                            SelfStatic => {
+                                                // Static methods become
+                                                // `DefStaticMethod`s.
+                                                DefStaticMethod(local_def(method.id),
+                                                                FromImpl(local_def(item.id)))
+                                            }
+                                            _ => {
+                                                // Non-static methods become
+                                                // `DefMethod`s.
+                                                DefMethod(local_def(method.id),
+                                                          None,
+                                                          FromImpl(local_def(item.id)))
+                                            }
+                                        };
 
                                     // NB: not IMPORTABLE
                                     let modifiers = if method.pe_vis() == ast::Public {
@@ -1492,7 +1516,7 @@ impl<'a> Resolver<'a> {
                                             ForbidDuplicateTypesAndModules,
                                             typedef.span);
                                     let def = DefAssociatedTy(local_def(
-                                            typedef.id));
+                                        typedef.id));
                                     // NB: not IMPORTABLE
                                     let modifiers = if typedef.vis == ast::Public {
                                         PUBLIC
@@ -1507,13 +1531,6 @@ impl<'a> Resolver<'a> {
                             }
                         }
                     }
-                    _ => {
-                        self.resolve_error(ty.span,
-                                           "inherent implementations may \
-                                            only be implemented in the same \
-                                            module as the type they are \
-                                            implemented for")
-                    }
                 }
 
                 parent
@@ -4721,7 +4738,7 @@ impl<'a> Resolver<'a> {
                 // type, the result will be that the type name resolves to a module but not
                 // a type (shadowing any imported modules or types with this name), leading
                 // to weird user-visible bugs. So we ward this off here. See #15060.
-                TyPath(ref path, _, path_id) => {
+                TyPath(ref path, path_id) => {
                     match self.def_map.borrow().get(&path_id) {
                         // FIXME: should we catch other options and give more precise errors?
                         Some(&DefMod(_)) => {
@@ -4887,7 +4904,7 @@ impl<'a> Resolver<'a> {
             // Like path expressions, the interpretation of path types depends
             // on whether the path has multiple elements in it or not.
 
-            TyPath(ref path, ref bounds, path_id) => {
+            TyPath(ref path, path_id) => {
                 // This is a path in the type namespace. Walk through scopes
                 // looking for it.
                 let mut result_def = None;
@@ -4957,11 +4974,12 @@ impl<'a> Resolver<'a> {
                         self.resolve_error(ty.span, msg.as_slice());
                     }
                 }
+            }
 
-                bounds.as_ref().map(|bound_vec| {
-                    self.resolve_type_parameter_bounds(ty.id, bound_vec,
+            TyObjectSum(ref ty, ref bound_vec) => {
+                self.resolve_type(&**ty);
+                self.resolve_type_parameter_bounds(ty.id, bound_vec,
                                                        TraitBoundingTypeParameter);
-                });
             }
 
             TyQPath(ref qpath) => {
@@ -5598,7 +5616,7 @@ impl<'a> Resolver<'a> {
         fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks)
                                                     -> Option<(Path, NodeId, FallbackChecks)> {
             match t.node {
-                TyPath(ref path, _, node_id) => Some((path.clone(), node_id, allow)),
+                TyPath(ref path, node_id) => Some((path.clone(), node_id, allow)),
                 TyPtr(ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics),
                 TyRptr(_, ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, allow),
                 // This doesn't handle the remaining `Ty` variants as they are not
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index fae64ff9242..02e353d6b1f 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -162,7 +162,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
                     visit::walk_ty(this, ty);
                 });
             }
-            ast::TyPath(ref path, ref opt_bounds, id) => {
+            ast::TyPath(ref path, id) => {
                 // if this path references a trait, then this will resolve to
                 // a trait ref, which introduces a binding scope.
                 match self.def_map.borrow().get(&id) {
@@ -170,13 +170,6 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
                         self.with(LateScope(&Vec::new(), self.scope), |this| {
                             this.visit_path(path, id);
                         });
-
-                        match *opt_bounds {
-                            Some(ref bounds) => {
-                                visit::walk_ty_param_bounds_helper(self, bounds);
-                            }
-                            None => { }
-                        }
                     }
                     _ => {
                         visit::walk_ty(self, ty);
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index dd6b1ffd1a5..436ab919ddb 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -43,7 +43,7 @@ use util::ppaux::Repr;
 pub struct SelectionContext<'cx, 'tcx:'cx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
     param_env: &'cx ty::ParameterEnvironment<'tcx>,
-    typer: &'cx Typer<'tcx>+'cx,
+    typer: &'cx (Typer<'tcx>+'cx),
 
     /// Skolemizer used specifically for skolemizing entries on the
     /// obligation stack. This ensures that all entries on the stack
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index fd5b1bd4793..8f1e2d115d3 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -59,8 +59,9 @@ use middle::typeck::rscope::{UnelidableRscope, RegionScope, SpecificRscope,
                              ShiftedRscope, BindingRscope};
 use middle::typeck::rscope;
 use middle::typeck::TypeAndSubsts;
+use util::common::ErrorReported;
 use util::nodemap::DefIdMap;
-use util::ppaux::{Repr, UserString};
+use util::ppaux::{mod, Repr, UserString};
 
 use std::rc::Rc;
 use std::iter::AdditiveIterator;
@@ -585,7 +586,7 @@ fn check_path_args(tcx: &ty::ctxt,
 pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
                                -> Option<Ty<'tcx>> {
     match ast_ty.node {
-        ast::TyPath(ref path, _, id) => {
+        ast::TyPath(ref path, id) => {
             let a_def = match tcx.def_map.borrow().get(&id) {
                 None => {
                     tcx.sess.span_bug(ast_ty.span,
@@ -642,7 +643,7 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
     }
 
     match ast_ty.node {
-        ast::TyPath(ref path, _, id) => {
+        ast::TyPath(ref path, id) => {
             let a_def = match this.tcx().def_map.borrow().get(&id) {
                 None => {
                     this.tcx()
@@ -682,64 +683,92 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
     }
 }
 
-// Handle `~`, `Box`, and `&` being able to mean strs and vecs.
-// If a_seq_ty is a str or a vec, make it a str/vec.
-// Also handle first-class trait types.
-fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
-        this: &AC,
-        rscope: &RS,
-        a_seq_mutbl: ast::Mutability,
-        a_seq_ty: &ast::Ty,
-        region: ty::Region,
-        constr: |Ty<'tcx>| -> Ty<'tcx>)
-        -> Ty<'tcx>
+fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
+                                   rscope: &RS,
+                                   ty: &ast::Ty,
+                                   bounds: &[ast::TyParamBound])
+                                   -> Result<ty::TraitRef<'tcx>, ErrorReported>
+    where AC : AstConv<'tcx>, RS : RegionScope
 {
-    let tcx = this.tcx();
-
-    debug!("mk_pointer(region={}, a_seq_ty={})",
-           region,
-           a_seq_ty.repr(tcx));
+    /*!
+     * In a type like `Foo + Send`, we want to wait to collect the
+     * full set of bounds before we make the object type, because we
+     * need them to infer a region bound.  (For example, if we tried
+     * made a type from just `Foo`, then it wouldn't be enough to
+     * infer a 'static bound, and hence the user would get an error.)
+     * So this function is used when we're dealing with a sum type to
+     * convert the LHS. It only accepts a type that refers to a trait
+     * name, and reports an error otherwise.
+     */
 
-    match a_seq_ty.node {
-        ast::TyVec(ref ty) => {
-            let ty = ast_ty_to_ty(this, rscope, &**ty);
-            return constr(ty::mk_vec(tcx, ty, None));
+    match ty.node {
+        ast::TyPath(ref path, id) => {
+            match this.tcx().def_map.borrow().get(&id) {
+                Some(&def::DefTrait(trait_def_id)) => {
+                    return Ok(ast_path_to_trait_ref(this,
+                                                    rscope,
+                                                    trait_def_id,
+                                                    None,
+                                                    path));
+                }
+                _ => {
+                    span_err!(this.tcx().sess, ty.span, E0170, "expected a reference to a trait");
+                    Err(ErrorReported)
+                }
+            }
         }
-        ast::TyPath(ref path, ref opt_bounds, id) => {
-            // Note that the "bounds must be empty if path is not a trait"
-            // restriction is enforced in the below case for ty_path, which
-            // will run after this as long as the path isn't a trait.
-            match tcx.def_map.borrow().get(&id) {
-                Some(&def::DefPrimTy(ast::TyStr)) => {
-                    check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                    return ty::mk_str_slice(tcx, region, a_seq_mutbl);
+        _ => {
+            span_err!(this.tcx().sess, ty.span, E0171,
+                      "expected a path on the left-hand side of `+`, not `{}`",
+                      pprust::ty_to_string(ty));
+            match ty.node {
+                ast::TyRptr(None, ref mut_ty) => {
+                    span_note!(this.tcx().sess, ty.span,
+                               "perhaps you meant `&{}({} +{})`? (per RFC 248)",
+                               ppaux::mutability_to_string(mut_ty.mutbl),
+                               pprust::ty_to_string(&*mut_ty.ty),
+                               pprust::bounds_to_string(bounds));
                 }
-                Some(&def::DefTrait(trait_def_id)) => {
-                    let result = ast_path_to_trait_ref(this,
-                                                       rscope,
-                                                       trait_def_id,
-                                                       None,
-                                                       path);
-                    let empty_vec = [];
-                    let bounds = match *opt_bounds { None => empty_vec.as_slice(),
-                                                     Some(ref bounds) => bounds.as_slice() };
-                    let existential_bounds = conv_existential_bounds(this,
-                                                                     rscope,
-                                                                     path.span,
-                                                                     &[Rc::new(result.clone())],
-                                                                     bounds);
-                    let tr = ty::mk_trait(tcx,
-                                          result,
-                                          existential_bounds);
-                    return ty::mk_rptr(tcx, region, ty::mt{mutbl: a_seq_mutbl, ty: tr});
+
+                ast::TyRptr(Some(ref lt), ref mut_ty) => {
+                    span_note!(this.tcx().sess, ty.span,
+                               "perhaps you meant `&{} {}({} +{})`? (per RFC 248)",
+                               pprust::lifetime_to_string(lt),
+                               ppaux::mutability_to_string(mut_ty.mutbl),
+                               pprust::ty_to_string(&*mut_ty.ty),
+                               pprust::bounds_to_string(bounds));
+                }
+
+                _ => {
+                    span_note!(this.tcx().sess, ty.span,
+                               "perhaps you forget parentheses? (per RFC 248)");
                 }
-                _ => {}
             }
+            Err(ErrorReported)
         }
-        _ => {}
     }
 
-    constr(ast_ty_to_ty(this, rscope, a_seq_ty))
+}
+
+fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
+                                        rscope: &RS,
+                                        span: Span,
+                                        trait_ref: ty::TraitRef<'tcx>,
+                                        bounds: &[ast::TyParamBound])
+                                        -> Ty<'tcx>
+    where AC : AstConv<'tcx>, RS : RegionScope
+{
+    let existential_bounds = conv_existential_bounds(this,
+                                                     rscope,
+                                                     span,
+                                                     &[Rc::new(trait_ref.clone())],
+                                                     bounds);
+
+    let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds);
+    debug!("trait_ref_to_object_type: result={}",
+           result.repr(this.tcx()));
+
+    result
 }
 
 fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
@@ -806,6 +835,17 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
             ast::TyVec(ref ty) => {
                 ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
             }
+            ast::TyObjectSum(ref ty, ref bounds) => {
+                match ast_ty_to_trait_ref(this, rscope, &**ty, bounds.as_slice()) {
+                    Ok(trait_ref) => {
+                        trait_ref_to_object_type(this, rscope, ast_ty.span,
+                                                 trait_ref, bounds.as_slice())
+                    }
+                    Err(ErrorReported) => {
+                        ty::mk_err()
+                    }
+                }
+            }
             ast::TyPtr(ref mt) => {
                 ty::mk_ptr(tcx, ty::mt {
                     ty: ast_ty_to_ty(this, rscope, &*mt.ty),
@@ -815,8 +855,8 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
             ast::TyRptr(ref region, ref mt) => {
                 let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
                 debug!("ty_rptr r={}", r.repr(this.tcx()));
-                mk_pointer(this, rscope, mt.mutbl, &*mt.ty, r,
-                           |ty| ty::mk_rptr(tcx, r, ty::mt {ty: ty, mutbl: mt.mutbl}))
+                let t = ast_ty_to_ty(this, rscope, &*mt.ty);
+                ty::mk_rptr(tcx, r, ty::mt {ty: t, mutbl: mt.mutbl})
             }
             ast::TyTup(ref fields) => {
                 let flds = fields.iter()
@@ -874,7 +914,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
             ast::TyPolyTraitRef(ref bounds) => {
                 conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds.as_slice())
             }
-            ast::TyPath(ref path, ref bounds, id) => {
+            ast::TyPath(ref path, id) => {
                 let a_def = match tcx.def_map.borrow().get(&id) {
                     None => {
                         tcx.sess
@@ -884,35 +924,16 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                     }
                     Some(&d) => d
                 };
-                // Kind bounds on path types are only supported for traits.
-                match a_def {
-                    // But don't emit the error if the user meant to do a trait anyway.
-                    def::DefTrait(..) => { },
-                    _ if bounds.is_some() =>
-                        tcx.sess.span_err(ast_ty.span,
-                                          "kind bounds can only be used on trait types"),
-                    _ => { },
-                }
                 match a_def {
                     def::DefTrait(trait_def_id) => {
+                        // N.B. this case overlaps somewhat with
+                        // TyObjectSum, see that fn for details
                         let result = ast_path_to_trait_ref(this,
                                                            rscope,
                                                            trait_def_id,
                                                            None,
                                                            path);
-                        let empty_bounds: &[ast::TyParamBound] = &[];
-                        let ast_bounds = match *bounds {
-                            Some(ref b) => b.as_slice(),
-                            None => empty_bounds
-                        };
-                        let bounds = conv_existential_bounds(this,
-                                                             rscope,
-                                                             ast_ty.span,
-                                                             &[Rc::new(result.clone())],
-                                                             ast_bounds);
-                        let result_ty = ty::mk_trait(tcx, result, bounds);
-                        debug!("ast_ty_to_ty: result_ty={}", result_ty.repr(this.tcx()));
-                        result_ty
+                        trait_ref_to_object_type(this, rscope, path.span, result, &[])
                     }
                     def::DefTy(did, _) | def::DefStruct(did) => {
                         ast_path_to_ty(this, rscope, did, path).ty
diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs
index bc36a2bd801..a78977d9fc7 100644
--- a/src/librustc/middle/typeck/infer/error_reporting.rs
+++ b/src/librustc/middle/typeck/infer/error_reporting.rs
@@ -1249,7 +1249,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                     }
                     ty_queue.push(&*mut_ty.ty);
                 }
-                ast::TyPath(ref path, ref bounds, id) => {
+                ast::TyPath(ref path, id) => {
                     let a_def = match self.tcx.def_map.borrow().get(&id) {
                         None => {
                             self.tcx
@@ -1296,7 +1296,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                             let new_path = self.rebuild_path(rebuild_info, lifetime);
                             let to = ast::Ty {
                                 id: cur_ty.id,
-                                node: ast::TyPath(new_path, bounds.clone(), id),
+                                node: ast::TyPath(new_path, id),
                                 span: cur_ty.span
                             };
                             new_ty = self.rebuild_ty(new_ty, P(to));
diff --git a/src/librustc/middle/typeck/rscope.rs b/src/librustc/middle/typeck/rscope.rs
index 2f72d3cf50d..3bca24f479f 100644
--- a/src/librustc/middle/typeck/rscope.rs
+++ b/src/librustc/middle/typeck/rscope.rs
@@ -139,11 +139,11 @@ impl RegionScope for BindingRscope {
 /// A scope which simply shifts the Debruijn index of other scopes
 /// to account for binding levels.
 pub struct ShiftedRscope<'r> {
-    base_scope: &'r RegionScope+'r
+    base_scope: &'r (RegionScope+'r)
 }
 
 impl<'r> ShiftedRscope<'r> {
-    pub fn new(base_scope: &'r RegionScope+'r) -> ShiftedRscope<'r> {
+    pub fn new(base_scope: &'r (RegionScope+'r)) -> ShiftedRscope<'r> {
         ShiftedRscope { base_scope: base_scope }
     }
 }
diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs
index ba6292f8975..f5c732d9adc 100644
--- a/src/librustc_trans/save/mod.rs
+++ b/src/librustc_trans/save/mod.rs
@@ -651,7 +651,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
                     typ: &ast::Ty,
                     impl_items: &Vec<ast::ImplItem>) {
         match typ.node {
-            ast::TyPath(ref path, _, id) => {
+            ast::TyPath(ref path, id) => {
                 match self.lookup_type_ref(id) {
                     Some(id) => {
                         let sub_span = self.span.sub_span_for_type_name(path.span);
@@ -1256,7 +1256,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
         }
 
         match t.node {
-            ast::TyPath(ref path, _, id) => {
+            ast::TyPath(ref path, id) => {
                 match self.lookup_type_ref(id) {
                     Some(id) => {
                         let sub_span = self.span.sub_span_for_type_name(t.span);
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index db23ec07a84..8270c8f3a20 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -992,7 +992,7 @@ impl Clean<Item> for doctree::Trait {
 
 impl Clean<Type> for ast::TraitRef {
     fn clean(&self, cx: &DocContext) -> Type {
-        resolve_type(cx, self.path.clean(cx), None, self.ref_id)
+        resolve_type(cx, self.path.clean(cx), self.ref_id)
     }
 }
 
@@ -1278,8 +1278,19 @@ impl Clean<Type> for ast::Ty {
             TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx),
                                                            e.span.to_src(cx)),
             TyTup(ref tys) => Tuple(tys.clean(cx)),
-            TyPath(ref p, ref tpbs, id) => {
-                resolve_type(cx, p.clean(cx), tpbs.clean(cx), id)
+            TyPath(ref p, id) => {
+                resolve_type(cx, p.clean(cx), id)
+            }
+            TyObjectSum(ref lhs, ref bounds) => {
+                let lhs_ty = lhs.clean(cx);
+                match lhs_ty {
+                    ResolvedPath { path, typarams: None, did } => {
+                        ResolvedPath { path: path, typarams: Some(bounds.clean(cx)), did: did}
+                    }
+                    _ => {
+                        lhs_ty // shouldn't happen
+                    }
+                }
             }
             TyClosure(ref c) => Closure(box c.clean(cx)),
             TyProc(ref c) => Proc(box c.clean(cx)),
@@ -2130,8 +2141,8 @@ fn name_from_pat(p: &ast::Pat) -> String {
 }
 
 /// Given a Type, resolve it using the def_map
-fn resolve_type(cx: &DocContext, path: Path,
-                tpbs: Option<Vec<TyParamBound>>,
+fn resolve_type(cx: &DocContext,
+                path: Path,
                 id: ast::NodeId) -> Type {
     let tcx = match cx.tcx_opt() {
         Some(tcx) => tcx,
@@ -2168,7 +2179,7 @@ fn resolve_type(cx: &DocContext, path: Path,
         _ => {}
     };
     let did = register_def(&*cx, def);
-    ResolvedPath { path: path, typarams: tpbs, did: did }
+    ResolvedPath { path: path, typarams: None, did: did }
 }
 
 fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId {
diff --git a/src/librustrt/unwind.rs b/src/librustrt/unwind.rs
index 7544b93ce52..697ee95df4c 100644
--- a/src/librustrt/unwind.rs
+++ b/src/librustrt/unwind.rs
@@ -86,7 +86,7 @@ struct Exception {
     cause: Option<Box<Any + Send>>,
 }
 
-pub type Callback = fn(msg: &Any + Send, file: &'static str, line: uint);
+pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: uint);
 
 // Variables used for invoking callbacks when a task starts to unwind.
 //
diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs
index 473552ab0ff..15c554be5d9 100644
--- a/src/libserialize/json.rs
+++ b/src/libserialize/json.rs
@@ -397,7 +397,7 @@ fn fmt_number_or_null(v: f64) -> string::String {
 
 /// A structure for implementing serialization to JSON.
 pub struct Encoder<'a> {
-    writer: &'a mut io::Writer+'a,
+    writer: &'a mut (io::Writer+'a),
 }
 
 impl<'a> Encoder<'a> {
@@ -601,7 +601,7 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
 /// Another encoder for JSON, but prints out human-readable JSON instead of
 /// compact data
 pub struct PrettyEncoder<'a> {
-    writer: &'a mut io::Writer+'a,
+    writer: &'a mut (io::Writer+'a),
     curr_indent: uint,
     indent: uint,
 }
diff --git a/src/libstd/comm/select.rs b/src/libstd/comm/select.rs
index 621556f75ce..3191519815a 100644
--- a/src/libstd/comm/select.rs
+++ b/src/libstd/comm/select.rs
@@ -84,7 +84,7 @@ pub struct Handle<'rx, T:'rx> {
     next: *mut Handle<'static, ()>,
     prev: *mut Handle<'static, ()>,
     added: bool,
-    packet: &'rx Packet+'rx,
+    packet: &'rx (Packet+'rx),
 
     // due to our fun transmutes, we be sure to place this at the end. (nothing
     // previous relies on T)
diff --git a/src/libstd/failure.rs b/src/libstd/failure.rs
index 32a8be22902..d839c1484e5 100644
--- a/src/libstd/failure.rs
+++ b/src/libstd/failure.rs
@@ -40,7 +40,7 @@ impl Writer for Stdio {
     }
 }
 
-pub fn on_fail(obj: &Any + Send, file: &'static str, line: uint) {
+pub fn on_fail(obj: &(Any+Send), file: &'static str, line: uint) {
     let msg = match obj.downcast_ref::<&'static str>() {
         Some(s) => *s,
         None => match obj.downcast_ref::<String>() {
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index ba9b074470d..3b272c3fe5d 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -910,7 +910,7 @@ impl<'a> Reader for Box<Reader+'a> {
     }
 }
 
-impl<'a> Reader for &'a mut Reader+'a {
+impl<'a> Reader for &'a mut (Reader+'a) {
     fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { (*self).read(buf) }
 }
 
@@ -1278,7 +1278,7 @@ impl<'a> Writer for Box<Writer+'a> {
     }
 }
 
-impl<'a> Writer for &'a mut Writer+'a {
+impl<'a> Writer for &'a mut (Writer+'a) {
     #[inline]
     fn write(&mut self, buf: &[u8]) -> IoResult<()> { (**self).write(buf) }
 
diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs
index 4f6c1f8a2c6..d375ddcc94b 100644
--- a/src/libstd/rt/backtrace.rs
+++ b/src/libstd/rt/backtrace.rs
@@ -288,7 +288,7 @@ mod imp {
 
         struct Context<'a> {
             idx: int,
-            writer: &'a mut Writer+'a,
+            writer: &'a mut (Writer+'a),
             last_error: Option<IoError>,
         }
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 3d33774aa55..14f164ff23b 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1151,7 +1151,9 @@ pub enum Ty_ {
     /// A path (`module::module::...::Type`) or primitive
     ///
     /// Type parameters are stored in the Path itself
-    TyPath(Path, Option<TyParamBounds>, NodeId), // for #7264; see above
+    TyPath(Path, NodeId),
+    /// Something like `A+B`. Note that `B` must always be a path.
+    TyObjectSum(P<Ty>, TyParamBounds),
     /// A type like `for<'a> Foo<&'a Bar>`
     TyPolyTraitRef(TyParamBounds),
     /// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 043e79bffd9..4d6ac4f3430 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -454,7 +454,7 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
     fn visit_ty(&mut self, typ: &Ty) {
         self.operation.visit_id(typ.id);
         match typ.node {
-            TyPath(_, _, id) => self.operation.visit_id(id),
+            TyPath(_, id) => self.operation.visit_id(id),
             _ => {}
         }
         visit::walk_ty(self, typ)
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 2c7f9e889f8..bd01e5e6430 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -44,7 +44,8 @@ pub trait AstBuilder {
     fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy;
 
     fn ty(&self, span: Span, ty: ast::Ty_) -> P<ast::Ty>;
-    fn ty_path(&self, ast::Path, Option<OwnedSlice<ast::TyParamBound>>) -> P<ast::Ty>;
+    fn ty_path(&self, ast::Path) -> P<ast::Ty>;
+    fn ty_sum(&self, ast::Path, OwnedSlice<ast::TyParamBound>) -> P<ast::Ty>;
     fn ty_ident(&self, span: Span, idents: ast::Ident) -> P<ast::Ty>;
 
     fn ty_rptr(&self, span: Span,
@@ -344,17 +345,21 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         })
     }
 
-    fn ty_path(&self, path: ast::Path, bounds: Option<OwnedSlice<ast::TyParamBound>>)
-              -> P<ast::Ty> {
+    fn ty_path(&self, path: ast::Path) -> P<ast::Ty> {
+        self.ty(path.span, ast::TyPath(path, ast::DUMMY_NODE_ID))
+    }
+
+    fn ty_sum(&self, path: ast::Path, bounds: OwnedSlice<ast::TyParamBound>) -> P<ast::Ty> {
         self.ty(path.span,
-                ast::TyPath(path, bounds, ast::DUMMY_NODE_ID))
+                ast::TyObjectSum(self.ty_path(path),
+                                 bounds))
     }
 
     // Might need to take bounds as an argument in the future, if you ever want
     // to generate a bounded existential trait type.
     fn ty_ident(&self, span: Span, ident: ast::Ident)
         -> P<ast::Ty> {
-        self.ty_path(self.path_ident(span, ident), None)
+        self.ty_path(self.path_ident(span, ident))
     }
 
     fn ty_rptr(&self,
@@ -386,7 +391,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                               self.ident_of("Option")
                           ),
                           Vec::new(),
-                          vec!( ty )), None)
+                          vec!( ty )))
     }
 
     fn ty_field_imm(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> ast::TypeField {
@@ -425,8 +430,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
 
     fn ty_vars_global(&self, ty_params: &OwnedSlice<ast::TyParam>) -> Vec<P<ast::Ty>> {
-        ty_params.iter().map(|p| self.ty_path(
-                self.path_global(DUMMY_SP, vec!(p.ident)), None)).collect()
+        ty_params
+            .iter()
+            .map(|p| self.ty_path(self.path_global(DUMMY_SP, vec!(p.ident))))
+            .collect()
     }
 
     fn trait_ref(&self, path: ast::Path) -> ast::TraitRef {
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index fcd4966683d..d5f472bd827 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -444,7 +444,7 @@ impl<'a> TraitDef<'a> {
         // Create the type of `self`.
         let self_type = cx.ty_path(
             cx.path_all(self.span, false, vec!( type_ident ), self_lifetimes,
-                        self_ty_params.into_vec()), None);
+                        self_ty_params.into_vec()));
 
         let attr = cx.attribute(
             self.span,
diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs
index 700ada8b4ad..6614ab50f1e 100644
--- a/src/libsyntax/ext/deriving/generic/ty.rs
+++ b/src/libsyntax/ext/deriving/generic/ty.rs
@@ -70,7 +70,7 @@ impl<'a> Path<'a> {
                  self_ty: Ident,
                  self_generics: &Generics)
                  -> P<ast::Ty> {
-        cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
+        cx.ty_path(self.to_path(cx, span, self_ty, self_generics))
     }
     pub fn to_path(&self,
                    cx: &ExtCtxt,
@@ -152,7 +152,7 @@ impl<'a> Ty<'a> {
             }
             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), None)
+                cx.ty_path(self.to_path(cx, span, self_ty, self_generics))
             }
             Tuple(ref fields) => {
                 let ty = ast::TyTup(fields.iter()
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index 490246f8246..d7d6c636849 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -531,7 +531,7 @@ impl<'a, 'b> Context<'a, 'b> {
                     true, Context::rtpath(self.ecx, "Argument"),
                     vec![static_lifetime],
                     vec![]
-                ), None);
+                ));
             lets.push(Context::item_static_array(self.ecx,
                                                  static_args_name,
                                                  piece_ty,
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index b4cd9779ae2..4785fe37293 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -514,7 +514,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal {
       "stmt" => token::NtStmt(p.parse_stmt(Vec::new())),
       "pat" => token::NtPat(p.parse_pat()),
       "expr" => token::NtExpr(p.parse_expr()),
-      "ty" => token::NtTy(p.parse_ty(false /* no need to disambiguate*/)),
+      "ty" => token::NtTy(p.parse_ty()),
       // this could be handled like a token, since it is one
       "ident" => match p.token {
         token::Ident(sn,b) => { p.bump(); token::NtIdent(box sn,b) }
@@ -525,7 +525,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal {
         }
       },
       "path" => {
-        token::NtPath(box p.parse_path(LifetimeAndTypesWithoutColons).path)
+        token::NtPath(box p.parse_path(LifetimeAndTypesWithoutColons))
       }
       "meta" => token::NtMeta(p.parse_meta_item()),
       "tt" => {
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 6941c0e9c18..122f99cabb3 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -433,11 +433,13 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
             }
             TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))),
             TyParen(ty) => TyParen(fld.fold_ty(ty)),
-            TyPath(path, bounds, id) => {
+            TyPath(path, id) => {
                 let id = fld.new_id(id);
-                TyPath(fld.fold_path(path),
-                        fld.fold_opt_bounds(bounds),
-                        id)
+                TyPath(fld.fold_path(path), id)
+            }
+            TyObjectSum(ty, bounds) => {
+                TyObjectSum(fld.fold_ty(ty),
+                            fld.fold_bounds(bounds))
             }
             TyQPath(qpath) => {
                 TyQPath(fld.fold_qpath(qpath))
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 96659031e6a..b46f7cdfe22 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -1029,7 +1029,7 @@ mod test {
                                                 parameters: ast::PathParameters::none(),
                                             }
                                         ),
-                                        }, None, ast::DUMMY_NODE_ID),
+                                        }, ast::DUMMY_NODE_ID),
                                         span:sp(10,13)
                                     }),
                                     pat: P(ast::Pat {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index c731a0005f8..35187ebb522 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -111,16 +111,6 @@ pub enum PathParsingMode {
     /// A path with a lifetime and type parameters with double colons before
     /// the type parameters; e.g. `foo::bar::<'a>::Baz::<T>`
     LifetimeAndTypesWithColons,
-    /// A path with a lifetime and type parameters with bounds before the last
-    /// set of type parameters only; e.g. `foo::bar<'a>::Baz+X+Y<T>` This
-    /// form does not use extra double colons.
-    LifetimeAndTypesAndBounds,
-}
-
-/// A path paired with optional type bounds.
-pub struct PathAndBounds {
-    pub path: ast::Path,
-    pub bounds: Option<ast::TyParamBounds>,
 }
 
 enum ItemOrViewItem {
@@ -1053,17 +1043,9 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub fn parse_ty_path(&mut self, plus_allowed: bool) -> Ty_ {
-        let mode = if plus_allowed {
-            LifetimeAndTypesAndBounds
-        } else {
-            LifetimeAndTypesWithoutColons
-        };
-        let PathAndBounds {
-            path,
-            bounds
-        } = self.parse_path(mode);
-        TyPath(path, bounds, ast::DUMMY_NODE_ID)
+    pub fn parse_ty_path(&mut self) -> Ty_ {
+        let path = self.parse_path(LifetimeAndTypesWithoutColons);
+        TyPath(path, ast::DUMMY_NODE_ID)
     }
 
     /// parse a TyBareFn type:
@@ -1286,7 +1268,7 @@ impl<'a> Parser<'a> {
         let lo = self.span.lo;
         let ident = self.parse_ident();
         self.expect(&token::Eq);
-        let typ = self.parse_ty(true);
+        let typ = self.parse_ty_sum();
         let hi = self.span.hi;
         self.expect(&token::Semi);
         Typedef {
@@ -1385,7 +1367,7 @@ impl<'a> Parser<'a> {
     /// Parse a possibly mutable type
     pub fn parse_mt(&mut self) -> MutTy {
         let mutbl = self.parse_mutability();
-        let t = self.parse_ty(true);
+        let t = self.parse_ty();
         MutTy { ty: t, mutbl: mutbl }
     }
 
@@ -1396,7 +1378,7 @@ impl<'a> Parser<'a> {
         let mutbl = self.parse_mutability();
         let id = self.parse_ident();
         self.expect(&token::Colon);
-        let ty = self.parse_ty(true);
+        let ty = self.parse_ty_sum();
         let hi = ty.span.hi;
         ast::TypeField {
             ident: id,
@@ -1411,7 +1393,19 @@ impl<'a> Parser<'a> {
             if self.eat(&token::Not) {
                 NoReturn(self.span)
             } else {
-                Return(self.parse_ty(true))
+                let t = self.parse_ty();
+
+                // We used to allow `fn foo() -> &T + U`, but don't
+                // anymore. If we see it, report a useful error.  This
+                // only makes sense because `parse_ret_ty` is only
+                // used in fn *declarations*, not fn types or where
+                // clauses (i.e., not when parsing something like
+                // `FnMut() -> T + Send`, where the `+` is legal).
+                if self.token == token::BinOp(token::Plus) {
+                    self.warn("deprecated syntax: `()` are required, see RFC 248 for details");
+                }
+
+                Return(t)
             }
         } else {
             let pos = self.span.lo;
@@ -1423,11 +1417,36 @@ impl<'a> Parser<'a> {
         }
     }
 
+    /// Parse a type in a context where `T1+T2` is allowed.
+    pub fn parse_ty_sum(&mut self) -> P<Ty> {
+        let lo = self.span.lo;
+        let lhs = self.parse_ty();
+
+        if !self.eat(&token::BinOp(token::Plus)) {
+            return lhs;
+        }
+
+        let bounds = self.parse_ty_param_bounds();
+
+        // In type grammar, `+` is treated like a binary operator,
+        // and hence both L and R side are required.
+        if bounds.len() == 0 {
+            let last_span = self.last_span;
+            self.span_err(last_span,
+                          "at least one type parameter bound \
+                          must be specified");
+        }
+
+        let sp = mk_sp(lo, self.last_span.hi);
+        let sum = ast::TyObjectSum(lhs, bounds);
+        P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp})
+    }
+
     /// Parse a type.
     ///
     /// The second parameter specifies whether the `+` binary operator is
     /// allowed in the type grammar.
-    pub fn parse_ty(&mut self, plus_allowed: bool) -> P<Ty> {
+    pub fn parse_ty(&mut self) -> P<Ty> {
         maybe_whole!(no_clone self, NtTy);
 
         let lo = self.span.lo;
@@ -1441,7 +1460,7 @@ impl<'a> Parser<'a> {
             let mut ts = vec![];
             let mut last_comma = false;
             while self.token != token::CloseDelim(token::Paren) {
-                ts.push(self.parse_ty(true));
+                ts.push(self.parse_ty_sum());
                 if self.token == token::Comma {
                     last_comma = true;
                     self.bump();
@@ -1465,7 +1484,7 @@ impl<'a> Parser<'a> {
                 token::OpenDelim(token::Bracket) => self.obsolete(last_span, ObsoleteOwnedVector),
                 _ => self.obsolete(last_span, ObsoleteOwnedType)
             }
-            TyTup(vec![self.parse_ty(false)])
+            TyTup(vec![self.parse_ty()])
         } else if self.token == token::BinOp(token::Star) {
             // STAR POINTER (bare pointer?)
             self.bump();
@@ -1473,7 +1492,7 @@ impl<'a> Parser<'a> {
         } else if self.token == token::OpenDelim(token::Bracket) {
             // VECTOR
             self.expect(&token::OpenDelim(token::Bracket));
-            let t = self.parse_ty(true);
+            let t = self.parse_ty_sum();
 
             // Parse the `, ..e` in `[ int, ..e ]`
             // where `e` is a const expression
@@ -1514,7 +1533,7 @@ impl<'a> Parser<'a> {
         } else if self.token == token::Lt {
             // QUALIFIED PATH `<TYPE as TRAIT_REF>::item`
             self.bump();
-            let self_type = self.parse_ty(true);
+            let self_type = self.parse_ty_sum();
             self.expect_keyword(keywords::As);
             let trait_ref = self.parse_trait_ref();
             self.expect(&token::Gt);
@@ -1529,7 +1548,7 @@ impl<'a> Parser<'a> {
                   self.token.is_ident() ||
                   self.token.is_path() {
             // NAMED TYPE
-            self.parse_ty_path(plus_allowed)
+            self.parse_ty_path()
         } else if self.eat(&token::Underscore) {
             // TYPE TO BE INFERRED
             TyInfer
@@ -1563,7 +1582,7 @@ impl<'a> Parser<'a> {
                            known as `*const T`");
             MutImmutable
         };
-        let t = self.parse_ty(true);
+        let t = self.parse_ty();
         MutTy { ty: t, mutbl: mutbl }
     }
 
@@ -1603,7 +1622,7 @@ impl<'a> Parser<'a> {
                                    special_idents::invalid)
         };
 
-        let t = self.parse_ty(true);
+        let t = self.parse_ty_sum();
 
         Arg {
             ty: t,
@@ -1621,7 +1640,7 @@ impl<'a> Parser<'a> {
     pub fn parse_fn_block_arg(&mut self) -> Arg {
         let pat = self.parse_pat();
         let t = if self.eat(&token::Colon) {
-            self.parse_ty(true)
+            self.parse_ty_sum()
         } else {
             P(Ty {
                 id: ast::DUMMY_NODE_ID,
@@ -1739,7 +1758,7 @@ impl<'a> Parser<'a> {
     /// mode. The `mode` parameter determines whether lifetimes, types, and/or
     /// bounds are permitted and whether `::` must precede type parameter
     /// groups.
-    pub fn parse_path(&mut self, mode: PathParsingMode) -> PathAndBounds {
+    pub fn parse_path(&mut self, mode: PathParsingMode) -> ast::Path {
         // Check for a whole path...
         let found = match self.token {
             token::Interpolated(token::NtPath(_)) => Some(self.bump_and_get()),
@@ -1747,10 +1766,7 @@ impl<'a> Parser<'a> {
         };
         match found {
             Some(token::Interpolated(token::NtPath(box path))) => {
-                return PathAndBounds {
-                    path: path,
-                    bounds: None
-                }
+                return path;
             }
             _ => {}
         }
@@ -1762,8 +1778,7 @@ impl<'a> Parser<'a> {
         // identifier followed by an optional lifetime and a set of types.
         // A bound set is a set of type parameter bounds.
         let segments = match mode {
-            LifetimeAndTypesWithoutColons |
-            LifetimeAndTypesAndBounds => {
+            LifetimeAndTypesWithoutColons => {
                 self.parse_path_segments_without_colons()
             }
             LifetimeAndTypesWithColons => {
@@ -1774,44 +1789,14 @@ impl<'a> Parser<'a> {
             }
         };
 
-        // Next, parse a plus and bounded type parameters, if
-        // applicable. We need to remember whether the separate was
-        // present for later, because in some contexts it's a parse
-        // error.
-        let opt_bounds = {
-            if mode == LifetimeAndTypesAndBounds &&
-                self.eat(&token::BinOp(token::Plus))
-            {
-                let bounds = self.parse_ty_param_bounds();
-
-                // For some reason that I do not fully understand, we
-                // do not permit an empty list in the case where it is
-                // introduced by a `+`, but we do for `:` and other
-                // separators. -nmatsakis
-                if bounds.len() == 0 {
-                    let last_span = self.last_span;
-                    self.span_err(last_span,
-                                  "at least one type parameter bound \
-                                   must be specified");
-                }
-
-                Some(bounds)
-            } else {
-                None
-            }
-        };
-
         // Assemble the span.
         let span = mk_sp(lo, self.last_span.hi);
 
         // Assemble the result.
-        PathAndBounds {
-            path: ast::Path {
-                span: span,
-                global: is_global,
-                segments: segments,
-            },
-            bounds: opt_bounds,
+        ast::Path {
+            span: span,
+            global: is_global,
+            segments: segments,
         }
     }
 
@@ -1837,10 +1822,10 @@ impl<'a> Parser<'a> {
                 let inputs = self.parse_seq_to_end(
                     &token::CloseDelim(token::Paren),
                     seq_sep_trailing_allowed(token::Comma),
-                    |p| p.parse_ty(true));
+                    |p| p.parse_ty_sum());
 
                 let output_ty = if self.eat(&token::RArrow) {
-                    Some(self.parse_ty(true))
+                    Some(self.parse_ty())
                 } else {
                     None
                 };
@@ -2327,7 +2312,7 @@ impl<'a> Parser<'a> {
                         !self.token.is_keyword(keywords::True) &&
                         !self.token.is_keyword(keywords::False) {
                     let pth =
-                        self.parse_path(LifetimeAndTypesWithColons).path;
+                        self.parse_path(LifetimeAndTypesWithColons);
 
                     // `!`, as an operator, is prefix, so we know this isn't that
                     if self.token == token::Not {
@@ -2898,7 +2883,7 @@ impl<'a> Parser<'a> {
             }
             None => {
                 if as_prec > min_prec && self.eat_keyword(keywords::As) {
-                    let rhs = self.parse_ty(false);
+                    let rhs = self.parse_ty();
                     let _as = self.mk_expr(lhs.span.lo,
                                            rhs.span.hi,
                                            ExprCast(lhs, rhs));
@@ -3362,8 +3347,7 @@ impl<'a> Parser<'a> {
                     }) {
                 self.bump();
                 let end = if self.token.is_ident() || self.token.is_path() {
-                    let path = self.parse_path(LifetimeAndTypesWithColons)
-                                   .path;
+                    let path = self.parse_path(LifetimeAndTypesWithColons);
                     let hi = self.span.hi;
                     self.mk_expr(lo, hi, ExprPath(path))
                 } else {
@@ -3433,8 +3417,7 @@ impl<'a> Parser<'a> {
                 }
             } else {
                 // parse an enum pat
-                let enum_path = self.parse_path(LifetimeAndTypesWithColons)
-                                    .path;
+                let enum_path = self.parse_path(LifetimeAndTypesWithColons);
                 match self.token {
                     token::OpenDelim(token::Brace) => {
                         self.bump();
@@ -3548,7 +3531,7 @@ impl<'a> Parser<'a> {
             span: mk_sp(lo, lo),
         });
         if self.eat(&token::Colon) {
-            ty = self.parse_ty(true);
+            ty = self.parse_ty_sum();
         }
         let init = self.parse_initializer();
         P(ast::Local {
@@ -3577,7 +3560,7 @@ impl<'a> Parser<'a> {
         }
         let name = self.parse_ident();
         self.expect(&token::Colon);
-        let ty = self.parse_ty(true);
+        let ty = self.parse_ty_sum();
         spanned(lo, self.last_span.hi, ast::StructField_ {
             kind: NamedField(name, pr),
             id: ast::DUMMY_NODE_ID,
@@ -3624,7 +3607,7 @@ impl<'a> Parser<'a> {
 
             // Potential trouble: if we allow macros with paths instead of
             // idents, we'd need to look ahead past the whole path here...
-            let pth = self.parse_path(NoTypesAllowed).path;
+            let pth = self.parse_path(NoTypesAllowed);
             self.bump();
 
             let id = match self.token {
@@ -3976,7 +3959,7 @@ impl<'a> Parser<'a> {
 
         let default = if self.token == token::Eq {
             self.bump();
-            Some(self.parse_ty(true))
+            Some(self.parse_ty_sum())
         }
         else { None };
 
@@ -4032,7 +4015,7 @@ impl<'a> Parser<'a> {
             Some(token::Comma),
             |p| {
                 p.forbid_lifetime();
-                p.parse_ty(true)
+                p.parse_ty_sum()
             }
         );
         (lifetimes, result.into_vec())
@@ -4265,7 +4248,7 @@ impl<'a> Parser<'a> {
                     // Determine whether this is the fully explicit form, `self:
                     // TYPE`.
                     if self.eat(&token::Colon) {
-                        SelfExplicit(self.parse_ty(false), self_ident)
+                        SelfExplicit(self.parse_ty_sum(), self_ident)
                     } else {
                         SelfValue(self_ident)
                     }
@@ -4277,7 +4260,7 @@ impl<'a> Parser<'a> {
                     // Determine whether this is the fully explicit form,
                     // `self: TYPE`.
                     if self.eat(&token::Colon) {
-                        SelfExplicit(self.parse_ty(false), self_ident)
+                        SelfExplicit(self.parse_ty_sum(), self_ident)
                     } else {
                         SelfValue(self_ident)
                     }
@@ -4466,7 +4449,7 @@ impl<'a> Parser<'a> {
                 && (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren))
                     || self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) {
                 // method macro.
-                let pth = self.parse_path(NoTypesAllowed).path;
+                let pth = self.parse_path(NoTypesAllowed);
                 self.expect(&token::Not);
 
                 // eat a matched-delimiter token tree:
@@ -4564,30 +4547,25 @@ impl<'a> Parser<'a> {
         let could_be_trait = self.token != token::OpenDelim(token::Paren);
 
         // Parse the trait.
-        let mut ty = self.parse_ty(true);
+        let mut ty = self.parse_ty_sum();
 
         // Parse traits, if necessary.
         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 {
-                TyPath(ref path, None, node_id) => {
+                TyPath(ref path, node_id) => {
                     Some(TraitRef {
                         path: (*path).clone(),
                         ref_id: node_id,
                     })
                 }
-                TyPath(_, Some(_), _) => {
-                    self.span_err(ty.span,
-                                  "bounded traits are only valid in type position");
-                    None
-                }
                 _ => {
                     self.span_err(ty.span, "not a trait");
                     None
                 }
             };
 
-            ty = self.parse_ty(true);
+            ty = self.parse_ty_sum();
             opt_trait_ref
         } else {
             None
@@ -4606,7 +4584,7 @@ impl<'a> Parser<'a> {
     /// Parse a::B<String,int>
     fn parse_trait_ref(&mut self) -> TraitRef {
         ast::TraitRef {
-            path: self.parse_path(LifetimeAndTypesWithoutColons).path,
+            path: self.parse_path(LifetimeAndTypesWithoutColons),
             ref_id: ast::DUMMY_NODE_ID,
         }
     }
@@ -4638,7 +4616,7 @@ impl<'a> Parser<'a> {
         let mut generics = self.parse_generics();
 
         if self.eat(&token::Colon) {
-            let ty = self.parse_ty(true);
+            let ty = self.parse_ty_sum();
             self.span_err(ty.span, "`virtual` structs have been removed from the language");
         }
 
@@ -4673,7 +4651,7 @@ impl<'a> Parser<'a> {
                 let struct_field_ = ast::StructField_ {
                     kind: UnnamedField(p.parse_visibility()),
                     id: ast::DUMMY_NODE_ID,
-                    ty: p.parse_ty(true),
+                    ty: p.parse_ty_sum(),
                     attrs: attrs,
                 };
                 spanned(lo, p.span.hi, struct_field_)
@@ -4830,7 +4808,7 @@ impl<'a> Parser<'a> {
     fn parse_item_const(&mut self, m: Option<Mutability>) -> ItemInfo {
         let id = self.parse_ident();
         self.expect(&token::Colon);
-        let ty = self.parse_ty(true);
+        let ty = self.parse_ty_sum();
         self.expect(&token::Eq);
         let e = self.parse_expr();
         self.commit_expr_expecting(&*e, token::Semi);
@@ -5023,7 +5001,7 @@ impl<'a> Parser<'a> {
 
         let ident = self.parse_ident();
         self.expect(&token::Colon);
-        let ty = self.parse_ty(true);
+        let ty = self.parse_ty_sum();
         let hi = self.span.hi;
         self.expect(&token::Semi);
         P(ForeignItem {
@@ -5181,7 +5159,7 @@ impl<'a> Parser<'a> {
         let mut tps = self.parse_generics();
         self.parse_where_clause(&mut tps);
         self.expect(&token::Eq);
-        let ty = self.parse_ty(true);
+        let ty = self.parse_ty_sum();
         self.expect(&token::Semi);
         (ident, ItemTy(ty, tps), None)
     }
@@ -5235,7 +5213,7 @@ impl<'a> Parser<'a> {
                     &token::OpenDelim(token::Paren),
                     &token::CloseDelim(token::Paren),
                     seq_sep_trailing_allowed(token::Comma),
-                    |p| p.parse_ty(true)
+                    |p| p.parse_ty_sum()
                 );
                 for ty in arg_tys.into_iter() {
                     args.push(ast::VariantArg {
@@ -5593,7 +5571,7 @@ impl<'a> Parser<'a> {
             // MACRO INVOCATION ITEM
 
             // item macro.
-            let pth = self.parse_path(NoTypesAllowed).path;
+            let pth = self.parse_path(NoTypesAllowed);
             self.expect(&token::Not);
 
             // a 'special' identifier (like what `macro_rules!` uses)
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 6960337c3e2..ab78d5ecbfd 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -61,7 +61,7 @@ pub struct State<'a> {
     literals: Option<Vec<comments::Literal> >,
     cur_cmnt_and_lit: CurrentCommentAndLiteral,
     boxes: Vec<pp::Breaks>,
-    ann: &'a PpAnn+'a,
+    ann: &'a (PpAnn+'a),
     encode_idents_with_hygiene: bool,
 }
 
@@ -293,6 +293,10 @@ pub fn ty_to_string(ty: &ast::Ty) -> String {
     $to_string(|s| s.print_type(ty))
 }
 
+pub fn bounds_to_string(bounds: &[ast::TyParamBound]) -> String {
+    $to_string(|s| s.print_bounds("", bounds))
+}
+
 pub fn pat_to_string(pat: &ast::Pat) -> String {
     $to_string(|s| s.print_pat(pat))
 }
@@ -739,11 +743,15 @@ impl<'a> State<'a> {
                                       Some(&generics),
                                       None));
             }
-            ast::TyPath(ref path, ref bounds, _) => {
-                try!(self.print_bounded_path(path, bounds));
+            ast::TyPath(ref path, _) => {
+                try!(self.print_path(path, false));
+            }
+            ast::TyObjectSum(ref ty, ref bounds) => {
+                try!(self.print_type(&**ty));
+                try!(self.print_bounds("+", bounds.as_slice()));
             }
             ast::TyPolyTraitRef(ref bounds) => {
-                try!(self.print_bounds("", bounds));
+                try!(self.print_bounds("", bounds.as_slice()));
             }
             ast::TyQPath(ref qpath) => {
                 try!(word(&mut self.s, "<"));
@@ -970,7 +978,7 @@ impl<'a> State<'a> {
                     }
                     _ => {}
                 }
-                try!(self.print_bounds(":", bounds));
+                try!(self.print_bounds(":", bounds.as_slice()));
                 try!(self.print_where_clause(generics));
                 try!(word(&mut self.s, " "));
                 try!(self.bopen());
@@ -1908,11 +1916,11 @@ impl<'a> State<'a> {
         self.print_expr(coll)
     }
 
-    fn print_path_(&mut self,
-                   path: &ast::Path,
-                   colons_before_params: bool,
-                   opt_bounds: &Option<OwnedSlice<ast::TyParamBound>>)
-        -> IoResult<()> {
+    fn print_path(&mut self,
+                  path: &ast::Path,
+                  colons_before_params: bool)
+                  -> IoResult<()>
+    {
         try!(self.maybe_print_comment(path.span.lo));
         if path.global {
             try!(word(&mut self.s, "::"));
@@ -1931,10 +1939,7 @@ impl<'a> State<'a> {
             try!(self.print_path_parameters(&segment.parameters, colons_before_params));
         }
 
-        match *opt_bounds {
-            None => Ok(()),
-            Some(ref bounds) => self.print_bounds("+", bounds)
-        }
+        Ok(())
     }
 
     fn print_path_parameters(&mut self,
@@ -1997,17 +2002,6 @@ impl<'a> State<'a> {
         Ok(())
     }
 
-    fn print_path(&mut self, path: &ast::Path,
-                  colons_before_params: bool) -> IoResult<()> {
-        self.print_path_(path, colons_before_params, &None)
-    }
-
-    fn print_bounded_path(&mut self, path: &ast::Path,
-                          bounds: &Option<OwnedSlice<ast::TyParamBound>>)
-        -> IoResult<()> {
-        self.print_path_(path, false, bounds)
-    }
-
     pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> {
         try!(self.maybe_print_comment(pat.span.lo));
         try!(self.ann.pre(self, NodePat(pat)));
@@ -2329,7 +2323,7 @@ impl<'a> State<'a> {
 
     pub fn print_bounds(&mut self,
                         prefix: &str,
-                        bounds: &OwnedSlice<ast::TyParamBound>)
+                        bounds: &[ast::TyParamBound])
                         -> IoResult<()> {
         if !bounds.is_empty() {
             try!(word(&mut self.s, prefix));
@@ -2418,7 +2412,7 @@ impl<'a> State<'a> {
             _ => {}
         }
         try!(self.print_ident(param.ident));
-        try!(self.print_bounds(":", &param.bounds));
+        try!(self.print_bounds(":", param.bounds.as_slice()));
         match param.default {
             Some(ref default) => {
                 try!(space(&mut self.s));
@@ -2447,7 +2441,7 @@ impl<'a> State<'a> {
             }
 
             try!(self.print_ident(predicate.ident));
-            try!(self.print_bounds(":", &predicate.bounds));
+            try!(self.print_bounds(":", predicate.bounds.as_slice()));
         }
 
         Ok(())
@@ -2664,7 +2658,7 @@ impl<'a> State<'a> {
             try!(self.pclose());
         }
 
-        try!(self.print_bounds(":", bounds));
+        try!(self.print_bounds(":", bounds.as_slice()));
 
         try!(self.print_fn_output(decl));
 
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index f21a3185d6d..05828fc05f8 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -482,8 +482,7 @@ fn mk_tests(cx: &TestCtxt) -> P<ast::Item> {
     let ecx = &cx.ext_cx;
     let struct_type = ecx.ty_path(ecx.path(sp, vec![ecx.ident_of("self"),
                                                     ecx.ident_of("test"),
-                                                    ecx.ident_of("TestDescAndFn")]),
-                                  None);
+                                                    ecx.ident_of("TestDescAndFn")]));
     let static_lt = ecx.lifetime(sp, token::special_idents::static_lifetime.name);
     // &'static [self::test::TestDescAndFn]
     let static_type = ecx.ty_rptr(sp,
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 3f87dbc0740..95679bc6bf0 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -404,14 +404,12 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             walk_fn_ret_ty(visitor, &function_declaration.decl.output);
             walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
         }
-        TyPath(ref path, ref opt_bounds, id) => {
+        TyPath(ref path, id) => {
             visitor.visit_path(path, id);
-            match *opt_bounds {
-                Some(ref bounds) => {
-                    walk_ty_param_bounds_helper(visitor, bounds);
-                }
-                None => { }
-            }
+        }
+        TyObjectSum(ref ty, ref bounds) => {
+            visitor.visit_ty(&**ty);
+            walk_ty_param_bounds_helper(visitor, bounds);
         }
         TyQPath(ref qpath) => {
             visitor.visit_ty(&*qpath.self_type);
diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs
index 151a388a133..611c10ea71a 100644
--- a/src/libterm/lib.rs
+++ b/src/libterm/lib.rs
@@ -115,7 +115,7 @@ pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
 #[cfg(not(windows))]
 /// Return a Terminal wrapping stderr, or None if a terminal couldn't be
 /// opened.
-pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send> + Send> {
+pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> {
     TerminfoTerminal::new(WriterWrapper {
         wrapped: box std::io::stderr() as Box<Writer + Send>,
     })
diff --git a/src/test/compile-fail/dst-index.rs b/src/test/compile-fail/dst-index.rs
index 542562b69e6..f6511d68662 100644
--- a/src/test/compile-fail/dst-index.rs
+++ b/src/test/compile-fail/dst-index.rs
@@ -25,7 +25,7 @@ impl Index<uint, str> for S {
 struct T;
 
 impl Index<uint, Show + 'static> for T {
-    fn index<'a>(&'a self, idx: &uint) -> &'a Show + 'static {
+    fn index<'a>(&'a self, idx: &uint) -> &'a (Show + 'static) {
         static x: uint = 42;
         &x
     }
diff --git a/src/test/compile-fail/hrtb-precedence-of-plus-error-message.rs b/src/test/compile-fail/hrtb-precedence-of-plus-error-message.rs
new file mode 100644
index 00000000000..a0d81b831f6
--- /dev/null
+++ b/src/test/compile-fail/hrtb-precedence-of-plus-error-message.rs
@@ -0,0 +1,35 @@
+// 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.
+
+#![feature(unboxed_closures)]
+
+// Test that we suggest the correct parentheses
+
+trait Bar {
+    fn dummy(&self) { }
+}
+
+struct Foo<'a> {
+    a: &'a Bar+'a,
+        //~^ ERROR E0171
+        //~^^ NOTE perhaps you meant `&'a (Bar + 'a)`?
+
+    b: &'a mut Bar+'a,
+        //~^ ERROR E0171
+        //~^^ NOTE perhaps you meant `&'a mut (Bar + 'a)`?
+
+    c: Box<Bar+'a>, // OK, no paren needed in this context
+
+    d: fn() -> Bar+'a,
+        //~^ ERROR E0171
+        //~^^ NOTE perhaps you forgot parentheses
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/issue-12470.rs b/src/test/compile-fail/issue-12470.rs
index aa7e3cd3739..0202d538cf6 100644
--- a/src/test/compile-fail/issue-12470.rs
+++ b/src/test/compile-fail/issue-12470.rs
@@ -24,7 +24,7 @@ impl X for B {
 }
 
 struct A<'a> {
-    p: &'a X+'a
+    p: &'a (X+'a)
 }
 
 fn make_a<'a>(p: &'a X) -> A<'a> {
diff --git a/src/test/compile-fail/issue-14285.rs b/src/test/compile-fail/issue-14285.rs
index 624ddf0c8bb..cbf4412a81d 100644
--- a/src/test/compile-fail/issue-14285.rs
+++ b/src/test/compile-fail/issue-14285.rs
@@ -14,7 +14,7 @@ struct A;
 
 impl Foo for A {}
 
-struct B<'a>(&'a Foo+'a);
+struct B<'a>(&'a (Foo+'a));
 
 fn foo<'a>(a: &Foo) -> B<'a> {
     B(a)    //~ ERROR cannot infer an appropriate lifetime
diff --git a/src/test/compile-fail/kindck-copy.rs b/src/test/compile-fail/kindck-copy.rs
index 499144698fb..202529c30b3 100644
--- a/src/test/compile-fail/kindck-copy.rs
+++ b/src/test/compile-fail/kindck-copy.rs
@@ -44,15 +44,15 @@ fn test<'a,T,U:Copy>(_: &'a int) {
 
     // borrowed object types are generally ok
     assert_copy::<&'a Dummy>();
-    assert_copy::<&'a Dummy+Copy>();
-    assert_copy::<&'static Dummy+Copy>();
+    assert_copy::<&'a (Dummy+Copy)>();
+    assert_copy::<&'static (Dummy+Copy)>();
 
     // owned object types are not ok
     assert_copy::<Box<Dummy>>(); //~ ERROR `core::kinds::Copy` is not implemented
     assert_copy::<Box<Dummy+Copy>>(); //~ ERROR `core::kinds::Copy` is not implemented
 
     // mutable object types are not ok
-    assert_copy::<&'a mut Dummy+Copy>();  //~ ERROR `core::kinds::Copy` is not implemented
+    assert_copy::<&'a mut (Dummy+Copy)>();  //~ ERROR `core::kinds::Copy` is not implemented
 
     // closures are like an `&mut` object
     assert_copy::<||>(); //~ ERROR `core::kinds::Copy` is not implemented
diff --git a/src/test/compile-fail/kindck-send-object.rs b/src/test/compile-fail/kindck-send-object.rs
index 9217d05002d..4fbb3eab8c4 100644
--- a/src/test/compile-fail/kindck-send-object.rs
+++ b/src/test/compile-fail/kindck-send-object.rs
@@ -19,7 +19,7 @@ trait Message : Send { }
 // careful with object types, who knows what they close over...
 
 fn object_ref_with_static_bound_not_ok() {
-    assert_send::<&'static Dummy+'static>();
+    assert_send::<&'static (Dummy+'static)>();
     //~^ ERROR the trait `core::kinds::Send` is not implemented
 }
 
@@ -36,7 +36,7 @@ fn closure_with_no_bound_not_ok<'a>() {
 }
 
 fn object_with_send_bound_ok() {
-    assert_send::<&'static Dummy+Send>();
+    assert_send::<&'static (Dummy+Send)>();
     assert_send::<Box<Dummy+Send>>();
     assert_send::<proc():Send>;
     assert_send::<||:Send>;
diff --git a/src/test/compile-fail/kindck-send-object1.rs b/src/test/compile-fail/kindck-send-object1.rs
index ff8daa045c6..a5519753643 100644
--- a/src/test/compile-fail/kindck-send-object1.rs
+++ b/src/test/compile-fail/kindck-send-object1.rs
@@ -21,13 +21,13 @@ fn test51<'a>() {
     //~^ ERROR the trait `core::kinds::Send` is not implemented
 }
 fn test52<'a>() {
-    assert_send::<&'a Dummy+Send>();
+    assert_send::<&'a (Dummy+Send)>();
     //~^ ERROR does not fulfill the required lifetime
 }
 
 // ...unless they are properly bounded
 fn test60() {
-    assert_send::<&'static Dummy+Send>();
+    assert_send::<&'static (Dummy+Send)>();
 }
 fn test61() {
     assert_send::<Box<Dummy+Send>>();
diff --git a/src/test/compile-fail/kindck-send-object2.rs b/src/test/compile-fail/kindck-send-object2.rs
index d46c6e68c05..ea8c2628306 100644
--- a/src/test/compile-fail/kindck-send-object2.rs
+++ b/src/test/compile-fail/kindck-send-object2.rs
@@ -23,7 +23,7 @@ fn test53() {
 
 // ...unless they are properly bounded
 fn test60() {
-    assert_send::<&'static Dummy+Send>();
+    assert_send::<&'static (Dummy+Send)>();
 }
 fn test61() {
     assert_send::<Box<Dummy+Send>>();
diff --git a/src/test/compile-fail/region-object-lifetime-1.rs b/src/test/compile-fail/region-object-lifetime-1.rs
index 01daeb628ef..4758ce71fff 100644
--- a/src/test/compile-fail/region-object-lifetime-1.rs
+++ b/src/test/compile-fail/region-object-lifetime-1.rs
@@ -28,14 +28,14 @@ fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () {
 
 // Borrowed receiver with two distinct lifetimes, but we know that
 // 'b:'a, hence &'a () is permitted.
-fn borrowed_receiver_related_lifetimes<'a,'b>(x: &'a Foo+'b) -> &'a () {
+fn borrowed_receiver_related_lifetimes<'a,'b>(x: &'a (Foo+'b)) -> &'a () {
     x.borrowed()
 }
 
 // Here we have two distinct lifetimes, but we try to return a pointer
 // with the longer lifetime when (from the signature) we only know
 // that it lives as long as the shorter lifetime. Therefore, error.
-fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a Foo+'b) -> &'b () {
+fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (Foo+'b)) -> &'b () {
     x.borrowed() //~ ERROR cannot infer
 }
 
diff --git a/src/test/compile-fail/regions-bounded-by-send.rs b/src/test/compile-fail/regions-bounded-by-send.rs
index 182b40ceaae..660a9be4f63 100644
--- a/src/test/compile-fail/regions-bounded-by-send.rs
+++ b/src/test/compile-fail/regions-bounded-by-send.rs
@@ -57,12 +57,12 @@ fn box_with_region_not_ok<'a>() {
 // objects with insufficient bounds no ok
 
 fn object_with_random_bound_not_ok<'a>() {
-    assert_send::<&'a Dummy+'a>();
+    assert_send::<&'a (Dummy+'a)>();
     //~^ ERROR not implemented
 }
 
 fn object_with_send_bound_not_ok<'a>() {
-    assert_send::<&'a Dummy+Send>();
+    assert_send::<&'a (Dummy+Send)>();
     //~^ ERROR does not fulfill
 }
 
diff --git a/src/test/compile-fail/regions-close-object-into-object.rs b/src/test/compile-fail/regions-close-object-into-object.rs
index 835c55c9bd1..48945868bd3 100644
--- a/src/test/compile-fail/regions-close-object-into-object.rs
+++ b/src/test/compile-fail/regions-close-object-into-object.rs
@@ -10,7 +10,7 @@
 
 
 trait A<T> {}
-struct B<'a, T>(&'a A<T>+'a);
+struct B<'a, T>(&'a (A<T>+'a));
 
 trait X {}
 impl<'a, T> X for B<'a, T> {}
diff --git a/src/test/compile-fail/regions-trait-variance.rs b/src/test/compile-fail/regions-trait-variance.rs
index 3ceb4e3fef6..4e31a41c4e0 100644
--- a/src/test/compile-fail/regions-trait-variance.rs
+++ b/src/test/compile-fail/regions-trait-variance.rs
@@ -31,7 +31,7 @@ impl Drop for B {
 }
 
 struct A<'r> {
-    p: &'r X+'r
+    p: &'r (X+'r)
 }
 
 fn make_a(p:&X) -> A {
diff --git a/src/test/compile-fail/trait-bounds-not-on-impl.rs b/src/test/compile-fail/trait-bounds-not-on-impl.rs
index 38c78144601..a034352c4a6 100644
--- a/src/test/compile-fail/trait-bounds-not-on-impl.rs
+++ b/src/test/compile-fail/trait-bounds-not-on-impl.rs
@@ -13,7 +13,7 @@ trait Foo {
 
 struct Bar;
 
-impl Foo + Owned for Bar { //~ ERROR bounded traits are only valid in type position
+impl Foo + Owned for Bar { //~ ERROR not a trait
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/trait-bounds-not-on-struct.rs b/src/test/compile-fail/trait-bounds-not-on-struct.rs
index 0a5909ff2ef..081efa429c3 100644
--- a/src/test/compile-fail/trait-bounds-not-on-struct.rs
+++ b/src/test/compile-fail/trait-bounds-not-on-struct.rs
@@ -11,6 +11,6 @@
 
 struct Foo;
 
-fn foo(_x: Box<Foo + Send>) { } //~ ERROR kind bounds can only be used on trait types
+fn foo(_x: Box<Foo + Send>) { } //~ ERROR expected a reference to a trait
 
 fn main() { }
diff --git a/src/test/compile-fail/trait-bounds-sugar.rs b/src/test/compile-fail/trait-bounds-sugar.rs
index 7ed8db4fcd2..4da496621d1 100644
--- a/src/test/compile-fail/trait-bounds-sugar.rs
+++ b/src/test/compile-fail/trait-bounds-sugar.rs
@@ -16,14 +16,14 @@ trait Foo {}
 fn a(_x: Box<Foo+Send>) {
 }
 
-fn b(_x: &'static Foo+'static) {
+fn b(_x: &'static (Foo+'static)) {
 }
 
 fn c(x: Box<Foo+Sync>) {
     a(x); //~ ERROR mismatched types
 }
 
-fn d(x: &'static Foo+Sync) {
+fn d(x: &'static (Foo+Sync)) {
     b(x); //~ ERROR cannot infer
     //~^ ERROR mismatched types
 }
diff --git a/src/test/run-pass/colorful-write-macros.rs b/src/test/run-pass/colorful-write-macros.rs
index 75b8e391331..bbb049eb960 100644
--- a/src/test/run-pass/colorful-write-macros.rs
+++ b/src/test/run-pass/colorful-write-macros.rs
@@ -18,7 +18,7 @@ use std::fmt;
 use std::fmt::FormatWriter;
 
 struct Foo<'a> {
-    writer: &'a mut Writer+'a,
+    writer: &'a mut (Writer+'a),
     other: &'a str,
 }
 
diff --git a/src/test/run-pass/dst-index.rs b/src/test/run-pass/dst-index.rs
index 266f9bcba5f..eaf7131e1d8 100644
--- a/src/test/run-pass/dst-index.rs
+++ b/src/test/run-pass/dst-index.rs
@@ -25,7 +25,7 @@ impl Index<uint, str> for S {
 struct T;
 
 impl Index<uint, Show + 'static> for T {
-    fn index<'a>(&'a self, idx: &uint) -> &'a Show + 'static {
+    fn index<'a>(&'a self, idx: &uint) -> &'a (Show + 'static) {
         static x: uint = 42;
         &x
     }
diff --git a/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs b/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs
new file mode 100644
index 00000000000..86ce49f56cb
--- /dev/null
+++ b/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs
@@ -0,0 +1,27 @@
+// 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.
+
+#![feature(unboxed_closures)]
+
+// Test that `F : Fn(int) -> int + Send` is interpreted as two
+// distinct bounds on `F`.
+
+fn foo<F>(f: F)
+    where F : FnOnce(int) -> int + Send
+{
+    bar(f);
+    baz(f);
+}
+
+fn bar<F:Send>(f: F) { }
+
+fn baz<F:FnOnce(int) -> int>(f: F) { }
+
+fn main() {}
diff --git a/src/test/run-pass/hrtb-precedence-of-plus.rs b/src/test/run-pass/hrtb-precedence-of-plus.rs
new file mode 100644
index 00000000000..9a43b5b711e
--- /dev/null
+++ b/src/test/run-pass/hrtb-precedence-of-plus.rs
@@ -0,0 +1,21 @@
+// 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.
+
+#![feature(unboxed_closures)]
+
+// Test that `Fn(int) -> int + 'static` parses as `(Fn(int) -> int) +
+// 'static` and not `Fn(int) -> (int + 'static)`. The latter would
+// cause a compilation error. Issue #18772.
+
+fn adder(y: int) -> Box<Fn(int) -> int + 'static> {
+    box move |&: x| y + x
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-10902.rs b/src/test/run-pass/issue-10902.rs
index 84d71e1ef5d..324a1701b2f 100644
--- a/src/test/run-pass/issue-10902.rs
+++ b/src/test/run-pass/issue-10902.rs
@@ -10,7 +10,7 @@
 
 pub mod two_tuple {
     pub trait T {}
-    pub struct P<'a>(&'a T + 'a, &'a T + 'a);
+    pub struct P<'a>(&'a (T + 'a), &'a (T + 'a));
     pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> {
         P(car, cdr)
     }
@@ -18,7 +18,7 @@ pub mod two_tuple {
 
 pub mod two_fields {
     pub trait T {}
-    pub struct P<'a> { car: &'a T + 'a, cdr: &'a T + 'a }
+    pub struct P<'a> { car: &'a (T + 'a), cdr: &'a (T + 'a) }
     pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> {
         P{ car: car, cdr: cdr }
     }
diff --git a/src/test/run-pass/issue-11205.rs b/src/test/run-pass/issue-11205.rs
index 89224e1fb12..ea138311f19 100644
--- a/src/test/run-pass/issue-11205.rs
+++ b/src/test/run-pass/issue-11205.rs
@@ -49,7 +49,7 @@ fn main() {
     foog(x, &[box 1i]);
 
     struct T<'a> {
-        t: [&'a Foo+'a, ..2]
+        t: [&'a (Foo+'a), ..2]
     }
     let _n = T {
         t: [&1i, &2i]
@@ -64,7 +64,7 @@ fn main() {
     };
 
     struct F<'b> {
-        t: &'b [&'b Foo+'b]
+        t: &'b [&'b (Foo+'b)]
     }
     let _n = F {
         t: &[&1i, &2i]
diff --git a/src/test/run-pass/issue-14901.rs b/src/test/run-pass/issue-14901.rs
index 647bbfbd65d..e41754fd1b9 100644
--- a/src/test/run-pass/issue-14901.rs
+++ b/src/test/run-pass/issue-14901.rs
@@ -11,7 +11,7 @@
 use std::io::Reader;
 
 enum Wrapper<'a> {
-    WrapReader(&'a Reader + 'a)
+    WrapReader(&'a (Reader + 'a))
 }
 
 trait Wrap<'a> {
diff --git a/src/test/run-pass/issue-14958.rs b/src/test/run-pass/issue-14958.rs
index 7f3321e0b3e..1ffd349a653 100644
--- a/src/test/run-pass/issue-14958.rs
+++ b/src/test/run-pass/issue-14958.rs
@@ -14,7 +14,7 @@ trait Foo {}
 
 struct Bar;
 
-impl<'a> std::ops::Fn<(&'a Foo+'a,), ()> for Bar {
+impl<'a> std::ops::Fn<(&'a (Foo+'a),), ()> for Bar {
     extern "rust-call" fn call(&self, _: (&'a Foo,)) {}
 }
 
diff --git a/src/test/run-pass/issue-14959.rs b/src/test/run-pass/issue-14959.rs
index 6cc5ab4d6cb..99472bb3610 100644
--- a/src/test/run-pass/issue-14959.rs
+++ b/src/test/run-pass/issue-14959.rs
@@ -33,8 +33,8 @@ impl Alloy {
     }
 }
 
-impl<'a, 'b> Fn<(&'b mut Response+'b,),()> for SendFile<'a> {
-    extern "rust-call" fn call(&self, (_res,): (&'b mut Response+'b,)) {}
+impl<'a, 'b> Fn<(&'b mut (Response+'b),),()> for SendFile<'a> {
+    extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {}
 }
 
 impl<Rq: Request, Rs: Response> Ingot<Rq, Rs> for HelloWorld {
diff --git a/src/test/run-pass/issue-5708.rs b/src/test/run-pass/issue-5708.rs
index 9c728005b6f..61ae273aef5 100644
--- a/src/test/run-pass/issue-5708.rs
+++ b/src/test/run-pass/issue-5708.rs
@@ -29,7 +29,7 @@ impl Inner for int {
 }
 
 struct Outer<'a> {
-    inner: &'a Inner+'a
+    inner: &'a (Inner+'a)
 }
 
 impl<'a> Outer<'a> {
@@ -51,7 +51,7 @@ pub fn main() {
 pub trait MyTrait<T> { }
 
 pub struct MyContainer<'a, T> {
-    foos: Vec<&'a MyTrait<T>+'a> ,
+    foos: Vec<&'a (MyTrait<T>+'a)> ,
 }
 
 impl<'a, T> MyContainer<'a, T> {
diff --git a/src/test/run-pass/issue-8249.rs b/src/test/run-pass/issue-8249.rs
index dae5db11b0a..44f07def531 100644
--- a/src/test/run-pass/issue-8249.rs
+++ b/src/test/run-pass/issue-8249.rs
@@ -13,7 +13,7 @@ struct B;
 impl A for B {}
 
 struct C<'a> {
-    foo: &'a mut A+'a,
+    foo: &'a mut (A+'a),
 }
 
 fn foo(a: &mut A) {
diff --git a/src/test/run-pass/issue-9719.rs b/src/test/run-pass/issue-9719.rs
index ebb9b20ec25..4c6b9a3aaa0 100644
--- a/src/test/run-pass/issue-9719.rs
+++ b/src/test/run-pass/issue-9719.rs
@@ -16,7 +16,7 @@ mod a {
     pub trait X {}
     impl X for int {}
 
-    pub struct Z<'a>(Enum<&'a X+'a>);
+    pub struct Z<'a>(Enum<&'a (X+'a)>);
     fn foo() { let x = 42i; let z = Z(Enum::A(&x as &X)); let _ = z; }
 }
 
@@ -24,7 +24,7 @@ mod b {
     trait X {}
     impl X for int {}
     struct Y<'a>{
-        x:Option<&'a X+'a>,
+        x:Option<&'a (X+'a)>,
     }
 
     fn bar() {
@@ -36,7 +36,7 @@ mod b {
 mod c {
     pub trait X { fn f(&self); }
     impl X for int { fn f(&self) {} }
-    pub struct Z<'a>(Option<&'a X+'a>);
+    pub struct Z<'a>(Option<&'a (X+'a)>);
     fn main() { let x = 42i; let z = Z(Some(&x as &X)); let _ = z; }
 }
 
diff --git a/src/test/run-pass/parameterized-trait-with-bounds.rs b/src/test/run-pass/parameterized-trait-with-bounds.rs
index 339c9e3c490..840e58848a7 100644
--- a/src/test/run-pass/parameterized-trait-with-bounds.rs
+++ b/src/test/run-pass/parameterized-trait-with-bounds.rs
@@ -19,7 +19,7 @@ mod foo {
     pub trait D<'a, T> {}
 }
 
-fn foo1<T>(_: &A<T> + Send) {}
+fn foo1<T>(_: &(A<T> + Send)) {}
 fn foo2<T>(_: Box<A<T> + Send + Sync>) {}
 fn foo3<T>(_: Box<B<int, uint> + 'static>) {}
 fn foo4<'a, T>(_: Box<C<'a, T> + 'static + Send>) {}
diff --git a/src/test/run-pass/regions-early-bound-trait-param.rs b/src/test/run-pass/regions-early-bound-trait-param.rs
index faf371e8826..907f610ff25 100644
--- a/src/test/run-pass/regions-early-bound-trait-param.rs
+++ b/src/test/run-pass/regions-early-bound-trait-param.rs
@@ -30,7 +30,7 @@ fn object_invoke1<'d>(x: &'d Trait<'d>) -> (int, int) {
 }
 
 struct Struct1<'e> {
-    f: &'e Trait<'e>+'e
+    f: &'e (Trait<'e>+'e)
 }
 
 fn field_invoke1<'f, 'g>(x: &'g Struct1<'f>) -> (int,int) {
@@ -40,7 +40,7 @@ fn field_invoke1<'f, 'g>(x: &'g Struct1<'f>) -> (int,int) {
 }
 
 struct Struct2<'h, 'i> {
-    f: &'h Trait<'i>+'h
+    f: &'h (Trait<'i>+'h)
 }
 
 fn object_invoke2<'j, 'k>(x: &'k Trait<'j>) -> int {