about summary refs log tree commit diff
path: root/src/libsyntax/parse/parser.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-06-06 03:56:22 +0000
committerbors <bors@rust-lang.org>2019-06-06 03:56:22 +0000
commit740668dbd99dbf1726bbb0cca6cd0943ea2f7e27 (patch)
tree7fcf783b5f92803e8ca4985eaa24097e76b6192c /src/libsyntax/parse/parser.rs
parent1bec46c9a5399d5e95c05e3428c3abd264780705 (diff)
parentee890331f6e33afe12ef250eb6388db2aab7cbbf (diff)
downloadrust-740668dbd99dbf1726bbb0cca6cd0943ea2f7e27.tar.gz
rust-740668dbd99dbf1726bbb0cca6cd0943ea2f7e27.zip
Auto merge of #57428 - alexreg:associated_type_bounds, r=nikomatsakis,Centril
Implementation of RFC 2289 (associated_type_bounds)

This PR implements the [`asociated_type_bounds` feature](https://github.com/rust-lang/rfcs/blob/master/text/2289-associated-type-bounds.md).

Associated type bounds are implemented in:
   - function/method arguments and return types
   - structs, enums, unions
   - associated items in traits
   - type aliases
   - type parameter defaults
   - trait objects
   - let bindings

CC @nikomatsakis @centril
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
-rw-r--r--src/libsyntax/parse/parser.rs110
1 files changed, 60 insertions, 50 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 39fcd29e1b0..790013f6eb1 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -27,7 +27,7 @@ use crate::ast::{VariantData, StructField};
 use crate::ast::StrStyle;
 use crate::ast::SelfKind;
 use crate::ast::{TraitItem, TraitRef, TraitObjectSyntax};
-use crate::ast::{Ty, TyKind, TypeBinding, GenericBounds};
+use crate::ast::{Ty, TyKind, AssocTyConstraint, AssocTyConstraintKind, GenericBounds};
 use crate::ast::{Visibility, VisibilityKind, WhereClause, CrateSugar};
 use crate::ast::{UseTree, UseTreeKind};
 use crate::ast::{BinOpKind, UnOp};
@@ -191,24 +191,24 @@ enum PrevTokenKind {
     Other,
 }
 
-/* ident is handled by common.rs */
+// NOTE: `Ident`s are handled by `common.rs`.
 
 #[derive(Clone)]
 pub struct Parser<'a> {
     pub sess: &'a ParseSess,
-    /// the current token:
+    /// The current token.
     pub token: token::Token,
-    /// the span of the current token:
+    /// The span of the current token.
     pub span: Span,
-    /// the span of the previous token:
     meta_var_span: Option<Span>,
+    /// The span of the previous token.
     pub prev_span: Span,
-    /// the previous token kind
+    /// The kind of the previous troken.
     prev_token_kind: PrevTokenKind,
     restrictions: Restrictions,
-    /// Used to determine the path to externally loaded source files
+    /// Used to determine the path to externally loaded source files.
     crate directory: Directory<'a>,
-    /// Whether to parse sub-modules in other files.
+    /// `true` to parse sub-modules in other files.
     pub recurse_into_file_modules: bool,
     /// Name of the root module this parser originated from. If `None`, then the
     /// name is not known. This does not change while the parser is descending
@@ -217,7 +217,7 @@ pub struct Parser<'a> {
     crate expected_tokens: Vec<TokenType>,
     crate token_cursor: TokenCursor,
     desugar_doc_comments: bool,
-    /// Whether we should configure out of line modules as we parse.
+    /// `true` we should configure out of line modules as we parse.
     pub cfg_mods: bool,
     /// This field is used to keep track of how many left angle brackets we have seen. This is
     /// required in order to detect extra leading left angle brackets (`<` characters) and error
@@ -1791,11 +1791,11 @@ impl<'a> Parser<'a> {
             let lo = self.span;
             let args = if self.eat_lt() {
                 // `<'a, T, A = U>`
-                let (args, bindings) =
+                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, bindings, span }.into()
+                AngleBracketedArgs { args, constraints, span }.into()
             } else {
                 // `(T, U) -> R`
                 self.bump(); // `(`
@@ -2680,8 +2680,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    // parse a stream of tokens into a list of TokenTree's,
-    // up to EOF.
+    /// Parses a stream of tokens into a list of `TokenTree`s, up to EOF.
     pub fn parse_all_token_trees(&mut self) -> PResult<'a, Vec<TokenTree>> {
         let mut tts = Vec::new();
         while self.token != token::Eof {
@@ -5077,7 +5076,7 @@ impl<'a> Parser<'a> {
         &mut self,
         style: PathStyle,
         lo: Span,
-    ) -> PResult<'a, (Vec<GenericArg>, Vec<TypeBinding>)> {
+    ) -> 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
@@ -5212,11 +5211,11 @@ impl<'a> Parser<'a> {
 
     /// 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<TypeBinding>)> {
+    fn parse_generic_args(&mut self) -> PResult<'a, (Vec<GenericArg>, Vec<AssocTyConstraint>)> {
         let mut args = Vec::new();
-        let mut bindings = Vec::new();
-        let mut misplaced_assoc_ty_bindings: Vec<Span> = Vec::new();
-        let mut assoc_ty_bindings: Vec<Span> = 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.span;
 
@@ -5224,21 +5223,31 @@ impl<'a> Parser<'a> {
             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_bindings.append(&mut assoc_ty_bindings);
-            } else if self.check_ident() && self.look_ahead(1, |t| t == &token::Eq) {
-                // Parse associated type binding.
+                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.span;
                 let ident = self.parse_ident()?;
-                self.bump();
-                let ty = self.parse_ty()?;
+                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);
-                bindings.push(TypeBinding {
+                constraints.push(AssocTyConstraint {
                     id: ast::DUMMY_NODE_ID,
                     ident,
-                    ty,
+                    kind,
                     span,
                 });
-                assoc_ty_bindings.push(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 {
@@ -5262,11 +5271,11 @@ impl<'a> Parser<'a> {
                     value: expr,
                 };
                 args.push(GenericArg::Const(value));
-                misplaced_assoc_ty_bindings.append(&mut assoc_ty_bindings);
+                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_bindings.append(&mut assoc_ty_bindings);
+                misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints);
             } else {
                 break
             }
@@ -5279,12 +5288,12 @@ impl<'a> Parser<'a> {
         // 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_bindings.len() > 0 {
+        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_bindings {
+            for span in misplaced_assoc_ty_constraints {
                 err.span_label(
                     span,
                     "this associated type binding should be moved after the generic parameters",
@@ -5293,7 +5302,7 @@ impl<'a> Parser<'a> {
             err.emit();
         }
 
-        Ok((args, bindings))
+        Ok((args, constraints))
     }
 
     /// Parses an optional where-clause and places it in `generics`.
@@ -5344,9 +5353,10 @@ impl<'a> Parser<'a> {
                 // 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.
-                // Example 1: for<'a> Trait1<'a>: Trait2<'a /*ok*/>
-                // Example 2: (for<'a> Trait1<'a>): Trait2<'a /*not ok*/>
-                // Example 3: for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /*ok*/, 'b /*not ok*/>
+                // 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,
@@ -5478,17 +5488,17 @@ impl<'a> Parser<'a> {
             this.look_ahead(n + 1, |t| t != &token::ModSep)
         };
 
-        // Parse optional self parameter of a method.
-        // Only a limited set of initial token sequences is considered self parameters, anything
+        // Parse optional `self` parameter of a method.
+        // Only a limited set of initial token sequences is considered `self` parameters; anything
         // else is parsed as a normal function parameter list, so some lookahead is required.
         let eself_lo = self.span;
         let (eself, eself_ident, eself_hi) = match self.token {
             token::BinOp(token::And) => {
-                // &self
-                // &mut self
-                // &'lt self
-                // &'lt mut self
-                // &not_self
+                // `&self`
+                // `&mut self`
+                // `&'lt self`
+                // `&'lt mut self`
+                // `&not_self`
                 (if isolated_self(self, 1) {
                     self.bump();
                     SelfKind::Region(None, Mutability::Immutable)
@@ -5514,10 +5524,10 @@ impl<'a> Parser<'a> {
                 }, expect_ident(self), self.prev_span)
             }
             token::BinOp(token::Star) => {
-                // *self
-                // *const self
-                // *mut self
-                // *not_self
+                // `*self`
+                // `*const self`
+                // `*mut self`
+                // `*not_self`
                 // Emit special error for `self` cases.
                 let msg = "cannot pass `self` by raw pointer";
                 (if isolated_self(self, 1) {
@@ -5540,8 +5550,8 @@ impl<'a> Parser<'a> {
             }
             token::Ident(..) => {
                 if isolated_self(self, 0) {
-                    // self
-                    // self: TYPE
+                    // `self`
+                    // `self: TYPE`
                     let eself_ident = expect_ident(self);
                     let eself_hi = self.prev_span;
                     (if self.eat(&token::Colon) {
@@ -5552,8 +5562,8 @@ impl<'a> Parser<'a> {
                     }, eself_ident, eself_hi)
                 } else if self.token.is_keyword(kw::Mut) &&
                           isolated_self(self, 1) {
-                    // mut self
-                    // mut self: TYPE
+                    // `mut self`
+                    // `mut self: TYPE`
                     self.bump();
                     let eself_ident = expect_ident(self);
                     let eself_hi = self.prev_span;
@@ -5580,7 +5590,7 @@ impl<'a> Parser<'a> {
     {
         self.expect(&token::OpenDelim(token::Paren))?;
 
-        // Parse optional self argument
+        // Parse optional self argument.
         let self_arg = self.parse_self_arg()?;
 
         // Parse the rest of the function parameter list.