Skip to content

Commit 6e75def

Browse files
committed
Fix issue with single question mark or paren
1 parent e038f58 commit 6e75def

File tree

3 files changed

+44
-25
lines changed

3 files changed

+44
-25
lines changed

src/doc/grammar.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -781,10 +781,11 @@ never_type : "!" ;
781781
### Type parameter bounds
782782

783783
```antlr
784+
bound-list := bound | bound '+' bound-list '+' ?
784785
bound := ty_bound | lt_bound
785786
lt_bound := lifetime
786-
ty_bound := [?] [ for<lt_param_defs> ] simple_path
787-
bound-list := bound | bound '+' bound-list '+' ?
787+
ty_bound := ty_bound_noparen | (ty_bound_noparen)
788+
ty_bound_noparen := [?] [ for<lt_param_defs> ] simple_path
788789
```
789790

790791
### Self types

src/libsyntax/parse/parser.rs

+28-23
Original file line numberDiff line numberDiff line change
@@ -4086,32 +4086,37 @@ impl<'a> Parser<'a> {
40864086
fn parse_ty_param_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, TyParamBounds> {
40874087
let mut bounds = Vec::new();
40884088
loop {
4089-
let has_parens = self.eat(&token::OpenDelim(token::Paren));
4090-
let question = if self.eat(&token::Question) { Some(self.prev_span) } else { None };
4091-
if self.check_lifetime() {
4092-
if let Some(question_span) = question {
4093-
self.span_err(question_span,
4094-
"`?` may only modify trait bounds, not lifetime bounds");
4095-
}
4096-
bounds.push(RegionTyParamBound(self.expect_lifetime()));
4097-
if has_parens {
4098-
self.expect(&token::CloseDelim(token::Paren))?;
4099-
self.span_err(self.prev_span,
4100-
"parenthesized lifetime bounds are not supported");
4101-
}
4102-
} else if self.check_keyword(keywords::For) || self.check_path() {
4103-
let lo = self.span;
4104-
let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
4105-
let path = self.parse_path(PathStyle::Type)?;
4106-
let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_span));
4107-
let modifier = if question.is_some() {
4108-
TraitBoundModifier::Maybe
4089+
let is_bound_start = self.check_path() || self.check_lifetime() ||
4090+
self.check(&token::Question) ||
4091+
self.check_keyword(keywords::For) ||
4092+
self.check(&token::OpenDelim(token::Paren));
4093+
if is_bound_start {
4094+
let has_parens = self.eat(&token::OpenDelim(token::Paren));
4095+
let question = if self.eat(&token::Question) { Some(self.prev_span) } else { None };
4096+
if self.token.is_lifetime() {
4097+
if let Some(question_span) = question {
4098+
self.span_err(question_span,
4099+
"`?` may only modify trait bounds, not lifetime bounds");
4100+
}
4101+
bounds.push(RegionTyParamBound(self.expect_lifetime()));
41094102
} else {
4110-
TraitBoundModifier::None
4111-
};
4112-
bounds.push(TraitTyParamBound(poly_trait, modifier));
4103+
let lo = self.span;
4104+
let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
4105+
let path = self.parse_path(PathStyle::Type)?;
4106+
let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_span));
4107+
let modifier = if question.is_some() {
4108+
TraitBoundModifier::Maybe
4109+
} else {
4110+
TraitBoundModifier::None
4111+
};
4112+
bounds.push(TraitTyParamBound(poly_trait, modifier));
4113+
}
41134114
if has_parens {
41144115
self.expect(&token::CloseDelim(token::Paren))?;
4116+
if let Some(&RegionTyParamBound(..)) = bounds.last() {
4117+
self.span_err(self.prev_span,
4118+
"parenthesized lifetime bounds are not supported");
4119+
}
41154120
}
41164121
} else {
41174122
break
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z parse-only
12+
13+
fn f<T: ?>() {} //~ ERROR expected identifier, found `>`

0 commit comments

Comments
 (0)