Add attribute support to generic lifetime and type parameters.
I am using `ThinAttributes` rather than a vector for attributes attached to generics, since I expect almost all lifetime and types parameters to not carry any attributes.
This commit is contained in:
parent
f2c53ea66b
commit
4c37ad6607
8 changed files with 85 additions and 14 deletions
|
@ -1184,7 +1184,7 @@ impl<'a> Parser<'a> {
|
|||
let lo = self.span.lo;
|
||||
|
||||
let (name, node) = if self.eat_keyword(keywords::Type) {
|
||||
let TyParam {ident, bounds, default, ..} = self.parse_ty_param()?;
|
||||
let TyParam {ident, bounds, default, ..} = self.parse_ty_param(vec![])?;
|
||||
self.expect(&token::Semi)?;
|
||||
(ident, TraitItemKind::Type(bounds, default))
|
||||
} else if self.is_const_item() {
|
||||
|
@ -1923,10 +1923,22 @@ impl<'a> Parser<'a> {
|
|||
|
||||
/// Parses `lifetime_defs = [ lifetime_defs { ',' lifetime_defs } ]` where `lifetime_def =
|
||||
/// lifetime [':' lifetimes]`
|
||||
pub fn parse_lifetime_defs(&mut self) -> PResult<'a, Vec<ast::LifetimeDef>> {
|
||||
|
||||
///
|
||||
/// If `followed_by_ty_params` is None, then we are in a context
|
||||
/// where only lifetime parameters are allowed, and thus we should
|
||||
/// error if we encounter attributes after the bound lifetimes.
|
||||
///
|
||||
/// If `followed_by_ty_params` is Some(r), then there may be type
|
||||
/// parameter bindings after the lifetimes, so we should pass
|
||||
/// along the parsed attributes to be attached to the first such
|
||||
/// type parmeter.
|
||||
pub fn parse_lifetime_defs(&mut self,
|
||||
followed_by_ty_params: Option<&mut Vec<ast::Attribute>>)
|
||||
-> PResult<'a, Vec<ast::LifetimeDef>>
|
||||
{
|
||||
let mut res = Vec::new();
|
||||
loop {
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
match self.token {
|
||||
token::Lifetime(_) => {
|
||||
let lifetime = self.parse_lifetime()?;
|
||||
|
@ -1936,11 +1948,20 @@ impl<'a> Parser<'a> {
|
|||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
res.push(ast::LifetimeDef { lifetime: lifetime,
|
||||
res.push(ast::LifetimeDef { attrs: attrs.into(),
|
||||
lifetime: lifetime,
|
||||
bounds: bounds });
|
||||
}
|
||||
|
||||
_ => {
|
||||
if let Some(recv) = followed_by_ty_params {
|
||||
assert!(recv.is_empty());
|
||||
*recv = attrs;
|
||||
} else {
|
||||
let msg = "encountered trailing attributes after lifetime parameters";
|
||||
return Err(self.fatal(msg));
|
||||
}
|
||||
debug!("parse_lifetime_defs ret {:?}", res);
|
||||
return Ok(res);
|
||||
}
|
||||
}
|
||||
|
@ -4238,7 +4259,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// Matches typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?
|
||||
fn parse_ty_param(&mut self) -> PResult<'a, TyParam> {
|
||||
fn parse_ty_param(&mut self, preceding_attrs: Vec<ast::Attribute>) -> PResult<'a, TyParam> {
|
||||
let span = self.span;
|
||||
let ident = self.parse_ident()?;
|
||||
|
||||
|
@ -4252,6 +4273,7 @@ impl<'a> Parser<'a> {
|
|||
};
|
||||
|
||||
Ok(TyParam {
|
||||
attrs: preceding_attrs.into(),
|
||||
ident: ident,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
bounds: bounds,
|
||||
|
@ -4272,11 +4294,18 @@ impl<'a> Parser<'a> {
|
|||
let span_lo = self.span.lo;
|
||||
|
||||
if self.eat(&token::Lt) {
|
||||
let lifetime_defs = self.parse_lifetime_defs()?;
|
||||
let mut attrs = vec![];
|
||||
let lifetime_defs = self.parse_lifetime_defs(Some(&mut attrs))?;
|
||||
let mut seen_default = false;
|
||||
let mut post_lifetime_attrs = Some(attrs);
|
||||
let ty_params = self.parse_seq_to_gt(Some(token::Comma), |p| {
|
||||
p.forbid_lifetime()?;
|
||||
let ty_param = p.parse_ty_param()?;
|
||||
let attrs = match post_lifetime_attrs.as_mut() {
|
||||
None => p.parse_outer_attributes()?,
|
||||
Some(attrs) => mem::replace(attrs, vec![]),
|
||||
};
|
||||
post_lifetime_attrs = None;
|
||||
let ty_param = p.parse_ty_param(attrs)?;
|
||||
if ty_param.default.is_some() {
|
||||
seen_default = true;
|
||||
} else if seen_default {
|
||||
|
@ -4433,7 +4462,7 @@ impl<'a> Parser<'a> {
|
|||
let bound_lifetimes = if self.eat_keyword(keywords::For) {
|
||||
// Higher ranked constraint.
|
||||
self.expect(&token::Lt)?;
|
||||
let lifetime_defs = self.parse_lifetime_defs()?;
|
||||
let lifetime_defs = self.parse_lifetime_defs(None)?;
|
||||
self.expect_gt()?;
|
||||
lifetime_defs
|
||||
} else {
|
||||
|
@ -5006,7 +5035,7 @@ impl<'a> Parser<'a> {
|
|||
fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<ast::LifetimeDef>> {
|
||||
if self.eat_keyword(keywords::For) {
|
||||
self.expect(&token::Lt)?;
|
||||
let lifetime_defs = self.parse_lifetime_defs()?;
|
||||
let lifetime_defs = self.parse_lifetime_defs(None)?;
|
||||
self.expect_gt()?;
|
||||
Ok(lifetime_defs)
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue