]> git.lizzy.rs Git - rust.git/commitdiff
parser: move into generics.rs
authorMazdak Farrokhzad <twingoow@gmail.com>
Sun, 11 Aug 2019 18:44:09 +0000 (20:44 +0200)
committerMazdak Farrokhzad <twingoow@gmail.com>
Sun, 11 Aug 2019 18:44:09 +0000 (20:44 +0200)
src/libsyntax/parse/parser.rs
src/libsyntax/parse/parser/generics.rs [new file with mode: 0644]
src/libsyntax/parse/parser/ty.rs

index 182941406ab8b8995e041cbe3c5e39482f196b6c..afa475a4c8bf0ca08fdbdb3d3023a29f1784d7d7 100644 (file)
@@ -8,10 +8,10 @@
 mod path;
 pub use path::PathStyle;
 mod stmt;
+mod generics;
 
 use crate::ast::{self, AttrStyle, Attribute, Arg, BindingMode, StrStyle, SelfKind};
-use crate::ast::{FnDecl, Ident, IsAsync, Lifetime, MacDelimiter, Mutability};
-use crate::ast::{GenericParam, GenericParamKind, WhereClause, TyKind,  GenericBounds};
+use crate::ast::{FnDecl, Ident, IsAsync, Lifetime, MacDelimiter, Mutability, TyKind};
 use crate::ast::{Visibility, VisibilityKind, Unsafety, CrateSugar};
 use crate::ext::hygiene::SyntaxContext;
 use crate::source_map::{self, respan};
@@ -1205,249 +1205,6 @@ fn with_res<F, T>(&mut self, r: Restrictions, f: F) -> T
 
     }
 
-    /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
-    ///
-    /// ```
-    /// BOUND = LT_BOUND (e.g., `'a`)
-    /// ```
-    fn parse_lt_param_bounds(&mut self) -> GenericBounds {
-        let mut lifetimes = Vec::new();
-        while self.check_lifetime() {
-            lifetimes.push(ast::GenericBound::Outlives(self.expect_lifetime()));
-
-            if !self.eat_plus() {
-                break
-            }
-        }
-        lifetimes
-    }
-
-    /// Matches `typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?`.
-    fn parse_ty_param(&mut self,
-                      preceding_attrs: Vec<Attribute>)
-                      -> PResult<'a, GenericParam> {
-        let ident = self.parse_ident()?;
-
-        // Parse optional colon and param bounds.
-        let bounds = if self.eat(&token::Colon) {
-            self.parse_generic_bounds(Some(self.prev_span))?
-        } else {
-            Vec::new()
-        };
-
-        let default = if self.eat(&token::Eq) {
-            Some(self.parse_ty()?)
-        } else {
-            None
-        };
-
-        Ok(GenericParam {
-            ident,
-            id: ast::DUMMY_NODE_ID,
-            attrs: preceding_attrs.into(),
-            bounds,
-            kind: GenericParamKind::Type {
-                default,
-            }
-        })
-    }
-
-    fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, GenericParam> {
-        self.expect_keyword(kw::Const)?;
-        let ident = self.parse_ident()?;
-        self.expect(&token::Colon)?;
-        let ty = self.parse_ty()?;
-
-        Ok(GenericParam {
-            ident,
-            id: ast::DUMMY_NODE_ID,
-            attrs: preceding_attrs.into(),
-            bounds: Vec::new(),
-            kind: GenericParamKind::Const {
-                ty,
-            }
-        })
-    }
-
-    /// Parses a (possibly empty) list of lifetime and type parameters, possibly including
-    /// a trailing comma and erroneous trailing attributes.
-    crate fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericParam>> {
-        let mut params = Vec::new();
-        loop {
-            let attrs = self.parse_outer_attributes()?;
-            if self.check_lifetime() {
-                let lifetime = self.expect_lifetime();
-                // Parse lifetime parameter.
-                let bounds = if self.eat(&token::Colon) {
-                    self.parse_lt_param_bounds()
-                } else {
-                    Vec::new()
-                };
-                params.push(ast::GenericParam {
-                    ident: lifetime.ident,
-                    id: lifetime.id,
-                    attrs: attrs.into(),
-                    bounds,
-                    kind: ast::GenericParamKind::Lifetime,
-                });
-            } else if self.check_keyword(kw::Const) {
-                // Parse const parameter.
-                params.push(self.parse_const_param(attrs)?);
-            } else if self.check_ident() {
-                // Parse type parameter.
-                params.push(self.parse_ty_param(attrs)?);
-            } else {
-                // Check for trailing attributes and stop parsing.
-                if !attrs.is_empty() {
-                    if !params.is_empty() {
-                        self.struct_span_err(
-                            attrs[0].span,
-                            &format!("trailing attribute after generic parameter"),
-                        )
-                        .span_label(attrs[0].span, "attributes must go before parameters")
-                        .emit();
-                    } else {
-                        self.struct_span_err(
-                            attrs[0].span,
-                            &format!("attribute without generic parameters"),
-                        )
-                        .span_label(
-                            attrs[0].span,
-                            "attributes are only permitted when preceding parameters",
-                        )
-                        .emit();
-                    }
-                }
-                break
-            }
-
-            if !self.eat(&token::Comma) {
-                break
-            }
-        }
-        Ok(params)
-    }
-
-    /// Parses a set of optional generic type parameter declarations. Where
-    /// clauses are not parsed here, and must be added later via
-    /// `parse_where_clause()`.
-    ///
-    /// matches generics = ( ) | ( < > ) | ( < typaramseq ( , )? > ) | ( < lifetimes ( , )? > )
-    ///                  | ( < lifetimes , typaramseq ( , )? > )
-    /// where   typaramseq = ( typaram ) | ( typaram , typaramseq )
-    fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
-        let span_lo = self.token.span;
-        let (params, span) = if self.eat_lt() {
-            let params = self.parse_generic_params()?;
-            self.expect_gt()?;
-            (params, span_lo.to(self.prev_span))
-        } else {
-            (vec![], self.prev_span.between(self.token.span))
-        };
-        Ok(ast::Generics {
-            params,
-            where_clause: WhereClause {
-                predicates: Vec::new(),
-                span: DUMMY_SP,
-            },
-            span,
-        })
-    }
-
-    /// Parses an optional where-clause and places it in `generics`.
-    ///
-    /// ```ignore (only-for-syntax-highlight)
-    /// where T : Trait<U, V> + 'b, 'a : 'b
-    /// ```
-    fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
-        let mut where_clause = WhereClause {
-            predicates: Vec::new(),
-            span: self.prev_span.to(self.prev_span),
-        };
-
-        if !self.eat_keyword(kw::Where) {
-            return Ok(where_clause);
-        }
-        let lo = self.prev_span;
-
-        // We are considering adding generics to the `where` keyword as an alternative higher-rank
-        // parameter syntax (as in `where<'a>` or `where<T>`. To avoid that being a breaking
-        // change we parse those generics now, but report an error.
-        if self.choose_generics_over_qpath() {
-            let generics = self.parse_generics()?;
-            self.struct_span_err(
-                generics.span,
-                "generic parameters on `where` clauses are reserved for future use",
-            )
-                .span_label(generics.span, "currently unsupported")
-                .emit();
-        }
-
-        loop {
-            let lo = self.token.span;
-            if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
-                let lifetime = self.expect_lifetime();
-                // Bounds starting with a colon are mandatory, but possibly empty.
-                self.expect(&token::Colon)?;
-                let bounds = self.parse_lt_param_bounds();
-                where_clause.predicates.push(ast::WherePredicate::RegionPredicate(
-                    ast::WhereRegionPredicate {
-                        span: lo.to(self.prev_span),
-                        lifetime,
-                        bounds,
-                    }
-                ));
-            } else if self.check_type() {
-                // Parse optional `for<'a, 'b>`.
-                // This `for` is parsed greedily and applies to the whole predicate,
-                // the bounded type can have its own `for` applying only to it.
-                // Examples:
-                // * `for<'a> Trait1<'a>: Trait2<'a /* ok */>`
-                // * `(for<'a> Trait1<'a>): Trait2<'a /* not ok */>`
-                // * `for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /* ok */, 'b /* not ok */>`
-                let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
-
-                // Parse type with mandatory colon and (possibly empty) bounds,
-                // or with mandatory equality sign and the second type.
-                let ty = self.parse_ty()?;
-                if self.eat(&token::Colon) {
-                    let bounds = self.parse_generic_bounds(Some(self.prev_span))?;
-                    where_clause.predicates.push(ast::WherePredicate::BoundPredicate(
-                        ast::WhereBoundPredicate {
-                            span: lo.to(self.prev_span),
-                            bound_generic_params: lifetime_defs,
-                            bounded_ty: ty,
-                            bounds,
-                        }
-                    ));
-                // FIXME: Decide what should be used here, `=` or `==`.
-                // FIXME: We are just dropping the binders in lifetime_defs on the floor here.
-                } else if self.eat(&token::Eq) || self.eat(&token::EqEq) {
-                    let rhs_ty = self.parse_ty()?;
-                    where_clause.predicates.push(ast::WherePredicate::EqPredicate(
-                        ast::WhereEqPredicate {
-                            span: lo.to(self.prev_span),
-                            lhs_ty: ty,
-                            rhs_ty,
-                            id: ast::DUMMY_NODE_ID,
-                        }
-                    ));
-                } else {
-                    return self.unexpected();
-                }
-            } else {
-                break
-            }
-
-            if !self.eat(&token::Comma) {
-                break
-            }
-        }
-
-        where_clause.span = lo.to(self.prev_span);
-        Ok(where_clause)
-    }
-
     fn parse_fn_args(&mut self, named_args: bool, allow_c_variadic: bool)
                      -> PResult<'a, (Vec<Arg> , bool)> {
         let sp = self.token.span;
@@ -1671,31 +1428,6 @@ fn parse_fn_decl_with_self<F>(&mut self, parse_arg_fn: F) -> PResult<'a, P<FnDec
         }))
     }
 
-    fn choose_generics_over_qpath(&self) -> bool {
-        // There's an ambiguity between generic parameters and qualified paths in impls.
-        // If we see `<` it may start both, so we have to inspect some following tokens.
-        // The following combinations can only start generics,
-        // but not qualified paths (with one exception):
-        //     `<` `>` - empty generic parameters
-        //     `<` `#` - generic parameters with attributes
-        //     `<` (LIFETIME|IDENT) `>` - single generic parameter
-        //     `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
-        //     `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
-        //     `<` (LIFETIME|IDENT) `=` - generic parameter with a default
-        //     `<` const                - generic const parameter
-        // The only truly ambiguous case is
-        //     `<` IDENT `>` `::` IDENT ...
-        // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
-        // because this is what almost always expected in practice, qualified paths in impls
-        // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
-        self.token == token::Lt &&
-            (self.look_ahead(1, |t| t == &token::Pound || t == &token::Gt) ||
-             self.look_ahead(1, |t| t.is_lifetime() || t.is_ident()) &&
-                self.look_ahead(2, |t| t == &token::Gt || t == &token::Comma ||
-                                       t == &token::Colon || t == &token::Eq) ||
-            self.is_keyword_ahead(1, &[kw::Const]))
-    }
-
     fn is_crate_vis(&self) -> bool {
         self.token.is_keyword(kw::Crate) && self.look_ahead(1, |t| t != &token::ModSep)
     }
diff --git a/src/libsyntax/parse/parser/generics.rs b/src/libsyntax/parse/parser/generics.rs
new file mode 100644 (file)
index 0000000..54f24f8
--- /dev/null
@@ -0,0 +1,276 @@
+use super::{Parser, PResult};
+
+use crate::ast::{self, WhereClause, GenericParam, GenericParamKind, GenericBounds, Attribute};
+use crate::parse::token;
+use crate::source_map::DUMMY_SP;
+use crate::symbol::kw;
+
+impl<'a> Parser<'a> {
+    /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
+    ///
+    /// ```
+    /// BOUND = LT_BOUND (e.g., `'a`)
+    /// ```
+    fn parse_lt_param_bounds(&mut self) -> GenericBounds {
+        let mut lifetimes = Vec::new();
+        while self.check_lifetime() {
+            lifetimes.push(ast::GenericBound::Outlives(self.expect_lifetime()));
+
+            if !self.eat_plus() {
+                break
+            }
+        }
+        lifetimes
+    }
+
+    /// Matches `typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?`.
+    fn parse_ty_param(&mut self,
+                      preceding_attrs: Vec<Attribute>)
+                      -> PResult<'a, GenericParam> {
+        let ident = self.parse_ident()?;
+
+        // Parse optional colon and param bounds.
+        let bounds = if self.eat(&token::Colon) {
+            self.parse_generic_bounds(Some(self.prev_span))?
+        } else {
+            Vec::new()
+        };
+
+        let default = if self.eat(&token::Eq) {
+            Some(self.parse_ty()?)
+        } else {
+            None
+        };
+
+        Ok(GenericParam {
+            ident,
+            id: ast::DUMMY_NODE_ID,
+            attrs: preceding_attrs.into(),
+            bounds,
+            kind: GenericParamKind::Type {
+                default,
+            }
+        })
+    }
+
+    fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, GenericParam> {
+        self.expect_keyword(kw::Const)?;
+        let ident = self.parse_ident()?;
+        self.expect(&token::Colon)?;
+        let ty = self.parse_ty()?;
+
+        Ok(GenericParam {
+            ident,
+            id: ast::DUMMY_NODE_ID,
+            attrs: preceding_attrs.into(),
+            bounds: Vec::new(),
+            kind: GenericParamKind::Const {
+                ty,
+            }
+        })
+    }
+
+    /// Parses a (possibly empty) list of lifetime and type parameters, possibly including
+    /// a trailing comma and erroneous trailing attributes.
+    crate fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericParam>> {
+        let mut params = Vec::new();
+        loop {
+            let attrs = self.parse_outer_attributes()?;
+            if self.check_lifetime() {
+                let lifetime = self.expect_lifetime();
+                // Parse lifetime parameter.
+                let bounds = if self.eat(&token::Colon) {
+                    self.parse_lt_param_bounds()
+                } else {
+                    Vec::new()
+                };
+                params.push(ast::GenericParam {
+                    ident: lifetime.ident,
+                    id: lifetime.id,
+                    attrs: attrs.into(),
+                    bounds,
+                    kind: ast::GenericParamKind::Lifetime,
+                });
+            } else if self.check_keyword(kw::Const) {
+                // Parse const parameter.
+                params.push(self.parse_const_param(attrs)?);
+            } else if self.check_ident() {
+                // Parse type parameter.
+                params.push(self.parse_ty_param(attrs)?);
+            } else {
+                // Check for trailing attributes and stop parsing.
+                if !attrs.is_empty() {
+                    if !params.is_empty() {
+                        self.struct_span_err(
+                            attrs[0].span,
+                            &format!("trailing attribute after generic parameter"),
+                        )
+                        .span_label(attrs[0].span, "attributes must go before parameters")
+                        .emit();
+                    } else {
+                        self.struct_span_err(
+                            attrs[0].span,
+                            &format!("attribute without generic parameters"),
+                        )
+                        .span_label(
+                            attrs[0].span,
+                            "attributes are only permitted when preceding parameters",
+                        )
+                        .emit();
+                    }
+                }
+                break
+            }
+
+            if !self.eat(&token::Comma) {
+                break
+            }
+        }
+        Ok(params)
+    }
+
+    /// Parses a set of optional generic type parameter declarations. Where
+    /// clauses are not parsed here, and must be added later via
+    /// `parse_where_clause()`.
+    ///
+    /// matches generics = ( ) | ( < > ) | ( < typaramseq ( , )? > ) | ( < lifetimes ( , )? > )
+    ///                  | ( < lifetimes , typaramseq ( , )? > )
+    /// where   typaramseq = ( typaram ) | ( typaram , typaramseq )
+    pub(super) fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
+        let span_lo = self.token.span;
+        let (params, span) = if self.eat_lt() {
+            let params = self.parse_generic_params()?;
+            self.expect_gt()?;
+            (params, span_lo.to(self.prev_span))
+        } else {
+            (vec![], self.prev_span.between(self.token.span))
+        };
+        Ok(ast::Generics {
+            params,
+            where_clause: WhereClause {
+                predicates: Vec::new(),
+                span: DUMMY_SP,
+            },
+            span,
+        })
+    }
+
+    /// Parses an optional where-clause and places it in `generics`.
+    ///
+    /// ```ignore (only-for-syntax-highlight)
+    /// where T : Trait<U, V> + 'b, 'a : 'b
+    /// ```
+    pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
+        let mut where_clause = WhereClause {
+            predicates: Vec::new(),
+            span: self.prev_span.to(self.prev_span),
+        };
+
+        if !self.eat_keyword(kw::Where) {
+            return Ok(where_clause);
+        }
+        let lo = self.prev_span;
+
+        // We are considering adding generics to the `where` keyword as an alternative higher-rank
+        // parameter syntax (as in `where<'a>` or `where<T>`. To avoid that being a breaking
+        // change we parse those generics now, but report an error.
+        if self.choose_generics_over_qpath() {
+            let generics = self.parse_generics()?;
+            self.struct_span_err(
+                generics.span,
+                "generic parameters on `where` clauses are reserved for future use",
+            )
+                .span_label(generics.span, "currently unsupported")
+                .emit();
+        }
+
+        loop {
+            let lo = self.token.span;
+            if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
+                let lifetime = self.expect_lifetime();
+                // Bounds starting with a colon are mandatory, but possibly empty.
+                self.expect(&token::Colon)?;
+                let bounds = self.parse_lt_param_bounds();
+                where_clause.predicates.push(ast::WherePredicate::RegionPredicate(
+                    ast::WhereRegionPredicate {
+                        span: lo.to(self.prev_span),
+                        lifetime,
+                        bounds,
+                    }
+                ));
+            } else if self.check_type() {
+                // Parse optional `for<'a, 'b>`.
+                // This `for` is parsed greedily and applies to the whole predicate,
+                // the bounded type can have its own `for` applying only to it.
+                // Examples:
+                // * `for<'a> Trait1<'a>: Trait2<'a /* ok */>`
+                // * `(for<'a> Trait1<'a>): Trait2<'a /* not ok */>`
+                // * `for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /* ok */, 'b /* not ok */>`
+                let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
+
+                // Parse type with mandatory colon and (possibly empty) bounds,
+                // or with mandatory equality sign and the second type.
+                let ty = self.parse_ty()?;
+                if self.eat(&token::Colon) {
+                    let bounds = self.parse_generic_bounds(Some(self.prev_span))?;
+                    where_clause.predicates.push(ast::WherePredicate::BoundPredicate(
+                        ast::WhereBoundPredicate {
+                            span: lo.to(self.prev_span),
+                            bound_generic_params: lifetime_defs,
+                            bounded_ty: ty,
+                            bounds,
+                        }
+                    ));
+                // FIXME: Decide what should be used here, `=` or `==`.
+                // FIXME: We are just dropping the binders in lifetime_defs on the floor here.
+                } else if self.eat(&token::Eq) || self.eat(&token::EqEq) {
+                    let rhs_ty = self.parse_ty()?;
+                    where_clause.predicates.push(ast::WherePredicate::EqPredicate(
+                        ast::WhereEqPredicate {
+                            span: lo.to(self.prev_span),
+                            lhs_ty: ty,
+                            rhs_ty,
+                            id: ast::DUMMY_NODE_ID,
+                        }
+                    ));
+                } else {
+                    return self.unexpected();
+                }
+            } else {
+                break
+            }
+
+            if !self.eat(&token::Comma) {
+                break
+            }
+        }
+
+        where_clause.span = lo.to(self.prev_span);
+        Ok(where_clause)
+    }
+
+    pub(super) fn choose_generics_over_qpath(&self) -> bool {
+        // There's an ambiguity between generic parameters and qualified paths in impls.
+        // If we see `<` it may start both, so we have to inspect some following tokens.
+        // The following combinations can only start generics,
+        // but not qualified paths (with one exception):
+        //     `<` `>` - empty generic parameters
+        //     `<` `#` - generic parameters with attributes
+        //     `<` (LIFETIME|IDENT) `>` - single generic parameter
+        //     `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
+        //     `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
+        //     `<` (LIFETIME|IDENT) `=` - generic parameter with a default
+        //     `<` const                - generic const parameter
+        // The only truly ambiguous case is
+        //     `<` IDENT `>` `::` IDENT ...
+        // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
+        // because this is what almost always expected in practice, qualified paths in impls
+        // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
+        self.token == token::Lt &&
+            (self.look_ahead(1, |t| t == &token::Pound || t == &token::Gt) ||
+             self.look_ahead(1, |t| t.is_lifetime() || t.is_ident()) &&
+                self.look_ahead(2, |t| t == &token::Gt || t == &token::Comma ||
+                                       t == &token::Colon || t == &token::Eq) ||
+            self.is_keyword_ahead(1, &[kw::Const]))
+    }
+}
index a5a073c3af1a9f952b58b05ecc2d9c1f2f3d588d..e01ce9a48c0dd887041541c6ce6e34a07a71dc9c 100644 (file)
@@ -430,8 +430,6 @@ fn parse_generic_bounds_common(&mut self,
         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()?;