diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2017-04-21 00:19:06 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2017-04-21 21:32:44 +0300 |
| commit | 6e75def7dba6ee28660b8479f0ede72986c299f7 (patch) | |
| tree | 3fb0cfafe35d43056786593e5593c74bb76a9fbd | |
| parent | e038f58105cc1769a9c7991981822d01ebffe277 (diff) | |
| download | rust-6e75def7dba6ee28660b8479f0ede72986c299f7.tar.gz rust-6e75def7dba6ee28660b8479f0ede72986c299f7.zip | |
Fix issue with single question mark or paren
| -rw-r--r-- | src/doc/grammar.md | 5 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 51 | ||||
| -rw-r--r-- | src/test/parse-fail/bound-single-question-mark.rs | 13 |
3 files changed, 44 insertions, 25 deletions
diff --git a/src/doc/grammar.md b/src/doc/grammar.md index 3fbf9f06d99..12daa24e857 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -781,10 +781,11 @@ never_type : "!" ; ### Type parameter bounds ```antlr +bound-list := bound | bound '+' bound-list '+' ? bound := ty_bound | lt_bound lt_bound := lifetime -ty_bound := [?] [ for<lt_param_defs> ] simple_path -bound-list := bound | bound '+' bound-list '+' ? +ty_bound := ty_bound_noparen | (ty_bound_noparen) +ty_bound_noparen := [?] [ for<lt_param_defs> ] simple_path ``` ### Self types diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1232411d1ec..79ae1d62915 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4086,32 +4086,37 @@ impl<'a> Parser<'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 { - self.span_err(question_span, - "`?` 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()?; - let path = self.parse_path(PathStyle::Type)?; - let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_span)); - let modifier = if question.is_some() { - TraitBoundModifier::Maybe + let is_bound_start = self.check_path() || self.check_lifetime() || + self.check(&token::Question) || + self.check_keyword(keywords::For) || + self.check(&token::OpenDelim(token::Paren)); + if is_bound_start { + let has_parens = self.eat(&token::OpenDelim(token::Paren)); + 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(RegionTyParamBound(self.expect_lifetime())); } else { - TraitBoundModifier::None - }; - bounds.push(TraitTyParamBound(poly_trait, modifier)); + let lo = self.span; + let lifetime_defs = self.parse_late_bound_lifetime_defs()?; + let path = self.parse_path(PathStyle::Type)?; + let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_span)); + let modifier = if question.is_some() { + TraitBoundModifier::Maybe + } else { + TraitBoundModifier::None + }; + bounds.push(TraitTyParamBound(poly_trait, modifier)); + } if has_parens { self.expect(&token::CloseDelim(token::Paren))?; + if let Some(&RegionTyParamBound(..)) = bounds.last() { + self.span_err(self.prev_span, + "parenthesized lifetime bounds are not supported"); + } } } else { break diff --git a/src/test/parse-fail/bound-single-question-mark.rs b/src/test/parse-fail/bound-single-question-mark.rs new file mode 100644 index 00000000000..9dde5268c08 --- /dev/null +++ b/src/test/parse-fail/bound-single-question-mark.rs @@ -0,0 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z parse-only + +fn f<T: ?>() {} //~ ERROR expected identifier, found `>` |
