]> git.lizzy.rs Git - rust.git/commitdiff
parser: split into {ty, path}.rs
authorMazdak Farrokhzad <twingoow@gmail.com>
Sun, 11 Aug 2019 17:59:27 +0000 (19:59 +0200)
committerMazdak Farrokhzad <twingoow@gmail.com>
Sun, 11 Aug 2019 17:59:27 +0000 (19:59 +0200)
src/libsyntax/parse/parser.rs
src/libsyntax/parse/parser/path.rs [new file with mode: 0644]
src/libsyntax/parse/parser/ty.rs [new file with mode: 0644]

index 6537f59395f4ea640f9a654a5aaf4d2715e3e99f..490abc8edd0b74a0dc6cd70a3a4c253b2eda2cb0 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-tidy-filelength
-
 mod expr;
 use expr::LhsExpr;
 mod pat;
@@ -7,20 +5,21 @@
 pub use item::AliasKind;
 mod module;
 pub use module::{ModulePath, ModulePathSuccess};
+mod ty;
+mod path;
+pub use path::PathStyle;
 
-use crate::ast::{self, AngleBracketedArgs, ParenthesizedArgs, AttrStyle, BareFnTy};
-use crate::ast::{AnonConst, Arg, Attribute, BindingMode};
+use crate::ast::{self, AttrStyle};
+use crate::ast::{Arg, Attribute, BindingMode};
 use crate::ast::{Block, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind};
-use crate::ast::{FnDecl, FunctionRetTy};
+use crate::ast::{FnDecl};
 use crate::ast::{Ident, IsAsync, Local, Lifetime};
 use crate::ast::{MacStmtStyle, Mac_, MacDelimiter};
-use crate::ast::{MutTy, Mutability};
-use crate::ast::{PolyTraitRef, QSelf, PathSegment};
+use crate::ast::{Mutability};
 use crate::ast::StrStyle;
 use crate::ast::SelfKind;
-use crate::ast::{GenericBound, TraitBoundModifier, TraitObjectSyntax};
-use crate::ast::{GenericParam, GenericParamKind, GenericArg, WhereClause};
-use crate::ast::{Ty, TyKind, AssocTyConstraint, AssocTyConstraintKind, GenericBounds};
+use crate::ast::{GenericParam, GenericParamKind, WhereClause};
+use crate::ast::{Ty, TyKind,  GenericBounds};
 use crate::ast::{Visibility, VisibilityKind, Unsafety, CrateSugar};
 use crate::ext::base::DummyResult;
 use crate::ext::hygiene::SyntaxContext;
@@ -54,29 +53,6 @@ struct Restrictions: u8 {
     }
 }
 
-/// Specifies how to parse a path.
-#[derive(Copy, Clone, PartialEq)]
-pub enum PathStyle {
-    /// In some contexts, notably in expressions, paths with generic arguments are ambiguous
-    /// with something else. For example, in expressions `segment < ....` can be interpreted
-    /// as a comparison and `segment ( ....` can be interpreted as a function call.
-    /// In all such contexts the non-path interpretation is preferred by default for practical
-    /// reasons, but the path interpretation can be forced by the disambiguator `::`, e.g.
-    /// `x<y>` - comparisons, `x::<y>` - unambiguously a path.
-    Expr,
-    /// In other contexts, notably in types, no ambiguity exists and paths can be written
-    /// without the disambiguator, e.g., `x<y>` - unambiguously a path.
-    /// Paths with disambiguators are still accepted, `x::<Y>` - unambiguously a path too.
-    Type,
-    /// A path with generic arguments disallowed, e.g., `foo::bar::Baz`, used in imports,
-    /// visibilities or attributes.
-    /// Technically, this variant is unnecessary and e.g., `Expr` can be used instead
-    /// (paths in "mod" contexts have to be checked later for absence of generic arguments
-    /// anyway, due to macros), but it is used to avoid weird suggestions about expected
-    /// tokens when something goes wrong.
-    Mod,
-}
-
 #[derive(Clone, Copy, PartialEq, Debug)]
 crate enum SemiColonMode {
     Break,
@@ -357,16 +333,6 @@ impl TokenType {
     }
 }
 
-/// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
-/// `IDENT<<u8 as Trait>::AssocTy>`.
-///
-/// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes
-/// that `IDENT` is not the ident of a fn trait.
-fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
-    t == &token::ModSep || t == &token::Lt ||
-    t == &token::BinOp(token::Shl)
-}
-
 #[derive(Copy, Clone, Debug)]
 crate enum TokenExpectType {
     Expect,
@@ -976,50 +942,6 @@ fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool {
         self.look_ahead(dist, |t| kws.iter().any(|&kw| t.is_keyword(kw)))
     }
 
-    /// Is the current token one of the keywords that signals a bare function type?
-    fn token_is_bare_fn_keyword(&mut self) -> bool {
-        self.check_keyword(kw::Fn) ||
-            self.check_keyword(kw::Unsafe) ||
-            self.check_keyword(kw::Extern)
-    }
-
-    /// Parses a `TyKind::BareFn` type.
-    fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a, TyKind> {
-        /*
-
-        [unsafe] [extern "ABI"] fn (S) -> T
-         ^~~~^           ^~~~^     ^~^    ^
-           |               |        |     |
-           |               |        |   Return type
-           |               |      Argument types
-           |               |
-           |              ABI
-        Function Style
-        */
-
-        let unsafety = self.parse_unsafety();
-        let abi = if self.eat_keyword(kw::Extern) {
-            self.parse_opt_abi()?.unwrap_or(Abi::C)
-        } else {
-            Abi::Rust
-        };
-
-        self.expect_keyword(kw::Fn)?;
-        let (inputs, c_variadic) = self.parse_fn_args(false, true)?;
-        let ret_ty = self.parse_ret_ty(false)?;
-        let decl = P(FnDecl {
-            inputs,
-            output: ret_ty,
-            c_variadic,
-        });
-        Ok(TyKind::BareFn(P(BareFnTy {
-            abi,
-            unsafety,
-            generic_params,
-            decl,
-        })))
-    }
-
     /// Parses asyncness: `async` or nothing.
     fn parse_asyncness(&mut self) -> IsAsync {
         if self.eat_keyword(kw::Async) {
@@ -1041,236 +963,6 @@ fn parse_unsafety(&mut self) -> Unsafety {
         }
     }
 
-    /// Parses an optional return type `[ -> TY ]` in a function declaration.
-    fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> {
-        if self.eat(&token::RArrow) {
-            Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true, false)?))
-        } else {
-            Ok(FunctionRetTy::Default(self.token.span.shrink_to_lo()))
-        }
-    }
-
-    /// Parses a type.
-    pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
-        self.parse_ty_common(true, true, false)
-    }
-
-    /// Parses a type in restricted contexts where `+` is not permitted.
-    ///
-    /// Example 1: `&'a TYPE`
-    ///     `+` is prohibited to maintain operator priority (P(+) < P(&)).
-    /// Example 2: `value1 as TYPE + value2`
-    ///     `+` is prohibited to avoid interactions with expression grammar.
-    fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
-        self.parse_ty_common(false, true, false)
-    }
-
-    fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool,
-                       allow_c_variadic: bool) -> PResult<'a, P<Ty>> {
-        maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
-        maybe_whole!(self, NtTy, |x| x);
-
-        let lo = self.token.span;
-        let mut impl_dyn_multi = false;
-        let node = if self.eat(&token::OpenDelim(token::Paren)) {
-            // `(TYPE)` is a parenthesized type.
-            // `(TYPE,)` is a tuple with a single field of type TYPE.
-            let mut ts = vec![];
-            let mut last_comma = false;
-            while self.token != token::CloseDelim(token::Paren) {
-                ts.push(self.parse_ty()?);
-                if self.eat(&token::Comma) {
-                    last_comma = true;
-                } else {
-                    last_comma = false;
-                    break;
-                }
-            }
-            let trailing_plus = self.prev_token_kind == PrevTokenKind::Plus;
-            self.expect(&token::CloseDelim(token::Paren))?;
-
-            if ts.len() == 1 && !last_comma {
-                let ty = ts.into_iter().nth(0).unwrap().into_inner();
-                let maybe_bounds = allow_plus && self.token.is_like_plus();
-                match ty.node {
-                    // `(TY_BOUND_NOPAREN) + BOUND + ...`.
-                    TyKind::Path(None, ref path) if maybe_bounds => {
-                        self.parse_remaining_bounds(Vec::new(), path.clone(), lo, true)?
-                    }
-                    TyKind::TraitObject(ref bounds, TraitObjectSyntax::None)
-                            if maybe_bounds && bounds.len() == 1 && !trailing_plus => {
-                        let path = match bounds[0] {
-                            GenericBound::Trait(ref pt, ..) => pt.trait_ref.path.clone(),
-                            GenericBound::Outlives(..) => self.bug("unexpected lifetime bound"),
-                        };
-                        self.parse_remaining_bounds(Vec::new(), path, lo, true)?
-                    }
-                    // `(TYPE)`
-                    _ => TyKind::Paren(P(ty))
-                }
-            } else {
-                TyKind::Tup(ts)
-            }
-        } else if self.eat(&token::Not) {
-            // Never type `!`
-            TyKind::Never
-        } else if self.eat(&token::BinOp(token::Star)) {
-            // Raw pointer
-            TyKind::Ptr(self.parse_ptr()?)
-        } else if self.eat(&token::OpenDelim(token::Bracket)) {
-            // Array or slice
-            let t = self.parse_ty()?;
-            // Parse optional `; EXPR` in `[TYPE; EXPR]`
-            let t = match self.maybe_parse_fixed_length_of_vec()? {
-                None => TyKind::Slice(t),
-                Some(length) => TyKind::Array(t, AnonConst {
-                    id: ast::DUMMY_NODE_ID,
-                    value: length,
-                }),
-            };
-            self.expect(&token::CloseDelim(token::Bracket))?;
-            t
-        } else if self.check(&token::BinOp(token::And)) || self.check(&token::AndAnd) {
-            // Reference
-            self.expect_and()?;
-            self.parse_borrowed_pointee()?
-        } else if self.eat_keyword_noexpect(kw::Typeof) {
-            // `typeof(EXPR)`
-            // In order to not be ambiguous, the type must be surrounded by parens.
-            self.expect(&token::OpenDelim(token::Paren))?;
-            let e = AnonConst {
-                id: ast::DUMMY_NODE_ID,
-                value: self.parse_expr()?,
-            };
-            self.expect(&token::CloseDelim(token::Paren))?;
-            TyKind::Typeof(e)
-        } else if self.eat_keyword(kw::Underscore) {
-            // A type to be inferred `_`
-            TyKind::Infer
-        } else if self.token_is_bare_fn_keyword() {
-            // Function pointer type
-            self.parse_ty_bare_fn(Vec::new())?
-        } else if self.check_keyword(kw::For) {
-            // Function pointer type or bound list (trait object type) starting with a poly-trait.
-            //   `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
-            //   `for<'lt> Trait1<'lt> + Trait2 + 'a`
-            let lo = self.token.span;
-            let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
-            if self.token_is_bare_fn_keyword() {
-                self.parse_ty_bare_fn(lifetime_defs)?
-            } else {
-                let path = self.parse_path(PathStyle::Type)?;
-                let parse_plus = allow_plus && self.check_plus();
-                self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)?
-            }
-        } else if self.eat_keyword(kw::Impl) {
-            // Always parse bounds greedily for better error recovery.
-            let bounds = self.parse_generic_bounds(None)?;
-            impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
-            TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
-        } else if self.check_keyword(kw::Dyn) &&
-                  (self.token.span.rust_2018() ||
-                   self.look_ahead(1, |t| t.can_begin_bound() &&
-                                          !can_continue_type_after_non_fn_ident(t))) {
-            self.bump(); // `dyn`
-            // Always parse bounds greedily for better error recovery.
-            let bounds = self.parse_generic_bounds(None)?;
-            impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
-            TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
-        } else if self.check(&token::Question) ||
-                  self.check_lifetime() && self.look_ahead(1, |t| t.is_like_plus()) {
-            // Bound list (trait object type)
-            TyKind::TraitObject(self.parse_generic_bounds_common(allow_plus, None)?,
-                                TraitObjectSyntax::None)
-        } else if self.eat_lt() {
-            // Qualified path
-            let (qself, path) = self.parse_qpath(PathStyle::Type)?;
-            TyKind::Path(Some(qself), path)
-        } else if self.token.is_path_start() {
-            // Simple path
-            let path = self.parse_path(PathStyle::Type)?;
-            if self.eat(&token::Not) {
-                // Macro invocation in type position
-                let (delim, tts) = self.expect_delimited_token_tree()?;
-                let node = Mac_ {
-                    path,
-                    tts,
-                    delim,
-                    prior_type_ascription: self.last_type_ascription,
-                };
-                TyKind::Mac(respan(lo.to(self.prev_span), node))
-            } else {
-                // Just a type path or bound list (trait object type) starting with a trait.
-                //   `Type`
-                //   `Trait1 + Trait2 + 'a`
-                if allow_plus && self.check_plus() {
-                    self.parse_remaining_bounds(Vec::new(), path, lo, true)?
-                } else {
-                    TyKind::Path(None, path)
-                }
-            }
-        } else if self.check(&token::DotDotDot) {
-            if allow_c_variadic {
-                self.eat(&token::DotDotDot);
-                TyKind::CVarArgs
-            } else {
-                return Err(self.fatal(
-                    "only foreign functions are allowed to be C-variadic"
-                ));
-            }
-        } else {
-            let msg = format!("expected type, found {}", self.this_token_descr());
-            let mut err = self.fatal(&msg);
-            err.span_label(self.token.span, "expected type");
-            self.maybe_annotate_with_ascription(&mut err, true);
-            return Err(err);
-        };
-
-        let span = lo.to(self.prev_span);
-        let ty = P(Ty { node, span, id: ast::DUMMY_NODE_ID });
-
-        // Try to recover from use of `+` with incorrect priority.
-        self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty);
-        self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?;
-        self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)
-    }
-
-    fn parse_remaining_bounds(&mut self, generic_params: Vec<GenericParam>, path: ast::Path,
-                              lo: Span, parse_plus: bool) -> PResult<'a, TyKind> {
-        let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span));
-        let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
-        if parse_plus {
-            self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
-            bounds.append(&mut self.parse_generic_bounds(Some(self.prev_span))?);
-        }
-        Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
-    }
-
-    fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
-        let opt_lifetime = if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
-        let mutbl = self.parse_mutability();
-        let ty = self.parse_ty_no_plus()?;
-        return Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl }));
-    }
-
-    fn parse_ptr(&mut self) -> PResult<'a, MutTy> {
-        let mutbl = if self.eat_keyword(kw::Mut) {
-            Mutability::Mutable
-        } else if self.eat_keyword(kw::Const) {
-            Mutability::Immutable
-        } else {
-            let span = self.prev_span;
-            let msg = "expected mut or const in raw pointer type";
-            self.struct_span_err(span, msg)
-                .span_label(span, msg)
-                .help("use `*mut T` or `*const T` as appropriate")
-                .emit();
-            Mutability::Immutable
-        };
-        let t = self.parse_ty_no_plus()?;
-        Ok(MutTy { ty: t, mutbl })
-    }
-
     fn is_named_argument(&self) -> bool {
         let offset = match self.token.kind {
             token::Interpolated(ref nt) => match **nt {
@@ -1387,25 +1079,6 @@ fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> {
         })
     }
 
-    fn maybe_parse_fixed_length_of_vec(&mut self) -> PResult<'a, Option<P<ast::Expr>>> {
-        if self.eat(&token::Semi) {
-            Ok(Some(self.parse_expr()?))
-        } else {
-            Ok(None)
-        }
-    }
-
-    fn parse_path_segment_ident(&mut self) -> PResult<'a, ast::Ident> {
-        match self.token.kind {
-            token::Ident(name, _) if name.is_path_segment_keyword() => {
-                let span = self.token.span;
-                self.bump();
-                Ok(Ident::new(name, span))
-            }
-            _ => self.parse_ident(),
-        }
-    }
-
     fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> {
         match self.token.kind {
             token::Ident(name, false) if name == kw::Underscore => {
@@ -1417,188 +1090,6 @@ fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> {
         }
     }
 
-    /// Parses a qualified path.
-    /// Assumes that the leading `<` has been parsed already.
-    ///
-    /// `qualified_path = <type [as trait_ref]>::path`
-    ///
-    /// # Examples
-    /// `<T>::default`
-    /// `<T as U>::a`
-    /// `<T as U>::F::a<S>` (without disambiguator)
-    /// `<T as U>::F::a::<S>` (with disambiguator)
-    fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, ast::Path)> {
-        let lo = self.prev_span;
-        let ty = self.parse_ty()?;
-
-        // `path` will contain the prefix of the path up to the `>`,
-        // if any (e.g., `U` in the `<T as U>::*` examples
-        // above). `path_span` has the span of that path, or an empty
-        // span in the case of something like `<T>::Bar`.
-        let (mut path, path_span);
-        if self.eat_keyword(kw::As) {
-            let path_lo = self.token.span;
-            path = self.parse_path(PathStyle::Type)?;
-            path_span = path_lo.to(self.prev_span);
-        } else {
-            path_span = self.token.span.to(self.token.span);
-            path = ast::Path { segments: Vec::new(), span: path_span };
-        }
-
-        // See doc comment for `unmatched_angle_bracket_count`.
-        self.expect(&token::Gt)?;
-        if self.unmatched_angle_bracket_count > 0 {
-            self.unmatched_angle_bracket_count -= 1;
-            debug!("parse_qpath: (decrement) count={:?}", self.unmatched_angle_bracket_count);
-        }
-
-        self.expect(&token::ModSep)?;
-
-        let qself = QSelf { ty, path_span, position: path.segments.len() };
-        self.parse_path_segments(&mut path.segments, style)?;
-
-        Ok((qself, ast::Path { segments: path.segments, span: lo.to(self.prev_span) }))
-    }
-
-    /// Parses simple paths.
-    ///
-    /// `path = [::] segment+`
-    /// `segment = ident | ident[::]<args> | ident[::](args) [-> type]`
-    ///
-    /// # Examples
-    /// `a::b::C<D>` (without disambiguator)
-    /// `a::b::C::<D>` (with disambiguator)
-    /// `Fn(Args)` (without disambiguator)
-    /// `Fn::(Args)` (with disambiguator)
-    pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path> {
-        maybe_whole!(self, NtPath, |path| {
-            if style == PathStyle::Mod &&
-               path.segments.iter().any(|segment| segment.args.is_some()) {
-                self.diagnostic().span_err(path.span, "unexpected generic arguments in path");
-            }
-            path
-        });
-
-        let lo = self.meta_var_span.unwrap_or(self.token.span);
-        let mut segments = Vec::new();
-        let mod_sep_ctxt = self.token.span.ctxt();
-        if self.eat(&token::ModSep) {
-            segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
-        }
-        self.parse_path_segments(&mut segments, style)?;
-
-        Ok(ast::Path { segments, span: lo.to(self.prev_span) })
-    }
-
-    /// Like `parse_path`, but also supports parsing `Word` meta items into paths for
-    /// backwards-compatibility. This is used when parsing derive macro paths in `#[derive]`
-    /// attributes.
-    pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, ast::Path> {
-        let meta_ident = match self.token.kind {
-            token::Interpolated(ref nt) => match **nt {
-                token::NtMeta(ref meta) => match meta.node {
-                    ast::MetaItemKind::Word => Some(meta.path.clone()),
-                    _ => None,
-                },
-                _ => None,
-            },
-            _ => None,
-        };
-        if let Some(path) = meta_ident {
-            self.bump();
-            return Ok(path);
-        }
-        self.parse_path(style)
-    }
-
-    crate fn parse_path_segments(&mut self,
-                           segments: &mut Vec<PathSegment>,
-                           style: PathStyle)
-                           -> PResult<'a, ()> {
-        loop {
-            let segment = self.parse_path_segment(style)?;
-            if style == PathStyle::Expr {
-                // In order to check for trailing angle brackets, we must have finished
-                // recursing (`parse_path_segment` can indirectly call this function),
-                // that is, the next token must be the highlighted part of the below example:
-                //
-                // `Foo::<Bar as Baz<T>>::Qux`
-                //                      ^ here
-                //
-                // As opposed to the below highlight (if we had only finished the first
-                // recursion):
-                //
-                // `Foo::<Bar as Baz<T>>::Qux`
-                //                     ^ here
-                //
-                // `PathStyle::Expr` is only provided at the root invocation and never in
-                // `parse_path_segment` to recurse and therefore can be checked to maintain
-                // this invariant.
-                self.check_trailing_angle_brackets(&segment, token::ModSep);
-            }
-            segments.push(segment);
-
-            if self.is_import_coupler() || !self.eat(&token::ModSep) {
-                return Ok(());
-            }
-        }
-    }
-
-    fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> {
-        let ident = self.parse_path_segment_ident()?;
-
-        let is_args_start = |token: &Token| match token.kind {
-            token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren)
-            | token::LArrow => true,
-            _ => false,
-        };
-        let check_args_start = |this: &mut Self| {
-            this.expected_tokens.extend_from_slice(
-                &[TokenType::Token(token::Lt), TokenType::Token(token::OpenDelim(token::Paren))]
-            );
-            is_args_start(&this.token)
-        };
-
-        Ok(if style == PathStyle::Type && check_args_start(self) ||
-              style != PathStyle::Mod && self.check(&token::ModSep)
-                                      && self.look_ahead(1, |t| is_args_start(t)) {
-            // We use `style == PathStyle::Expr` to check if this is in a recursion or not. If
-            // it isn't, then we reset the unmatched angle bracket count as we're about to start
-            // parsing a new path.
-            if style == PathStyle::Expr {
-                self.unmatched_angle_bracket_count = 0;
-                self.max_angle_bracket_count = 0;
-            }
-
-            // Generic arguments are found - `<`, `(`, `::<` or `::(`.
-            self.eat(&token::ModSep);
-            let lo = self.token.span;
-            let args = if self.eat_lt() {
-                // `<'a, T, A = U>`
-                let (args, constraints) =
-                    self.parse_generic_args_with_leaning_angle_bracket_recovery(style, lo)?;
-                self.expect_gt()?;
-                let span = lo.to(self.prev_span);
-                AngleBracketedArgs { args, constraints, span }.into()
-            } else {
-                // `(T, U) -> R`
-                let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
-                let span = lo.to(self.prev_span);
-                let output = if self.eat(&token::RArrow) {
-                    Some(self.parse_ty_common(false, false, false)?)
-                } else {
-                    None
-                };
-                ParenthesizedArgs { inputs, output, span }.into()
-            };
-
-            PathSegment { ident, args, id: ast::DUMMY_NODE_ID }
-        } else {
-            // Generic arguments are not found.
-            PathSegment::from_ident(ident)
-        })
-    }
-
     crate fn check_lifetime(&mut self) -> bool {
         self.expected_tokens.push(TokenType::Lifetime);
         self.token.is_lifetime()
@@ -2202,130 +1693,6 @@ fn warn_missing_semicolon(&self) {
         }).emit();
     }
 
-    /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`.
-    ///
-    /// ```
-    /// BOUND = TY_BOUND | LT_BOUND
-    /// LT_BOUND = LIFETIME (e.g., `'a`)
-    /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
-    /// TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g., `?for<'a: 'b> m::Trait<'a>`)
-    /// ```
-    fn parse_generic_bounds_common(&mut self,
-                                   allow_plus: bool,
-                                   colon_span: Option<Span>) -> PResult<'a, GenericBounds> {
-        let mut bounds = Vec::new();
-        let mut negative_bounds = Vec::new();
-        let mut last_plus_span = None;
-        let mut was_negative = false;
-        loop {
-            // This needs to be synchronized with `TokenKind::can_begin_bound`.
-            let is_bound_start = self.check_path() || self.check_lifetime() ||
-                                 self.check(&token::Not) || // used for error reporting only
-                                 self.check(&token::Question) ||
-                                 self.check_keyword(kw::For) ||
-                                 self.check(&token::OpenDelim(token::Paren));
-            if is_bound_start {
-                let lo = self.token.span;
-                let has_parens = self.eat(&token::OpenDelim(token::Paren));
-                let inner_lo = self.token.span;
-                let is_negative = self.eat(&token::Not);
-                let question = if self.eat(&token::Question) { Some(self.prev_span) } else { None };
-                if self.token.is_lifetime() {
-                    if let Some(question_span) = question {
-                        self.span_err(question_span,
-                                      "`?` may only modify trait bounds, not lifetime bounds");
-                    }
-                    bounds.push(GenericBound::Outlives(self.expect_lifetime()));
-                    if has_parens {
-                        let inner_span = inner_lo.to(self.prev_span);
-                        self.expect(&token::CloseDelim(token::Paren))?;
-                        let mut err = self.struct_span_err(
-                            lo.to(self.prev_span),
-                            "parenthesized lifetime bounds are not supported"
-                        );
-                        if let Ok(snippet) = self.span_to_snippet(inner_span) {
-                            err.span_suggestion_short(
-                                lo.to(self.prev_span),
-                                "remove the parentheses",
-                                snippet.to_owned(),
-                                Applicability::MachineApplicable
-                            );
-                        }
-                        err.emit();
-                    }
-                } else {
-                    let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
-                    let path = self.parse_path(PathStyle::Type)?;
-                    if has_parens {
-                        self.expect(&token::CloseDelim(token::Paren))?;
-                    }
-                    let poly_span = lo.to(self.prev_span);
-                    if is_negative {
-                        was_negative = true;
-                        if let Some(sp) = last_plus_span.or(colon_span) {
-                            negative_bounds.push(sp.to(poly_span));
-                        }
-                    } else {
-                        let poly_trait = PolyTraitRef::new(lifetime_defs, path, poly_span);
-                        let modifier = if question.is_some() {
-                            TraitBoundModifier::Maybe
-                        } else {
-                            TraitBoundModifier::None
-                        };
-                        bounds.push(GenericBound::Trait(poly_trait, modifier));
-                    }
-                }
-            } else {
-                break
-            }
-
-            if !allow_plus || !self.eat_plus() {
-                break
-            } else {
-                last_plus_span = Some(self.prev_span);
-            }
-        }
-
-        if !negative_bounds.is_empty() || was_negative {
-            let plural = negative_bounds.len() > 1;
-            let last_span = negative_bounds.last().map(|sp| *sp);
-            let mut err = self.struct_span_err(
-                negative_bounds,
-                "negative trait bounds are not supported",
-            );
-            if let Some(sp) = last_span {
-                err.span_label(sp, "negative trait bounds are not supported");
-            }
-            if let Some(bound_list) = colon_span {
-                let bound_list = bound_list.to(self.prev_span);
-                let mut new_bound_list = String::new();
-                if !bounds.is_empty() {
-                    let mut snippets = bounds.iter().map(|bound| bound.span())
-                        .map(|span| self.span_to_snippet(span));
-                    while let Some(Ok(snippet)) = snippets.next() {
-                        new_bound_list.push_str(" + ");
-                        new_bound_list.push_str(&snippet);
-                    }
-                    new_bound_list = new_bound_list.replacen(" +", ":", 1);
-                }
-                err.span_suggestion_hidden(
-                    bound_list,
-                    &format!("remove the trait bound{}", if plural { "s" } else { "" }),
-                    new_bound_list,
-                    Applicability::MachineApplicable,
-                );
-            }
-            err.emit();
-        }
-
-        return Ok(bounds);
-    }
-
-    crate fn parse_generic_bounds(&mut self,
-                                  colon_span: Option<Span>) -> PResult<'a, GenericBounds> {
-        self.parse_generic_bounds_common(true, colon_span)
-    }
-
     /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
     ///
     /// ```
@@ -2475,250 +1842,6 @@ fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
         })
     }
 
-    /// Parses generic args (within a path segment) with recovery for extra leading angle brackets.
-    /// For the purposes of understanding the parsing logic of generic arguments, this function
-    /// can be thought of being the same as just calling `self.parse_generic_args()` if the source
-    /// had the correct amount of leading angle brackets.
-    ///
-    /// ```ignore (diagnostics)
-    /// bar::<<<<T as Foo>::Output>();
-    ///      ^^ help: remove extra angle brackets
-    /// ```
-    fn parse_generic_args_with_leaning_angle_bracket_recovery(
-        &mut self,
-        style: PathStyle,
-        lo: Span,
-    ) -> PResult<'a, (Vec<GenericArg>, Vec<AssocTyConstraint>)> {
-        // We need to detect whether there are extra leading left angle brackets and produce an
-        // appropriate error and suggestion. This cannot be implemented by looking ahead at
-        // upcoming tokens for a matching `>` character - if there are unmatched `<` tokens
-        // then there won't be matching `>` tokens to find.
-        //
-        // To explain how this detection works, consider the following example:
-        //
-        // ```ignore (diagnostics)
-        // bar::<<<<T as Foo>::Output>();
-        //      ^^ help: remove extra angle brackets
-        // ```
-        //
-        // Parsing of the left angle brackets starts in this function. We start by parsing the
-        // `<` token (incrementing the counter of unmatched angle brackets on `Parser` via
-        // `eat_lt`):
-        //
-        // *Upcoming tokens:* `<<<<T as Foo>::Output>;`
-        // *Unmatched count:* 1
-        // *`parse_path_segment` calls deep:* 0
-        //
-        // This has the effect of recursing as this function is called if a `<` character
-        // is found within the expected generic arguments:
-        //
-        // *Upcoming tokens:* `<<<T as Foo>::Output>;`
-        // *Unmatched count:* 2
-        // *`parse_path_segment` calls deep:* 1
-        //
-        // Eventually we will have recursed until having consumed all of the `<` tokens and
-        // this will be reflected in the count:
-        //
-        // *Upcoming tokens:* `T as Foo>::Output>;`
-        // *Unmatched count:* 4
-        // `parse_path_segment` calls deep:* 3
-        //
-        // The parser will continue until reaching the first `>` - this will decrement the
-        // unmatched angle bracket count and return to the parent invocation of this function
-        // having succeeded in parsing:
-        //
-        // *Upcoming tokens:* `::Output>;`
-        // *Unmatched count:* 3
-        // *`parse_path_segment` calls deep:* 2
-        //
-        // This will continue until the next `>` character which will also return successfully
-        // to the parent invocation of this function and decrement the count:
-        //
-        // *Upcoming tokens:* `;`
-        // *Unmatched count:* 2
-        // *`parse_path_segment` calls deep:* 1
-        //
-        // At this point, this function will expect to find another matching `>` character but
-        // won't be able to and will return an error. This will continue all the way up the
-        // call stack until the first invocation:
-        //
-        // *Upcoming tokens:* `;`
-        // *Unmatched count:* 2
-        // *`parse_path_segment` calls deep:* 0
-        //
-        // In doing this, we have managed to work out how many unmatched leading left angle
-        // brackets there are, but we cannot recover as the unmatched angle brackets have
-        // already been consumed. To remedy this, we keep a snapshot of the parser state
-        // before we do the above. We can then inspect whether we ended up with a parsing error
-        // and unmatched left angle brackets and if so, restore the parser state before we
-        // consumed any `<` characters to emit an error and consume the erroneous tokens to
-        // recover by attempting to parse again.
-        //
-        // In practice, the recursion of this function is indirect and there will be other
-        // locations that consume some `<` characters - as long as we update the count when
-        // this happens, it isn't an issue.
-
-        let is_first_invocation = style == PathStyle::Expr;
-        // Take a snapshot before attempting to parse - we can restore this later.
-        let snapshot = if is_first_invocation {
-            Some(self.clone())
-        } else {
-            None
-        };
-
-        debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
-        match self.parse_generic_args() {
-            Ok(value) => Ok(value),
-            Err(ref mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => {
-                // Cancel error from being unable to find `>`. We know the error
-                // must have been this due to a non-zero unmatched angle bracket
-                // count.
-                e.cancel();
-
-                // Swap `self` with our backup of the parser state before attempting to parse
-                // generic arguments.
-                let snapshot = mem::replace(self, snapshot.unwrap());
-
-                debug!(
-                    "parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \
-                     snapshot.count={:?}",
-                    snapshot.unmatched_angle_bracket_count,
-                );
-
-                // Eat the unmatched angle brackets.
-                for _ in 0..snapshot.unmatched_angle_bracket_count {
-                    self.eat_lt();
-                }
-
-                // Make a span over ${unmatched angle bracket count} characters.
-                let span = lo.with_hi(
-                    lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count)
-                );
-                let plural = snapshot.unmatched_angle_bracket_count > 1;
-                self.diagnostic()
-                    .struct_span_err(
-                        span,
-                        &format!(
-                            "unmatched angle bracket{}",
-                            if plural { "s" } else { "" }
-                        ),
-                    )
-                    .span_suggestion(
-                        span,
-                        &format!(
-                            "remove extra angle bracket{}",
-                            if plural { "s" } else { "" }
-                        ),
-                        String::new(),
-                        Applicability::MachineApplicable,
-                    )
-                    .emit();
-
-                // Try again without unmatched angle bracket characters.
-                self.parse_generic_args()
-            },
-            Err(e) => Err(e),
-        }
-    }
-
-    /// Parses (possibly empty) list of lifetime and type arguments and associated type bindings,
-    /// possibly including trailing comma.
-    fn parse_generic_args(&mut self) -> PResult<'a, (Vec<GenericArg>, Vec<AssocTyConstraint>)> {
-        let mut args = Vec::new();
-        let mut constraints = Vec::new();
-        let mut misplaced_assoc_ty_constraints: Vec<Span> = Vec::new();
-        let mut assoc_ty_constraints: Vec<Span> = Vec::new();
-
-        let args_lo = self.token.span;
-
-        loop {
-            if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
-                // Parse lifetime argument.
-                args.push(GenericArg::Lifetime(self.expect_lifetime()));
-                misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints);
-            } else if self.check_ident() && self.look_ahead(1,
-                    |t| t == &token::Eq || t == &token::Colon) {
-                // Parse associated type constraint.
-                let lo = self.token.span;
-                let ident = self.parse_ident()?;
-                let kind = if self.eat(&token::Eq) {
-                    AssocTyConstraintKind::Equality {
-                        ty: self.parse_ty()?,
-                    }
-                } else if self.eat(&token::Colon) {
-                    AssocTyConstraintKind::Bound {
-                        bounds: self.parse_generic_bounds(Some(self.prev_span))?,
-                    }
-                } else {
-                    unreachable!();
-                };
-                let span = lo.to(self.prev_span);
-                constraints.push(AssocTyConstraint {
-                    id: ast::DUMMY_NODE_ID,
-                    ident,
-                    kind,
-                    span,
-                });
-                assoc_ty_constraints.push(span);
-            } else if self.check_const_arg() {
-                // Parse const argument.
-                let expr = if let token::OpenDelim(token::Brace) = self.token.kind {
-                    self.parse_block_expr(
-                        None, self.token.span, BlockCheckMode::Default, ThinVec::new()
-                    )?
-                } else if self.token.is_ident() {
-                    // FIXME(const_generics): to distinguish between idents for types and consts,
-                    // we should introduce a GenericArg::Ident in the AST and distinguish when
-                    // lowering to the HIR. For now, idents for const args are not permitted.
-                    if self.token.is_keyword(kw::True) || self.token.is_keyword(kw::False) {
-                        self.parse_literal_maybe_minus()?
-                    } else {
-                        return Err(
-                            self.fatal("identifiers may currently not be used for const generics")
-                        );
-                    }
-                } else {
-                    self.parse_literal_maybe_minus()?
-                };
-                let value = AnonConst {
-                    id: ast::DUMMY_NODE_ID,
-                    value: expr,
-                };
-                args.push(GenericArg::Const(value));
-                misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints);
-            } else if self.check_type() {
-                // Parse type argument.
-                args.push(GenericArg::Type(self.parse_ty()?));
-                misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints);
-            } else {
-                break
-            }
-
-            if !self.eat(&token::Comma) {
-                break
-            }
-        }
-
-        // FIXME: we would like to report this in ast_validation instead, but we currently do not
-        // preserve ordering of generic parameters with respect to associated type binding, so we
-        // lose that information after parsing.
-        if misplaced_assoc_ty_constraints.len() > 0 {
-            let mut err = self.struct_span_err(
-                args_lo.to(self.prev_span),
-                "associated type bindings must be declared after generic parameters",
-            );
-            for span in misplaced_assoc_ty_constraints {
-                err.span_label(
-                    span,
-                    "this associated type binding should be moved after the generic parameters",
-                );
-            }
-            err.emit();
-        }
-
-        Ok((args, constraints))
-    }
-
     /// Parses an optional where-clause and places it in `generics`.
     ///
     /// ```ignore (only-for-syntax-highlight)
@@ -3087,19 +2210,6 @@ fn choose_generics_over_qpath(&self) -> bool {
             self.is_keyword_ahead(1, &[kw::Const]))
     }
 
-    fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
-        if self.eat_keyword(kw::For) {
-            self.expect_lt()?;
-            let params = self.parse_generic_params()?;
-            self.expect_gt()?;
-            // We rely on AST validation to rule out invalid cases: There must not be type
-            // parameters, and the lifetime parameters must not have bounds.
-            Ok(params)
-        } else {
-            Ok(Vec::new())
-        }
-    }
-
     /// Parses `pub`, `pub(crate)` and `pub(in path)` plus shortcuts `crate` for `pub(crate)`,
     /// `pub(self)` for `pub(in self)` and `pub(super)` for `pub(in super)`.
     /// If the following element can't be a tuple (i.e., it's a function definition), then
diff --git a/src/libsyntax/parse/parser/path.rs b/src/libsyntax/parse/parser/path.rs
new file mode 100644 (file)
index 0000000..2760cd3
--- /dev/null
@@ -0,0 +1,474 @@
+use super::{Parser, PResult, TokenType, BlockCheckMode};
+
+use crate::{maybe_whole, ThinVec};
+use crate::ast::{self, QSelf, Path, PathSegment, Ident, ParenthesizedArgs, AngleBracketedArgs};
+use crate::ast::{AnonConst, GenericArg, AssocTyConstraint, AssocTyConstraintKind};
+use crate::parse::token::{self, Token};
+use crate::source_map::{Span, BytePos};
+use crate::symbol::{kw};
+
+use std::mem;
+use log::debug;
+use errors::{Applicability};
+
+/// Specifies how to parse a path.
+#[derive(Copy, Clone, PartialEq)]
+pub enum PathStyle {
+    /// In some contexts, notably in expressions, paths with generic arguments are ambiguous
+    /// with something else. For example, in expressions `segment < ....` can be interpreted
+    /// as a comparison and `segment ( ....` can be interpreted as a function call.
+    /// In all such contexts the non-path interpretation is preferred by default for practical
+    /// reasons, but the path interpretation can be forced by the disambiguator `::`, e.g.
+    /// `x<y>` - comparisons, `x::<y>` - unambiguously a path.
+    Expr,
+    /// In other contexts, notably in types, no ambiguity exists and paths can be written
+    /// without the disambiguator, e.g., `x<y>` - unambiguously a path.
+    /// Paths with disambiguators are still accepted, `x::<Y>` - unambiguously a path too.
+    Type,
+    /// A path with generic arguments disallowed, e.g., `foo::bar::Baz`, used in imports,
+    /// visibilities or attributes.
+    /// Technically, this variant is unnecessary and e.g., `Expr` can be used instead
+    /// (paths in "mod" contexts have to be checked later for absence of generic arguments
+    /// anyway, due to macros), but it is used to avoid weird suggestions about expected
+    /// tokens when something goes wrong.
+    Mod,
+}
+
+impl<'a> Parser<'a> {
+    /// Parses a qualified path.
+    /// Assumes that the leading `<` has been parsed already.
+    ///
+    /// `qualified_path = <type [as trait_ref]>::path`
+    ///
+    /// # Examples
+    /// `<T>::default`
+    /// `<T as U>::a`
+    /// `<T as U>::F::a<S>` (without disambiguator)
+    /// `<T as U>::F::a::<S>` (with disambiguator)
+    pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, Path)> {
+        let lo = self.prev_span;
+        let ty = self.parse_ty()?;
+
+        // `path` will contain the prefix of the path up to the `>`,
+        // if any (e.g., `U` in the `<T as U>::*` examples
+        // above). `path_span` has the span of that path, or an empty
+        // span in the case of something like `<T>::Bar`.
+        let (mut path, path_span);
+        if self.eat_keyword(kw::As) {
+            let path_lo = self.token.span;
+            path = self.parse_path(PathStyle::Type)?;
+            path_span = path_lo.to(self.prev_span);
+        } else {
+            path_span = self.token.span.to(self.token.span);
+            path = ast::Path { segments: Vec::new(), span: path_span };
+        }
+
+        // See doc comment for `unmatched_angle_bracket_count`.
+        self.expect(&token::Gt)?;
+        if self.unmatched_angle_bracket_count > 0 {
+            self.unmatched_angle_bracket_count -= 1;
+            debug!("parse_qpath: (decrement) count={:?}", self.unmatched_angle_bracket_count);
+        }
+
+        self.expect(&token::ModSep)?;
+
+        let qself = QSelf { ty, path_span, position: path.segments.len() };
+        self.parse_path_segments(&mut path.segments, style)?;
+
+        Ok((qself, Path { segments: path.segments, span: lo.to(self.prev_span) }))
+    }
+
+    /// Parses simple paths.
+    ///
+    /// `path = [::] segment+`
+    /// `segment = ident | ident[::]<args> | ident[::](args) [-> type]`
+    ///
+    /// # Examples
+    /// `a::b::C<D>` (without disambiguator)
+    /// `a::b::C::<D>` (with disambiguator)
+    /// `Fn(Args)` (without disambiguator)
+    /// `Fn::(Args)` (with disambiguator)
+    pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> {
+        maybe_whole!(self, NtPath, |path| {
+            if style == PathStyle::Mod &&
+               path.segments.iter().any(|segment| segment.args.is_some()) {
+                self.diagnostic().span_err(path.span, "unexpected generic arguments in path");
+            }
+            path
+        });
+
+        let lo = self.meta_var_span.unwrap_or(self.token.span);
+        let mut segments = Vec::new();
+        let mod_sep_ctxt = self.token.span.ctxt();
+        if self.eat(&token::ModSep) {
+            segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
+        }
+        self.parse_path_segments(&mut segments, style)?;
+
+        Ok(Path { segments, span: lo.to(self.prev_span) })
+    }
+
+    /// Like `parse_path`, but also supports parsing `Word` meta items into paths for
+    /// backwards-compatibility. This is used when parsing derive macro paths in `#[derive]`
+    /// attributes.
+    pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, Path> {
+        let meta_ident = match self.token.kind {
+            token::Interpolated(ref nt) => match **nt {
+                token::NtMeta(ref meta) => match meta.node {
+                    ast::MetaItemKind::Word => Some(meta.path.clone()),
+                    _ => None,
+                },
+                _ => None,
+            },
+            _ => None,
+        };
+        if let Some(path) = meta_ident {
+            self.bump();
+            return Ok(path);
+        }
+        self.parse_path(style)
+    }
+
+    crate fn parse_path_segments(&mut self,
+                           segments: &mut Vec<PathSegment>,
+                           style: PathStyle)
+                           -> PResult<'a, ()> {
+        loop {
+            let segment = self.parse_path_segment(style)?;
+            if style == PathStyle::Expr {
+                // In order to check for trailing angle brackets, we must have finished
+                // recursing (`parse_path_segment` can indirectly call this function),
+                // that is, the next token must be the highlighted part of the below example:
+                //
+                // `Foo::<Bar as Baz<T>>::Qux`
+                //                      ^ here
+                //
+                // As opposed to the below highlight (if we had only finished the first
+                // recursion):
+                //
+                // `Foo::<Bar as Baz<T>>::Qux`
+                //                     ^ here
+                //
+                // `PathStyle::Expr` is only provided at the root invocation and never in
+                // `parse_path_segment` to recurse and therefore can be checked to maintain
+                // this invariant.
+                self.check_trailing_angle_brackets(&segment, token::ModSep);
+            }
+            segments.push(segment);
+
+            if self.is_import_coupler() || !self.eat(&token::ModSep) {
+                return Ok(());
+            }
+        }
+    }
+
+    pub(super) fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> {
+        let ident = self.parse_path_segment_ident()?;
+
+        let is_args_start = |token: &Token| match token.kind {
+            token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren)
+            | token::LArrow => true,
+            _ => false,
+        };
+        let check_args_start = |this: &mut Self| {
+            this.expected_tokens.extend_from_slice(
+                &[TokenType::Token(token::Lt), TokenType::Token(token::OpenDelim(token::Paren))]
+            );
+            is_args_start(&this.token)
+        };
+
+        Ok(if style == PathStyle::Type && check_args_start(self) ||
+              style != PathStyle::Mod && self.check(&token::ModSep)
+                                      && self.look_ahead(1, |t| is_args_start(t)) {
+            // We use `style == PathStyle::Expr` to check if this is in a recursion or not. If
+            // it isn't, then we reset the unmatched angle bracket count as we're about to start
+            // parsing a new path.
+            if style == PathStyle::Expr {
+                self.unmatched_angle_bracket_count = 0;
+                self.max_angle_bracket_count = 0;
+            }
+
+            // Generic arguments are found - `<`, `(`, `::<` or `::(`.
+            self.eat(&token::ModSep);
+            let lo = self.token.span;
+            let args = if self.eat_lt() {
+                // `<'a, T, A = U>`
+                let (args, constraints) =
+                    self.parse_generic_args_with_leaning_angle_bracket_recovery(style, lo)?;
+                self.expect_gt()?;
+                let span = lo.to(self.prev_span);
+                AngleBracketedArgs { args, constraints, span }.into()
+            } else {
+                // `(T, U) -> R`
+                let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
+                let span = lo.to(self.prev_span);
+                let output = if self.eat(&token::RArrow) {
+                    Some(self.parse_ty_common(false, false, false)?)
+                } else {
+                    None
+                };
+                ParenthesizedArgs { inputs, output, span }.into()
+            };
+
+            PathSegment { ident, args, id: ast::DUMMY_NODE_ID }
+        } else {
+            // Generic arguments are not found.
+            PathSegment::from_ident(ident)
+        })
+    }
+
+    pub(super) fn parse_path_segment_ident(&mut self) -> PResult<'a, Ident> {
+        match self.token.kind {
+            token::Ident(name, _) if name.is_path_segment_keyword() => {
+                let span = self.token.span;
+                self.bump();
+                Ok(Ident::new(name, span))
+            }
+            _ => self.parse_ident(),
+        }
+    }
+
+    /// Parses generic args (within a path segment) with recovery for extra leading angle brackets.
+    /// For the purposes of understanding the parsing logic of generic arguments, this function
+    /// can be thought of being the same as just calling `self.parse_generic_args()` if the source
+    /// had the correct amount of leading angle brackets.
+    ///
+    /// ```ignore (diagnostics)
+    /// bar::<<<<T as Foo>::Output>();
+    ///      ^^ help: remove extra angle brackets
+    /// ```
+    fn parse_generic_args_with_leaning_angle_bracket_recovery(
+        &mut self,
+        style: PathStyle,
+        lo: Span,
+    ) -> PResult<'a, (Vec<GenericArg>, Vec<AssocTyConstraint>)> {
+        // We need to detect whether there are extra leading left angle brackets and produce an
+        // appropriate error and suggestion. This cannot be implemented by looking ahead at
+        // upcoming tokens for a matching `>` character - if there are unmatched `<` tokens
+        // then there won't be matching `>` tokens to find.
+        //
+        // To explain how this detection works, consider the following example:
+        //
+        // ```ignore (diagnostics)
+        // bar::<<<<T as Foo>::Output>();
+        //      ^^ help: remove extra angle brackets
+        // ```
+        //
+        // Parsing of the left angle brackets starts in this function. We start by parsing the
+        // `<` token (incrementing the counter of unmatched angle brackets on `Parser` via
+        // `eat_lt`):
+        //
+        // *Upcoming tokens:* `<<<<T as Foo>::Output>;`
+        // *Unmatched count:* 1
+        // *`parse_path_segment` calls deep:* 0
+        //
+        // This has the effect of recursing as this function is called if a `<` character
+        // is found within the expected generic arguments:
+        //
+        // *Upcoming tokens:* `<<<T as Foo>::Output>;`
+        // *Unmatched count:* 2
+        // *`parse_path_segment` calls deep:* 1
+        //
+        // Eventually we will have recursed until having consumed all of the `<` tokens and
+        // this will be reflected in the count:
+        //
+        // *Upcoming tokens:* `T as Foo>::Output>;`
+        // *Unmatched count:* 4
+        // `parse_path_segment` calls deep:* 3
+        //
+        // The parser will continue until reaching the first `>` - this will decrement the
+        // unmatched angle bracket count and return to the parent invocation of this function
+        // having succeeded in parsing:
+        //
+        // *Upcoming tokens:* `::Output>;`
+        // *Unmatched count:* 3
+        // *`parse_path_segment` calls deep:* 2
+        //
+        // This will continue until the next `>` character which will also return successfully
+        // to the parent invocation of this function and decrement the count:
+        //
+        // *Upcoming tokens:* `;`
+        // *Unmatched count:* 2
+        // *`parse_path_segment` calls deep:* 1
+        //
+        // At this point, this function will expect to find another matching `>` character but
+        // won't be able to and will return an error. This will continue all the way up the
+        // call stack until the first invocation:
+        //
+        // *Upcoming tokens:* `;`
+        // *Unmatched count:* 2
+        // *`parse_path_segment` calls deep:* 0
+        //
+        // In doing this, we have managed to work out how many unmatched leading left angle
+        // brackets there are, but we cannot recover as the unmatched angle brackets have
+        // already been consumed. To remedy this, we keep a snapshot of the parser state
+        // before we do the above. We can then inspect whether we ended up with a parsing error
+        // and unmatched left angle brackets and if so, restore the parser state before we
+        // consumed any `<` characters to emit an error and consume the erroneous tokens to
+        // recover by attempting to parse again.
+        //
+        // In practice, the recursion of this function is indirect and there will be other
+        // locations that consume some `<` characters - as long as we update the count when
+        // this happens, it isn't an issue.
+
+        let is_first_invocation = style == PathStyle::Expr;
+        // Take a snapshot before attempting to parse - we can restore this later.
+        let snapshot = if is_first_invocation {
+            Some(self.clone())
+        } else {
+            None
+        };
+
+        debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
+        match self.parse_generic_args() {
+            Ok(value) => Ok(value),
+            Err(ref mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => {
+                // Cancel error from being unable to find `>`. We know the error
+                // must have been this due to a non-zero unmatched angle bracket
+                // count.
+                e.cancel();
+
+                // Swap `self` with our backup of the parser state before attempting to parse
+                // generic arguments.
+                let snapshot = mem::replace(self, snapshot.unwrap());
+
+                debug!(
+                    "parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \
+                     snapshot.count={:?}",
+                    snapshot.unmatched_angle_bracket_count,
+                );
+
+                // Eat the unmatched angle brackets.
+                for _ in 0..snapshot.unmatched_angle_bracket_count {
+                    self.eat_lt();
+                }
+
+                // Make a span over ${unmatched angle bracket count} characters.
+                let span = lo.with_hi(
+                    lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count)
+                );
+                let plural = snapshot.unmatched_angle_bracket_count > 1;
+                self.diagnostic()
+                    .struct_span_err(
+                        span,
+                        &format!(
+                            "unmatched angle bracket{}",
+                            if plural { "s" } else { "" }
+                        ),
+                    )
+                    .span_suggestion(
+                        span,
+                        &format!(
+                            "remove extra angle bracket{}",
+                            if plural { "s" } else { "" }
+                        ),
+                        String::new(),
+                        Applicability::MachineApplicable,
+                    )
+                    .emit();
+
+                // Try again without unmatched angle bracket characters.
+                self.parse_generic_args()
+            },
+            Err(e) => Err(e),
+        }
+    }
+
+    /// Parses (possibly empty) list of lifetime and type arguments and associated type bindings,
+    /// possibly including trailing comma.
+    fn parse_generic_args(&mut self) -> PResult<'a, (Vec<GenericArg>, Vec<AssocTyConstraint>)> {
+        let mut args = Vec::new();
+        let mut constraints = Vec::new();
+        let mut misplaced_assoc_ty_constraints: Vec<Span> = Vec::new();
+        let mut assoc_ty_constraints: Vec<Span> = Vec::new();
+
+        let args_lo = self.token.span;
+
+        loop {
+            if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
+                // Parse lifetime argument.
+                args.push(GenericArg::Lifetime(self.expect_lifetime()));
+                misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints);
+            } else if self.check_ident() && self.look_ahead(1,
+                    |t| t == &token::Eq || t == &token::Colon) {
+                // Parse associated type constraint.
+                let lo = self.token.span;
+                let ident = self.parse_ident()?;
+                let kind = if self.eat(&token::Eq) {
+                    AssocTyConstraintKind::Equality {
+                        ty: self.parse_ty()?,
+                    }
+                } else if self.eat(&token::Colon) {
+                    AssocTyConstraintKind::Bound {
+                        bounds: self.parse_generic_bounds(Some(self.prev_span))?,
+                    }
+                } else {
+                    unreachable!();
+                };
+                let span = lo.to(self.prev_span);
+                constraints.push(AssocTyConstraint {
+                    id: ast::DUMMY_NODE_ID,
+                    ident,
+                    kind,
+                    span,
+                });
+                assoc_ty_constraints.push(span);
+            } else if self.check_const_arg() {
+                // Parse const argument.
+                let expr = if let token::OpenDelim(token::Brace) = self.token.kind {
+                    self.parse_block_expr(
+                        None, self.token.span, BlockCheckMode::Default, ThinVec::new()
+                    )?
+                } else if self.token.is_ident() {
+                    // FIXME(const_generics): to distinguish between idents for types and consts,
+                    // we should introduce a GenericArg::Ident in the AST and distinguish when
+                    // lowering to the HIR. For now, idents for const args are not permitted.
+                    if self.token.is_keyword(kw::True) || self.token.is_keyword(kw::False) {
+                        self.parse_literal_maybe_minus()?
+                    } else {
+                        return Err(
+                            self.fatal("identifiers may currently not be used for const generics")
+                        );
+                    }
+                } else {
+                    self.parse_literal_maybe_minus()?
+                };
+                let value = AnonConst {
+                    id: ast::DUMMY_NODE_ID,
+                    value: expr,
+                };
+                args.push(GenericArg::Const(value));
+                misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints);
+            } else if self.check_type() {
+                // Parse type argument.
+                args.push(GenericArg::Type(self.parse_ty()?));
+                misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints);
+            } else {
+                break
+            }
+
+            if !self.eat(&token::Comma) {
+                break
+            }
+        }
+
+        // FIXME: we would like to report this in ast_validation instead, but we currently do not
+        // preserve ordering of generic parameters with respect to associated type binding, so we
+        // lose that information after parsing.
+        if misplaced_assoc_ty_constraints.len() > 0 {
+            let mut err = self.struct_span_err(
+                args_lo.to(self.prev_span),
+                "associated type bindings must be declared after generic parameters",
+            );
+            for span in misplaced_assoc_ty_constraints {
+                err.span_label(
+                    span,
+                    "this associated type binding should be moved after the generic parameters",
+                );
+            }
+            err.emit();
+        }
+
+        Ok((args, constraints))
+    }
+}
diff --git a/src/libsyntax/parse/parser/ty.rs b/src/libsyntax/parse/parser/ty.rs
new file mode 100644 (file)
index 0000000..a5a073c
--- /dev/null
@@ -0,0 +1,447 @@
+use super::{Parser, PResult, PathStyle, PrevTokenKind};
+
+use crate::{maybe_whole, maybe_recover_from_interpolated_ty_qpath};
+use crate::ptr::P;
+use crate::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam};
+use crate::ast::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef};
+use crate::ast::{Mutability, AnonConst, FnDecl, Mac_};
+use crate::parse::token::{self, Token};
+use crate::source_map::{respan, Span};
+use crate::symbol::{kw};
+
+use rustc_target::spec::abi::Abi;
+
+use errors::{Applicability};
+
+/// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
+/// `IDENT<<u8 as Trait>::AssocTy>`.
+///
+/// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes
+/// that `IDENT` is not the ident of a fn trait.
+fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
+    t == &token::ModSep || t == &token::Lt ||
+    t == &token::BinOp(token::Shl)
+}
+
+impl<'a> Parser<'a> {
+    /// Parses a type.
+    pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
+        self.parse_ty_common(true, true, false)
+    }
+
+    /// Parses a type in restricted contexts where `+` is not permitted.
+    ///
+    /// Example 1: `&'a TYPE`
+    ///     `+` is prohibited to maintain operator priority (P(+) < P(&)).
+    /// Example 2: `value1 as TYPE + value2`
+    ///     `+` is prohibited to avoid interactions with expression grammar.
+    pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
+        self.parse_ty_common(false, true, false)
+    }
+
+    /// Parses an optional return type `[ -> TY ]` in a function declaration.
+    pub(super) fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> {
+        if self.eat(&token::RArrow) {
+            Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true, false)?))
+        } else {
+            Ok(FunctionRetTy::Default(self.token.span.shrink_to_lo()))
+        }
+    }
+
+    pub(super) fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool,
+                       allow_c_variadic: bool) -> PResult<'a, P<Ty>> {
+        maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
+        maybe_whole!(self, NtTy, |x| x);
+
+        let lo = self.token.span;
+        let mut impl_dyn_multi = false;
+        let node = if self.eat(&token::OpenDelim(token::Paren)) {
+            // `(TYPE)` is a parenthesized type.
+            // `(TYPE,)` is a tuple with a single field of type TYPE.
+            let mut ts = vec![];
+            let mut last_comma = false;
+            while self.token != token::CloseDelim(token::Paren) {
+                ts.push(self.parse_ty()?);
+                if self.eat(&token::Comma) {
+                    last_comma = true;
+                } else {
+                    last_comma = false;
+                    break;
+                }
+            }
+            let trailing_plus = self.prev_token_kind == PrevTokenKind::Plus;
+            self.expect(&token::CloseDelim(token::Paren))?;
+
+            if ts.len() == 1 && !last_comma {
+                let ty = ts.into_iter().nth(0).unwrap().into_inner();
+                let maybe_bounds = allow_plus && self.token.is_like_plus();
+                match ty.node {
+                    // `(TY_BOUND_NOPAREN) + BOUND + ...`.
+                    TyKind::Path(None, ref path) if maybe_bounds => {
+                        self.parse_remaining_bounds(Vec::new(), path.clone(), lo, true)?
+                    }
+                    TyKind::TraitObject(ref bounds, TraitObjectSyntax::None)
+                            if maybe_bounds && bounds.len() == 1 && !trailing_plus => {
+                        let path = match bounds[0] {
+                            GenericBound::Trait(ref pt, ..) => pt.trait_ref.path.clone(),
+                            GenericBound::Outlives(..) => self.bug("unexpected lifetime bound"),
+                        };
+                        self.parse_remaining_bounds(Vec::new(), path, lo, true)?
+                    }
+                    // `(TYPE)`
+                    _ => TyKind::Paren(P(ty))
+                }
+            } else {
+                TyKind::Tup(ts)
+            }
+        } else if self.eat(&token::Not) {
+            // Never type `!`
+            TyKind::Never
+        } else if self.eat(&token::BinOp(token::Star)) {
+            // Raw pointer
+            TyKind::Ptr(self.parse_ptr()?)
+        } else if self.eat(&token::OpenDelim(token::Bracket)) {
+            // Array or slice
+            let t = self.parse_ty()?;
+            // Parse optional `; EXPR` in `[TYPE; EXPR]`
+            let t = match self.maybe_parse_fixed_length_of_vec()? {
+                None => TyKind::Slice(t),
+                Some(length) => TyKind::Array(t, AnonConst {
+                    id: ast::DUMMY_NODE_ID,
+                    value: length,
+                }),
+            };
+            self.expect(&token::CloseDelim(token::Bracket))?;
+            t
+        } else if self.check(&token::BinOp(token::And)) || self.check(&token::AndAnd) {
+            // Reference
+            self.expect_and()?;
+            self.parse_borrowed_pointee()?
+        } else if self.eat_keyword_noexpect(kw::Typeof) {
+            // `typeof(EXPR)`
+            // In order to not be ambiguous, the type must be surrounded by parens.
+            self.expect(&token::OpenDelim(token::Paren))?;
+            let e = AnonConst {
+                id: ast::DUMMY_NODE_ID,
+                value: self.parse_expr()?,
+            };
+            self.expect(&token::CloseDelim(token::Paren))?;
+            TyKind::Typeof(e)
+        } else if self.eat_keyword(kw::Underscore) {
+            // A type to be inferred `_`
+            TyKind::Infer
+        } else if self.token_is_bare_fn_keyword() {
+            // Function pointer type
+            self.parse_ty_bare_fn(Vec::new())?
+        } else if self.check_keyword(kw::For) {
+            // Function pointer type or bound list (trait object type) starting with a poly-trait.
+            //   `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
+            //   `for<'lt> Trait1<'lt> + Trait2 + 'a`
+            let lo = self.token.span;
+            let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
+            if self.token_is_bare_fn_keyword() {
+                self.parse_ty_bare_fn(lifetime_defs)?
+            } else {
+                let path = self.parse_path(PathStyle::Type)?;
+                let parse_plus = allow_plus && self.check_plus();
+                self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)?
+            }
+        } else if self.eat_keyword(kw::Impl) {
+            // Always parse bounds greedily for better error recovery.
+            let bounds = self.parse_generic_bounds(None)?;
+            impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
+            TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
+        } else if self.check_keyword(kw::Dyn) &&
+                  (self.token.span.rust_2018() ||
+                   self.look_ahead(1, |t| t.can_begin_bound() &&
+                                          !can_continue_type_after_non_fn_ident(t))) {
+            self.bump(); // `dyn`
+            // Always parse bounds greedily for better error recovery.
+            let bounds = self.parse_generic_bounds(None)?;
+            impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
+            TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
+        } else if self.check(&token::Question) ||
+                  self.check_lifetime() && self.look_ahead(1, |t| t.is_like_plus()) {
+            // Bound list (trait object type)
+            TyKind::TraitObject(self.parse_generic_bounds_common(allow_plus, None)?,
+                                TraitObjectSyntax::None)
+        } else if self.eat_lt() {
+            // Qualified path
+            let (qself, path) = self.parse_qpath(PathStyle::Type)?;
+            TyKind::Path(Some(qself), path)
+        } else if self.token.is_path_start() {
+            // Simple path
+            let path = self.parse_path(PathStyle::Type)?;
+            if self.eat(&token::Not) {
+                // Macro invocation in type position
+                let (delim, tts) = self.expect_delimited_token_tree()?;
+                let node = Mac_ {
+                    path,
+                    tts,
+                    delim,
+                    prior_type_ascription: self.last_type_ascription,
+                };
+                TyKind::Mac(respan(lo.to(self.prev_span), node))
+            } else {
+                // Just a type path or bound list (trait object type) starting with a trait.
+                //   `Type`
+                //   `Trait1 + Trait2 + 'a`
+                if allow_plus && self.check_plus() {
+                    self.parse_remaining_bounds(Vec::new(), path, lo, true)?
+                } else {
+                    TyKind::Path(None, path)
+                }
+            }
+        } else if self.check(&token::DotDotDot) {
+            if allow_c_variadic {
+                self.eat(&token::DotDotDot);
+                TyKind::CVarArgs
+            } else {
+                return Err(self.fatal(
+                    "only foreign functions are allowed to be C-variadic"
+                ));
+            }
+        } else {
+            let msg = format!("expected type, found {}", self.this_token_descr());
+            let mut err = self.fatal(&msg);
+            err.span_label(self.token.span, "expected type");
+            self.maybe_annotate_with_ascription(&mut err, true);
+            return Err(err);
+        };
+
+        let span = lo.to(self.prev_span);
+        let ty = P(Ty { node, span, id: ast::DUMMY_NODE_ID });
+
+        // Try to recover from use of `+` with incorrect priority.
+        self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty);
+        self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?;
+        self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)
+    }
+
+    fn parse_remaining_bounds(&mut self, generic_params: Vec<GenericParam>, path: ast::Path,
+                              lo: Span, parse_plus: bool) -> PResult<'a, TyKind> {
+        let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span));
+        let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
+        if parse_plus {
+            self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
+            bounds.append(&mut self.parse_generic_bounds(Some(self.prev_span))?);
+        }
+        Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
+    }
+
+    fn parse_ptr(&mut self) -> PResult<'a, MutTy> {
+        let mutbl = if self.eat_keyword(kw::Mut) {
+            Mutability::Mutable
+        } else if self.eat_keyword(kw::Const) {
+            Mutability::Immutable
+        } else {
+            let span = self.prev_span;
+            let msg = "expected mut or const in raw pointer type";
+            self.struct_span_err(span, msg)
+                .span_label(span, msg)
+                .help("use `*mut T` or `*const T` as appropriate")
+                .emit();
+            Mutability::Immutable
+        };
+        let t = self.parse_ty_no_plus()?;
+        Ok(MutTy { ty: t, mutbl })
+    }
+
+    fn maybe_parse_fixed_length_of_vec(&mut self) -> PResult<'a, Option<P<ast::Expr>>> {
+        if self.eat(&token::Semi) {
+            Ok(Some(self.parse_expr()?))
+        } else {
+            Ok(None)
+        }
+    }
+
+    fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
+        let opt_lifetime = if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
+        let mutbl = self.parse_mutability();
+        let ty = self.parse_ty_no_plus()?;
+        return Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl }));
+    }
+
+    /// Is the current token one of the keywords that signals a bare function type?
+    fn token_is_bare_fn_keyword(&mut self) -> bool {
+        self.check_keyword(kw::Fn) ||
+            self.check_keyword(kw::Unsafe) ||
+            self.check_keyword(kw::Extern)
+    }
+
+    /// Parses a `TyKind::BareFn` type.
+    fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a, TyKind> {
+        /*
+
+        [unsafe] [extern "ABI"] fn (S) -> T
+         ^~~~^           ^~~~^     ^~^    ^
+           |               |        |     |
+           |               |        |   Return type
+           |               |      Argument types
+           |               |
+           |              ABI
+        Function Style
+        */
+
+        let unsafety = self.parse_unsafety();
+        let abi = if self.eat_keyword(kw::Extern) {
+            self.parse_opt_abi()?.unwrap_or(Abi::C)
+        } else {
+            Abi::Rust
+        };
+
+        self.expect_keyword(kw::Fn)?;
+        let (inputs, c_variadic) = self.parse_fn_args(false, true)?;
+        let ret_ty = self.parse_ret_ty(false)?;
+        let decl = P(FnDecl {
+            inputs,
+            output: ret_ty,
+            c_variadic,
+        });
+        Ok(TyKind::BareFn(P(BareFnTy {
+            abi,
+            unsafety,
+            generic_params,
+            decl,
+        })))
+    }
+
+    crate fn parse_generic_bounds(&mut self,
+                                  colon_span: Option<Span>) -> PResult<'a, GenericBounds> {
+        self.parse_generic_bounds_common(true, colon_span)
+    }
+
+    /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`.
+    ///
+    /// ```
+    /// BOUND = TY_BOUND | LT_BOUND
+    /// LT_BOUND = LIFETIME (e.g., `'a`)
+    /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
+    /// TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g., `?for<'a: 'b> m::Trait<'a>`)
+    /// ```
+    fn parse_generic_bounds_common(&mut self,
+                                   allow_plus: bool,
+                                   colon_span: Option<Span>) -> PResult<'a, GenericBounds> {
+        let mut bounds = Vec::new();
+        let mut negative_bounds = Vec::new();
+        let mut last_plus_span = None;
+        let mut was_negative = false;
+        loop {
+            // This needs to be synchronized with `TokenKind::can_begin_bound`.
+            let is_bound_start = self.check_path() || self.check_lifetime() ||
+                                 self.check(&token::Not) || // used for error reporting only
+                                 self.check(&token::Question) ||
+                                 self.check_keyword(kw::For) ||
+                                 self.check(&token::OpenDelim(token::Paren));
+            if is_bound_start {
+                let lo = self.token.span;
+                let has_parens = self.eat(&token::OpenDelim(token::Paren));
+                let inner_lo = self.token.span;
+                let is_negative = self.eat(&token::Not);
+                let question = if self.eat(&token::Question) { Some(self.prev_span) } else { None };
+                if self.token.is_lifetime() {
+                    if let Some(question_span) = question {
+                        self.span_err(question_span,
+                                      "`?` may only modify trait bounds, not lifetime bounds");
+                    }
+                    bounds.push(GenericBound::Outlives(self.expect_lifetime()));
+                    if has_parens {
+                        let inner_span = inner_lo.to(self.prev_span);
+                        self.expect(&token::CloseDelim(token::Paren))?;
+                        let mut err = self.struct_span_err(
+                            lo.to(self.prev_span),
+                            "parenthesized lifetime bounds are not supported"
+                        );
+                        if let Ok(snippet) = self.span_to_snippet(inner_span) {
+                            err.span_suggestion_short(
+                                lo.to(self.prev_span),
+                                "remove the parentheses",
+                                snippet.to_owned(),
+                                Applicability::MachineApplicable
+                            );
+                        }
+                        err.emit();
+                    }
+                } else {
+                    let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
+                    let path = self.parse_path(PathStyle::Type)?;
+                    if has_parens {
+                        self.expect(&token::CloseDelim(token::Paren))?;
+                    }
+                    let poly_span = lo.to(self.prev_span);
+                    if is_negative {
+                        was_negative = true;
+                        if let Some(sp) = last_plus_span.or(colon_span) {
+                            negative_bounds.push(sp.to(poly_span));
+                        }
+                    } else {
+                        let poly_trait = PolyTraitRef::new(lifetime_defs, path, poly_span);
+                        let modifier = if question.is_some() {
+                            TraitBoundModifier::Maybe
+                        } else {
+                            TraitBoundModifier::None
+                        };
+                        bounds.push(GenericBound::Trait(poly_trait, modifier));
+                    }
+                }
+            } else {
+                break
+            }
+
+            if !allow_plus || !self.eat_plus() {
+                break
+            } else {
+                last_plus_span = Some(self.prev_span);
+            }
+        }
+
+        if !negative_bounds.is_empty() || was_negative {
+            let plural = negative_bounds.len() > 1;
+            let last_span = negative_bounds.last().map(|sp| *sp);
+            let mut err = self.struct_span_err(
+                negative_bounds,
+                "negative trait bounds are not supported",
+            );
+            if let Some(sp) = last_span {
+                err.span_label(sp, "negative trait bounds are not supported");
+            }
+            if let Some(bound_list) = colon_span {
+                let bound_list = bound_list.to(self.prev_span);
+                let mut new_bound_list = String::new();
+                if !bounds.is_empty() {
+                    let mut snippets = bounds.iter().map(|bound| bound.span())
+                        .map(|span| self.span_to_snippet(span));
+                    while let Some(Ok(snippet)) = snippets.next() {
+                        new_bound_list.push_str(" + ");
+                        new_bound_list.push_str(&snippet);
+                    }
+                    new_bound_list = new_bound_list.replacen(" +", ":", 1);
+                }
+                err.span_suggestion_hidden(
+                    bound_list,
+                    &format!("remove the trait bound{}", if plural { "s" } else { "" }),
+                    new_bound_list,
+                    Applicability::MachineApplicable,
+                );
+            }
+            err.emit();
+        }
+
+        return Ok(bounds);
+    }
+
+    // TODO remove super below.
+
+    pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
+        if self.eat_keyword(kw::For) {
+            self.expect_lt()?;
+            let params = self.parse_generic_params()?;
+            self.expect_gt()?;
+            // We rely on AST validation to rule out invalid cases: There must not be type
+            // parameters, and the lifetime parameters must not have bounds.
+            Ok(params)
+        } else {
+            Ok(Vec::new())
+        }
+    }
+}