diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs b/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs
index f6260527039d0..0694bbab66f18 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs
+++ b/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs
@@ -88,7 +88,7 @@ pub trait MirWithFlowState<'tcx> {
 }
 
 impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
-    where 'a, 'tcx: 'a, BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>
+    where 'tcx: 'a, BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>
 {
     type BD = BD;
     fn node_id(&self) -> NodeId { self.node_id }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 61268d457ce44..09d6b12ed4c38 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1091,14 +1091,12 @@ impl<'a> Parser<'a> {
             let poly_trait_ref = ast::PolyTraitRef { bound_lifetimes: lifetime_defs,
                                                      trait_ref: trait_ref,
                                                      span: mk_sp(lo, hi)};
-            let other_bounds = if self.eat(&token::BinOp(token::Plus)) {
-                self.parse_ty_param_bounds(BoundParsingMode::Bare)?
-            } else {
-                P::new()
-            };
+
+            let other_bounds = self.parse_opt_ty_param_bounds(&token::BinOp(token::Plus),
+                                                              BoundParsingMode::Bare)?;
             let all_bounds =
                 Some(TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)).into_iter()
-                .chain(other_bounds.into_vec())
+                .chain(other_bounds.unwrap_or_else(P::new).into_vec())
                 .collect();
             Ok(ast::TyKind::PolyTraitRef(all_bounds))
         }
@@ -1319,24 +1317,15 @@ impl<'a> Parser<'a> {
         let lo = self.span.lo;
         let lhs = self.parse_ty()?;
 
-        if !self.eat(&token::BinOp(token::Plus)) {
-            return Ok(lhs);
-        }
-
-        let bounds = self.parse_ty_param_bounds(BoundParsingMode::Bare)?;
-
-        // In type grammar, `+` is treated like a binary operator,
-        // and hence both L and R side are required.
-        if bounds.is_empty() {
-            let prev_span = self.prev_span;
-            self.span_err(prev_span,
-                          "at least one type parameter bound \
-                          must be specified");
+        match self.parse_opt_ty_param_bounds(&token::BinOp(token::Plus),
+                                             BoundParsingMode::Bare)? {
+            None => Ok(lhs),
+            Some(bounds) => {
+                let sp = mk_sp(lo, self.prev_span.hi);
+                let sum = ast::TyKind::ObjectSum(lhs, bounds);
+                Ok(P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp}))
+            }
         }
-
-        let sp = mk_sp(lo, self.prev_span.hi);
-        let sum = ast::TyKind::ObjectSum(lhs, bounds);
-        Ok(P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp}))
     }
 
     /// Parse a type.
@@ -4186,11 +4175,25 @@ impl<'a> Parser<'a> {
                                         mode: BoundParsingMode)
                                         -> PResult<'a, TyParamBounds>
     {
-        if !self.eat(&token::Colon) {
-            Ok(P::new())
-        } else {
-            self.parse_ty_param_bounds(mode)
+        Ok(self.parse_opt_ty_param_bounds(&token::Colon, mode)?.unwrap_or_else(P::new))
+    }
+
+    fn parse_opt_ty_param_bounds(&mut self,
+                                 intoducing_token: &token::Token,
+                                 mode: BoundParsingMode)
+                                 -> PResult<'a, Option<TyParamBounds>> {
+        if !self.eat(intoducing_token) {
+            return Ok(None);
         }
+
+        let bounds = self.parse_ty_param_bounds(mode)?;
+
+        if bounds.is_empty() {
+            self.span_err(self.prev_span,
+                          "at least one type parameter bound must be specified");
+        }
+
+        Ok(Some(bounds))
     }
 
     // matches bounds    = ( boundseq )?
@@ -4440,7 +4443,7 @@ impl<'a> Parser<'a> {
                     let bounded_lifetime =
                         self.parse_lifetime()?;
 
-                    self.eat(&token::Colon);
+                    self.expect(&token::Colon)?;
 
                     let bounds =
                         self.parse_lifetimes(token::BinOp(token::Plus))?;
@@ -4448,6 +4451,12 @@ impl<'a> Parser<'a> {
                     let hi = self.prev_span.hi;
                     let span = mk_sp(lo, hi);
 
+                    if bounds.is_empty() {
+                        self.span_err(span,
+                                      "each predicate in a `where` clause must have \
+                                       at least one bound in it");
+                    }
+
                     where_clause.predicates.push(ast::WherePredicate::RegionPredicate(
                         ast::WhereRegionPredicate {
                             span: span,
@@ -4472,46 +4481,40 @@ impl<'a> Parser<'a> {
 
                     let bounded_ty = self.parse_ty()?;
 
-                    if self.eat(&token::Colon) {
-                        let bounds = self.parse_ty_param_bounds(BoundParsingMode::Bare)?;
-                        let hi = self.prev_span.hi;
-                        let span = mk_sp(lo, hi);
-
-                        if bounds.is_empty() {
-                            self.span_err(span,
-                                          "each predicate in a `where` clause must have \
-                                           at least one bound in it");
-                        }
+                    if let Some(bounds) = self.parse_opt_ty_param_bounds(&token::Colon,
+                                                                         BoundParsingMode::Bare)? {
 
                         where_clause.predicates.push(ast::WherePredicate::BoundPredicate(
                                 ast::WhereBoundPredicate {
-                                    span: span,
+                                    span: mk_sp(lo, self.prev_span.hi),
                                     bound_lifetimes: bound_lifetimes,
                                     bounded_ty: bounded_ty,
                                     bounds: bounds,
                         }));
 
                         parsed_something = true;
-                    } else if self.eat(&token::Eq) {
-                        // let ty = try!(self.parse_ty());
-                        let hi = self.prev_span.hi;
-                        let span = mk_sp(lo, hi);
-                        // where_clause.predicates.push(
-                        //     ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
-                        //         id: ast::DUMMY_NODE_ID,
-                        //         span: span,
-                        //         path: panic!("NYI"), //bounded_ty,
-                        //         ty: ty,
-                        // }));
-                        // parsed_something = true;
-                        // // FIXME(#18433)
-                        self.span_err(span,
-                                     "equality constraints are not yet supported \
-                                     in where clauses (#20041)");
                     } else {
-                        let prev_span = self.prev_span;
-                        self.span_err(prev_span,
-                              "unexpected token in `where` clause");
+                        if self.eat(&token::Eq) {
+                            // let ty = try!(self.parse_ty());
+                            let hi = self.prev_span.hi;
+                            let span = mk_sp(lo, hi);
+                            // where_clause.predicates.push(
+                            //     ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
+                            //         id: ast::DUMMY_NODE_ID,
+                            //         span: span,
+                            //         path: panic!("NYI"), //bounded_ty,
+                            //         ty: ty,
+                            // }));
+                            // parsed_something = true;
+                            // // FIXME(#18433)
+                            self.span_err(span,
+                                          "equality constraints are not yet supported \
+                                          in where clauses (#20041)");
+                        } else {
+                            let prev_span = self.prev_span;
+                            self.span_err(prev_span,
+                                          "unexpected token in `where` clause");
+                        }
                     }
                 }
             };
diff --git a/src/test/parse-fail/empty-type-parameter-bounds.rs b/src/test/parse-fail/empty-type-parameter-bounds.rs
new file mode 100644
index 0000000000000..d7bf840c80c6e
--- /dev/null
+++ b/src/test/parse-fail/empty-type-parameter-bounds.rs
@@ -0,0 +1,22 @@
+// Copyright 2016 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.
+
+// compile-flags: -Z parse-only -Z continue-parse-after-error
+
+trait T {}
+
+type S = for<'a> T+;
+//~^ ERROR at least one type parameter bound must be specified
+
+fn foo<T:>(x: T) -> T { x }
+//~^ ERROR at least one type parameter bound must be specified
+
+fn main() {
+}
diff --git a/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs b/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs
index 3ac71176342ba..5ff8335126190 100644
--- a/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs
+++ b/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z parse-only
+// compile-flags: -Z parse-only -Z continue-parse-after-error
 
 fn equal1<T>(_: &T, _: &T) -> bool where {
 //~^ ERROR a `where` clause must have at least one predicate in it
@@ -16,9 +16,15 @@ fn equal1<T>(_: &T, _: &T) -> bool where {
 }
 
 fn equal2<T>(_: &T, _: &T) -> bool where T: {
-//~^ ERROR each predicate in a `where` clause must have at least one bound
+//~^ ERROR at least one type parameter bound must be specified
     true
 }
 
+fn foo2<'a>() where 'a: {}
+//~^ ERROR each predicate in a `where` clause must have at least one bound
+
+fn foo1<'a>() where 'a {}
+//~^ ERROR expected `:`, found `{`
+
 fn main() {
 }