Add a parser for parsing types without the + character

This allows us to correctly parse types in more situations. For example,
`&T` should not allow `+` characters in `T` without brackets, as `&`
binds more tightly than the `+` operator, which is now correctly
handled.

I don't believe that I correctly ignore `+` in all required places in
ty.rs yet, but it's a first step. This set of changes allows us to pass
all of our current parsing tests.

In addition, this allows us to fix our parsing of `as T` expressions in
the next patch.
diff --git a/src/ty.rs b/src/ty.rs
index e767852..1f9717e 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -324,40 +324,52 @@
     use synom::tokens::*;
 
     impl Synom for Ty {
-        named!(parse -> Self, alt!(
-            // must be before mac
-            syn!(TyParen) => { Ty::Paren }
-            |
-            // must be before path
-            syn!(Mac) => { Ty::Mac }
-            |
-            // must be before ty_poly_trait_ref
-            ty_path
-            |
-            syn!(TySlice) => { Ty::Slice }
-            |
-            syn!(TyArray) => { Ty::Array }
-            |
-            syn!(TyPtr) => { Ty::Ptr }
-            |
-            syn!(TyRptr) => { Ty::Rptr }
-            |
-            syn!(TyBareFn) => { Ty::BareFn }
-            |
-            syn!(TyNever) => { Ty::Never }
-            |
-            syn!(TyTup) => { Ty::Tup }
-            |
-            ty_poly_trait_ref
-            |
-            syn!(TyImplTrait) => { Ty::ImplTrait }
-        ));
+        named!(parse -> Self, call!(ambig_ty, true));
 
         fn description() -> Option<&'static str> {
             Some("type")
         }
     }
 
+    impl Ty {
+        /// In some positions, types may not contain the `+` character, to
+        /// disambiguate them. For example in the expression `1 as T`, T may not
+        /// contain a `+` character.
+        ///
+        /// This parser does not allow a `+`, while the default parser does.
+        named!(without_plus -> Self, call!(ambig_ty, false));
+    }
+
+    named!(ambig_ty(allow_plus: bool) -> Ty, alt!(
+        // must be before mac
+        syn!(TyParen) => { Ty::Paren }
+        |
+        // must be before path
+        syn!(Mac) => { Ty::Mac }
+        |
+        // must be before ty_poly_trait_ref
+        call!(ty_path, allow_plus)
+        |
+        syn!(TySlice) => { Ty::Slice }
+        |
+        syn!(TyArray) => { Ty::Array }
+        |
+        syn!(TyPtr) => { Ty::Ptr }
+        |
+        syn!(TyRptr) => { Ty::Rptr }
+        |
+        syn!(TyBareFn) => { Ty::BareFn }
+        |
+        syn!(TyNever) => { Ty::Never }
+        |
+        syn!(TyTup) => { Ty::Tup }
+        |
+        // Don't try parsing poly_trait_ref if we aren't allowing it
+        call!(ty_poly_trait_ref, allow_plus)
+        |
+        syn!(TyImplTrait) => { Ty::ImplTrait }
+    ));
+
     impl Synom for TySlice {
         named!(parse -> Self, map!(
             brackets!(syn!(Ty)),
@@ -405,7 +417,7 @@
                 |
                 syn!(Mut) => { |m| (Mutability::Mutable(m), None) }
             ) >>
-            target: syn!(Ty) >>
+            target: call!(Ty::without_plus) >>
             (TyPtr {
                 const_token: mutability.1,
                 star_token: star,
@@ -422,7 +434,8 @@
             amp: syn!(And) >>
             life: option!(syn!(Lifetime)) >>
             mutability: syn!(Mutability) >>
-            target: syn!(Ty) >>
+            // & binds tighter than +, so we don't allow + here.
+            target: call!(Ty::without_plus) >>
             (TyRptr {
                 lifetime: life,
                 ty: Box::new(MutTy {
@@ -480,13 +493,21 @@
         ));
     }
 
-    named!(ty_path -> Ty, do_parse!(
+    named!(ty_path(allow_plus: bool) -> Ty, do_parse!(
         qpath: qpath >>
         parenthesized: cond!(
             qpath.1.segments.get(qpath.1.segments.len() - 1).item().parameters.is_empty(),
             option!(syn!(ParenthesizedParameterData))
         ) >>
-        bounds: many0!(tuple!(syn!(Add), syn!(TyParamBound))) >>
+        // Only allow parsing additional bounds if allow_plus is true.
+        bounds: alt!(
+            cond_reduce!(
+                allow_plus,
+                many0!(tuple!(syn!(Add), syn!(TyParamBound)))
+            )
+            |
+            value!(vec![])
+        ) >>
         ({
             let (qself, mut path) = qpath;
             if let Some(Some(parenthesized)) = parenthesized {
@@ -583,14 +604,22 @@
         ));
     }
 
-    named!(ty_poly_trait_ref -> Ty, map!(
-        call!(Delimited::parse_separated_nonempty),
-        |x| TyTraitObject { bounds: x }.into()
+    // Only allow multiple trait references if allow_plus is true.
+    named!(ty_poly_trait_ref(allow_plus: bool) -> Ty, alt!(
+        cond_reduce!(allow_plus, call!(Delimited::parse_separated_nonempty)) => {
+            |x| TyTraitObject { bounds: x }.into()
+        }
+        |
+        syn!(TyParamBound) => {
+            |x| TyTraitObject { bounds: vec![x].into() }.into()
+        }
     ));
 
     impl Synom for TyImplTrait {
         named!(parse -> Self, do_parse!(
             impl_: syn!(Impl) >>
+            // NOTE: rust-lang/rust#34511 includes discussion about whether or
+            // not + should be allowed in ImplTrait directly without ().
             elem: call!(Delimited::parse_separated_nonempty) >>
             (TyImplTrait {
                 impl_token: impl_,