diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2017-04-05 01:12:53 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2017-04-21 21:32:44 +0300 |
| commit | e038f58105cc1769a9c7991981822d01ebffe277 (patch) | |
| tree | 1aa398de845539946c8c16f7fd3f622aa7e49111 /src/libsyntax/parse/parser.rs | |
| parent | 5695c3e9435a5872e23a6bb61c1ea0b3ada83eef (diff) | |
| download | rust-e038f58105cc1769a9c7991981822d01ebffe277.tar.gz rust-e038f58105cc1769a9c7991981822d01ebffe277.zip | |
syntax: Support parentheses around trait bounds
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 0cdb09a842f..1232411d1ec 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -152,6 +152,7 @@ fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>) enum PrevTokenKind { DocComment, Comma, + Plus, Interpolated, Eof, Other, @@ -1061,6 +1062,7 @@ impl<'a> Parser<'a> { self.prev_token_kind = match self.token { token::DocComment(..) => PrevTokenKind::DocComment, token::Comma => PrevTokenKind::Comma, + token::BinOp(token::Plus) => PrevTokenKind::Plus, token::Interpolated(..) => PrevTokenKind::Interpolated, token::Eof => PrevTokenKind::Eof, _ => PrevTokenKind::Other, @@ -1354,20 +1356,29 @@ impl<'a> Parser<'a> { 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().unwrap(); + let maybe_bounds = allow_plus && self.token == token::BinOp(token::Plus); match ty.node { - // Accept `(Trait1) + Trait2 + 'a` for backward compatibility (#39318). - TyKind::Path(None, ref path) - if allow_plus && self.token == token::BinOp(token::Plus) => { + // `(TY_BOUND_NOPAREN) + BOUND + ...`. + TyKind::Path(None, ref path) if maybe_bounds => { self.bump(); // `+` let pt = PolyTraitRef::new(Vec::new(), path.clone(), lo.to(self.prev_span)); let mut bounds = vec![TraitTyParamBound(pt, TraitBoundModifier::None)]; bounds.append(&mut self.parse_ty_param_bounds()?); TyKind::TraitObject(bounds) } + TyKind::TraitObject(ref bounds) + if maybe_bounds && bounds.len() == 1 && !trailing_plus => { + self.bump(); // `+` + let mut bounds = bounds.clone(); + bounds.append(&mut self.parse_ty_param_bounds()?); + TyKind::TraitObject(bounds) + } + // `(TYPE)` _ => TyKind::Paren(P(ty)) } } else { @@ -4070,10 +4081,12 @@ impl<'a> Parser<'a> { // Parse bounds of a type parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`. // BOUND = TY_BOUND | LT_BOUND // LT_BOUND = LIFETIME (e.g. `'a`) - // TY_BOUND = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g. `?for<'a: 'b> m::Trait<'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_ty_param_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, TyParamBounds> { let mut bounds = Vec::new(); loop { + let has_parens = self.eat(&token::OpenDelim(token::Paren)); let question = if self.eat(&token::Question) { Some(self.prev_span) } else { None }; if self.check_lifetime() { if let Some(question_span) = question { @@ -4081,6 +4094,11 @@ impl<'a> Parser<'a> { "`?` may only modify trait bounds, not lifetime bounds"); } bounds.push(RegionTyParamBound(self.expect_lifetime())); + if has_parens { + self.expect(&token::CloseDelim(token::Paren))?; + self.span_err(self.prev_span, + "parenthesized lifetime bounds are not supported"); + } } else if self.check_keyword(keywords::For) || self.check_path() { let lo = self.span; let lifetime_defs = self.parse_late_bound_lifetime_defs()?; @@ -4092,6 +4110,9 @@ impl<'a> Parser<'a> { TraitBoundModifier::None }; bounds.push(TraitTyParamBound(poly_trait, modifier)); + if has_parens { + self.expect(&token::CloseDelim(token::Paren))?; + } } else { break } |
