summaryrefslogtreecommitdiffstats
path: root/vendor/syn/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/syn/src')
-rw-r--r--vendor/syn/src/error.rs23
-rw-r--r--vendor/syn/src/expr.rs24
-rw-r--r--vendor/syn/src/item.rs395
-rw-r--r--vendor/syn/src/lib.rs3
-rw-r--r--vendor/syn/src/meta.rs2
-rw-r--r--vendor/syn/src/pat.rs22
-rw-r--r--vendor/syn/src/punctuated.rs12
7 files changed, 270 insertions, 211 deletions
diff --git a/vendor/syn/src/error.rs b/vendor/syn/src/error.rs
index 7eebd243c..93f20f42f 100644
--- a/vendor/syn/src/error.rs
+++ b/vendor/syn/src/error.rs
@@ -278,8 +278,29 @@ impl ErrorMessage {
None => (Span::call_site(), Span::call_site()),
};
- // compile_error!($message)
+ // ::core::compile_error!($message)
TokenStream::from_iter(vec![
+ TokenTree::Punct({
+ let mut punct = Punct::new(':', Spacing::Joint);
+ punct.set_span(start);
+ punct
+ }),
+ TokenTree::Punct({
+ let mut punct = Punct::new(':', Spacing::Alone);
+ punct.set_span(start);
+ punct
+ }),
+ TokenTree::Ident(Ident::new("core", start)),
+ TokenTree::Punct({
+ let mut punct = Punct::new(':', Spacing::Joint);
+ punct.set_span(start);
+ punct
+ }),
+ TokenTree::Punct({
+ let mut punct = Punct::new(':', Spacing::Alone);
+ punct.set_span(start);
+ punct
+ }),
TokenTree::Ident(Ident::new("compile_error", start)),
TokenTree::Punct({
let mut punct = Punct::new('!', Spacing::Alone);
diff --git a/vendor/syn/src/expr.rs b/vendor/syn/src/expr.rs
index 8caccb33f..8a982021f 100644
--- a/vendor/syn/src/expr.rs
+++ b/vendor/syn/src/expr.rs
@@ -1301,9 +1301,7 @@ pub(crate) mod parsing {
Precedence::Assign
} else if input.peek(Token![..]) {
Precedence::Range
- } else if input.peek(Token![as])
- || cfg!(feature = "full") && input.peek(Token![:]) && !input.peek(Token![::])
- {
+ } else if input.peek(Token![as]) {
Precedence::Cast
} else {
Precedence::Any
@@ -2718,13 +2716,21 @@ pub(crate) mod parsing {
}
fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
- let mut float_repr = float.to_string();
+ let float_token = float.token();
+ let float_span = float_token.span();
+ let mut float_repr = float_token.to_string();
let trailing_dot = float_repr.ends_with('.');
if trailing_dot {
float_repr.truncate(float_repr.len() - 1);
}
+
+ let mut offset = 0;
for part in float_repr.split('.') {
- let index = crate::parse_str(part).map_err(|err| Error::new(float.span(), err))?;
+ let mut index: Index =
+ crate::parse_str(part).map_err(|err| Error::new(float_span, err))?;
+ let part_end = offset + part.len();
+ index.span = float_token.subspan(offset..part_end).unwrap_or(float_span);
+
let base = mem::replace(e, Expr::DUMMY);
*e = Expr::Field(ExprField {
attrs: Vec::new(),
@@ -2732,8 +2738,14 @@ pub(crate) mod parsing {
dot_token: Token![.](dot_token.span),
member: Member::Unnamed(index),
});
- *dot_token = Token![.](float.span());
+
+ let dot_span = float_token
+ .subspan(part_end..part_end + 1)
+ .unwrap_or(float_span);
+ *dot_token = Token![.](dot_span);
+ offset = part_end + 1;
}
+
Ok(!trailing_dot)
}
diff --git a/vendor/syn/src/item.rs b/vendor/syn/src/item.rs
index 9d724b063..46ccd73ff 100644
--- a/vendor/syn/src/item.rs
+++ b/vendor/syn/src/item.rs
@@ -893,9 +893,6 @@ pub(crate) mod parsing {
use crate::ext::IdentExt;
use crate::parse::discouraged::Speculative;
use crate::parse::{Parse, ParseBuffer, ParseStream, Result};
- use crate::token::Brace;
- use proc_macro2::{Punct, Spacing, TokenTree};
- use std::iter::FromIterator;
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Item {
@@ -971,40 +968,32 @@ pub(crate) mod parsing {
}
}
} else if lookahead.peek(Token![const]) {
- ahead.parse::<Token![const]>()?;
- let lookahead = ahead.lookahead1();
- if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
- let vis = input.parse()?;
- let const_token = input.parse()?;
- let ident = {
- let lookahead = input.lookahead1();
- if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
- input.call(Ident::parse_any)?
- } else {
- return Err(lookahead.error());
- }
- };
- let colon_token = input.parse()?;
- let ty = input.parse()?;
- if input.peek(Token![;]) {
- input.parse::<Token![;]>()?;
- Ok(Item::Verbatim(verbatim::between(begin, input)))
- } else {
- Ok(Item::Const(ItemConst {
- attrs: Vec::new(),
- vis,
- const_token,
- ident,
- generics: Generics::default(),
- colon_token,
- ty,
- eq_token: input.parse()?,
- expr: input.parse()?,
- semi_token: input.parse()?,
- }))
- }
+ let vis = input.parse()?;
+ let const_token: Token![const] = input.parse()?;
+ let lookahead = input.lookahead1();
+ let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
+ input.call(Ident::parse_any)?
} else {
- Err(lookahead.error())
+ return Err(lookahead.error());
+ };
+ let colon_token = input.parse()?;
+ let ty = input.parse()?;
+ if input.peek(Token![;]) {
+ input.parse::<Token![;]>()?;
+ Ok(Item::Verbatim(verbatim::between(begin, input)))
+ } else {
+ Ok(Item::Const(ItemConst {
+ attrs: Vec::new(),
+ vis,
+ const_token,
+ ident,
+ generics: Generics::default(),
+ colon_token,
+ ty,
+ eq_token: input.parse()?,
+ expr: input.parse()?,
+ semi_token: input.parse()?,
+ }))
}
} else if lookahead.peek(Token![unsafe]) {
ahead.parse::<Token![unsafe]>()?;
@@ -1083,6 +1072,11 @@ pub(crate) mod parsing {
semi_token: Token![;],
}
+ enum TypeDefaultness {
+ Optional,
+ Disallowed,
+ }
+
enum WhereClauseLocation {
// type Ty<T> where T: 'static = T;
BeforeEq,
@@ -1093,27 +1087,20 @@ pub(crate) mod parsing {
}
impl FlexibleItemType {
- fn parse(input: ParseStream, where_clause_location: WhereClauseLocation) -> Result<Self> {
+ fn parse(
+ input: ParseStream,
+ allow_defaultness: TypeDefaultness,
+ where_clause_location: WhereClauseLocation,
+ ) -> Result<Self> {
let vis: Visibility = input.parse()?;
- let defaultness: Option<Token![default]> = input.parse()?;
+ let defaultness: Option<Token![default]> = match allow_defaultness {
+ TypeDefaultness::Optional => input.parse()?,
+ TypeDefaultness::Disallowed => None,
+ };
let type_token: Token![type] = input.parse()?;
let ident: Ident = input.parse()?;
let mut generics: Generics = input.parse()?;
- let colon_token: Option<Token![:]> = input.parse()?;
-
- let mut bounds = Punctuated::new();
- if colon_token.is_some() {
- loop {
- if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
- break;
- }
- bounds.push_value(input.parse::<TypeParamBound>()?);
- if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
- break;
- }
- bounds.push_punct(input.parse::<Token![+]>()?);
- }
- }
+ let (colon_token, bounds) = Self::parse_optional_bounds(input)?;
match where_clause_location {
WhereClauseLocation::BeforeEq | WhereClauseLocation::Both => {
@@ -1122,11 +1109,7 @@ pub(crate) mod parsing {
WhereClauseLocation::AfterEq => {}
}
- let ty = if let Some(eq_token) = input.parse()? {
- Some((eq_token, input.parse::<Type>()?))
- } else {
- None
- };
+ let ty = Self::parse_optional_definition(input)?;
match where_clause_location {
WhereClauseLocation::AfterEq | WhereClauseLocation::Both
@@ -1151,6 +1134,38 @@ pub(crate) mod parsing {
semi_token,
})
}
+
+ fn parse_optional_bounds(
+ input: ParseStream,
+ ) -> Result<(Option<Token![:]>, Punctuated<TypeParamBound, Token![+]>)> {
+ let colon_token: Option<Token![:]> = input.parse()?;
+
+ let mut bounds = Punctuated::new();
+ if colon_token.is_some() {
+ loop {
+ if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
+ break;
+ }
+ bounds.push_value(input.parse::<TypeParamBound>()?);
+ if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
+ break;
+ }
+ bounds.push_punct(input.parse::<Token![+]>()?);
+ }
+ }
+
+ Ok((colon_token, bounds))
+ }
+
+ fn parse_optional_definition(input: ParseStream) -> Result<Option<(Token![=], Type)>> {
+ let eq_token: Option<Token![=]> = input.parse()?;
+ if let Some(eq_token) = eq_token {
+ let definition: Type = input.parse()?;
+ Ok(Some((eq_token, definition)))
+ } else {
+ Ok(None)
+ }
+ }
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
@@ -1852,7 +1867,7 @@ pub(crate) mod parsing {
fn parse_foreign_item_type(begin: ParseBuffer, input: ParseStream) -> Result<ForeignItem> {
let FlexibleItemType {
vis,
- defaultness,
+ defaultness: _,
type_token,
ident,
generics,
@@ -1860,9 +1875,13 @@ pub(crate) mod parsing {
bounds: _,
ty,
semi_token,
- } = FlexibleItemType::parse(input, WhereClauseLocation::Both)?;
+ } = FlexibleItemType::parse(
+ input,
+ TypeDefaultness::Disallowed,
+ WhereClauseLocation::Both,
+ )?;
- if defaultness.is_some() || colon_token.is_some() || ty.is_some() {
+ if colon_token.is_some() || ty.is_some() {
Ok(ForeignItem::Verbatim(verbatim::between(begin, input)))
} else {
Ok(ForeignItem::Type(ForeignItemType {
@@ -1917,7 +1936,7 @@ pub(crate) mod parsing {
fn parse_item_type(begin: ParseBuffer, input: ParseStream) -> Result<Item> {
let FlexibleItemType {
vis,
- defaultness,
+ defaultness: _,
type_token,
ident,
generics,
@@ -1925,23 +1944,27 @@ pub(crate) mod parsing {
bounds: _,
ty,
semi_token,
- } = FlexibleItemType::parse(input, WhereClauseLocation::BeforeEq)?;
+ } = FlexibleItemType::parse(
+ input,
+ TypeDefaultness::Disallowed,
+ WhereClauseLocation::BeforeEq,
+ )?;
+
+ let (eq_token, ty) = match ty {
+ Some(ty) if colon_token.is_none() => ty,
+ _ => return Ok(Item::Verbatim(verbatim::between(begin, input))),
+ };
- if defaultness.is_some() || colon_token.is_some() || ty.is_none() {
- Ok(Item::Verbatim(verbatim::between(begin, input)))
- } else {
- let (eq_token, ty) = ty.unwrap();
- Ok(Item::Type(ItemType {
- attrs: Vec::new(),
- vis,
- type_token,
- ident,
- generics,
- eq_token,
- ty: Box::new(ty),
- semi_token,
- }))
- }
+ Ok(Item::Type(ItemType {
+ attrs: Vec::new(),
+ vis,
+ type_token,
+ ident,
+ generics,
+ eq_token,
+ ty: Box::new(ty),
+ semi_token,
+ }))
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
@@ -2202,11 +2225,13 @@ pub(crate) mod parsing {
}
} else if lookahead.peek(Token![type]) {
parse_trait_item_type(begin.fork(), input)
- } else if lookahead.peek(Ident)
- || lookahead.peek(Token![self])
- || lookahead.peek(Token![super])
- || lookahead.peek(Token![crate])
- || lookahead.peek(Token![::])
+ } else if vis.is_inherited()
+ && defaultness.is_none()
+ && (lookahead.peek(Ident)
+ || lookahead.peek(Token![self])
+ || lookahead.peek(Token![super])
+ || lookahead.peek(Token![crate])
+ || lookahead.peek(Token![::]))
{
input.parse().map(TraitItem::Macro)
} else {
@@ -2298,30 +2323,10 @@ pub(crate) mod parsing {
let type_token: Token![type] = input.parse()?;
let ident: Ident = input.parse()?;
let mut generics: Generics = input.parse()?;
- let colon_token: Option<Token![:]> = input.parse()?;
-
- let mut bounds = Punctuated::new();
- if colon_token.is_some() {
- while !input.peek(Token![where]) && !input.peek(Token![=]) && !input.peek(Token![;])
- {
- if !bounds.is_empty() {
- bounds.push_punct(input.parse()?);
- }
- bounds.push_value(input.parse()?);
- }
- }
-
- let default = if input.peek(Token![=]) {
- let eq_token: Token![=] = input.parse()?;
- let default: Type = input.parse()?;
- Some((eq_token, default))
- } else {
- None
- };
-
+ let (colon_token, bounds) = FlexibleItemType::parse_optional_bounds(input)?;
+ let default = FlexibleItemType::parse_optional_definition(input)?;
generics.where_clause = input.parse()?;
let semi_token: Token![;] = input.parse()?;
-
Ok(TraitItemType {
attrs,
type_token,
@@ -2338,7 +2343,7 @@ pub(crate) mod parsing {
fn parse_trait_item_type(begin: ParseBuffer, input: ParseStream) -> Result<TraitItem> {
let FlexibleItemType {
vis,
- defaultness,
+ defaultness: _,
type_token,
ident,
generics,
@@ -2346,9 +2351,13 @@ pub(crate) mod parsing {
bounds,
ty,
semi_token,
- } = FlexibleItemType::parse(input, WhereClauseLocation::AfterEq)?;
+ } = FlexibleItemType::parse(
+ input,
+ TypeDefaultness::Disallowed,
+ WhereClauseLocation::AfterEq,
+ )?;
- if defaultness.is_some() || vis.is_some() {
+ if vis.is_some() {
Ok(TraitItem::Verbatim(verbatim::between(begin, input)))
} else {
Ok(TraitItem::Type(TraitItemType {
@@ -2512,35 +2521,40 @@ pub(crate) mod parsing {
};
let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead) {
- input.parse().map(ImplItem::Fn)
+ let allow_omitted_body = true;
+ if let Some(item) = parse_impl_item_fn(input, allow_omitted_body)? {
+ Ok(ImplItem::Fn(item))
+ } else {
+ Ok(ImplItem::Verbatim(verbatim::between(begin, input)))
+ }
} else if lookahead.peek(Token![const]) {
- let const_token: Token![const] = ahead.parse()?;
- let lookahead = ahead.lookahead1();
- if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
- input.advance_to(&ahead);
- let ident: Ident = input.call(Ident::parse_any)?;
- let colon_token: Token![:] = input.parse()?;
- let ty: Type = input.parse()?;
- if let Some(eq_token) = input.parse()? {
- return Ok(ImplItem::Const(ImplItemConst {
- attrs,
- vis,
- defaultness,
- const_token,
- ident,
- generics: Generics::default(),
- colon_token,
- ty,
- eq_token,
- expr: input.parse()?,
- semi_token: input.parse()?,
- }));
- } else {
- input.parse::<Token![;]>()?;
- return Ok(ImplItem::Verbatim(verbatim::between(begin, input)));
- }
+ input.advance_to(&ahead);
+ let const_token: Token![const] = input.parse()?;
+ let lookahead = input.lookahead1();
+ let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
+ input.call(Ident::parse_any)?
} else {
- Err(lookahead.error())
+ return Err(lookahead.error());
+ };
+ let colon_token: Token![:] = input.parse()?;
+ let ty: Type = input.parse()?;
+ if let Some(eq_token) = input.parse()? {
+ return Ok(ImplItem::Const(ImplItemConst {
+ attrs,
+ vis,
+ defaultness,
+ const_token,
+ ident,
+ generics: Generics::default(),
+ colon_token,
+ ty,
+ eq_token,
+ expr: input.parse()?,
+ semi_token: input.parse()?,
+ }));
+ } else {
+ input.parse::<Token![;]>()?;
+ return Ok(ImplItem::Verbatim(verbatim::between(begin, input)));
}
} else if lookahead.peek(Token![type]) {
parse_impl_item_type(begin, input)
@@ -2602,41 +2616,42 @@ pub(crate) mod parsing {
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for ImplItemFn {
fn parse(input: ParseStream) -> Result<Self> {
- let mut attrs = input.call(Attribute::parse_outer)?;
- let vis: Visibility = input.parse()?;
- let defaultness: Option<Token![default]> = input.parse()?;
- let sig: Signature = input.parse()?;
+ let allow_omitted_body = false;
+ parse_impl_item_fn(input, allow_omitted_body).map(Option::unwrap)
+ }
+ }
- let block = if let Some(semi) = input.parse::<Option<Token![;]>>()? {
- // Accept functions without a body in an impl block because
- // rustc's *parser* does not reject them (the compilation error
- // is emitted later than parsing) and it can be useful for macro
- // DSLs.
- let mut punct = Punct::new(';', Spacing::Alone);
- punct.set_span(semi.span);
- let tokens = TokenStream::from_iter(vec![TokenTree::Punct(punct)]);
- Block {
- brace_token: Brace(semi.span),
- stmts: vec![Stmt::Item(Item::Verbatim(tokens))],
- }
- } else {
- let content;
- let brace_token = braced!(content in input);
- attrs.extend(content.call(Attribute::parse_inner)?);
- Block {
- brace_token,
- stmts: content.call(Block::parse_within)?,
- }
- };
+ fn parse_impl_item_fn(
+ input: ParseStream,
+ allow_omitted_body: bool,
+ ) -> Result<Option<ImplItemFn>> {
+ let mut attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ let defaultness: Option<Token![default]> = input.parse()?;
+ let sig: Signature = input.parse()?;
- Ok(ImplItemFn {
- attrs,
- vis,
- defaultness,
- sig,
- block,
- })
+ // Accept functions without a body in an impl block because rustc's
+ // *parser* does not reject them (the compilation error is emitted later
+ // than parsing) and it can be useful for macro DSLs.
+ if allow_omitted_body && input.parse::<Option<Token![;]>>()?.is_some() {
+ return Ok(None);
}
+
+ let content;
+ let brace_token = braced!(content in input);
+ attrs.extend(content.call(Attribute::parse_inner)?);
+ let block = Block {
+ brace_token,
+ stmts: content.call(Block::parse_within)?,
+ };
+
+ Ok(Some(ImplItemFn {
+ attrs,
+ vis,
+ defaultness,
+ sig,
+ block,
+ }))
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
@@ -2677,24 +2692,28 @@ pub(crate) mod parsing {
bounds: _,
ty,
semi_token,
- } = FlexibleItemType::parse(input, WhereClauseLocation::AfterEq)?;
+ } = FlexibleItemType::parse(
+ input,
+ TypeDefaultness::Optional,
+ WhereClauseLocation::AfterEq,
+ )?;
+
+ let (eq_token, ty) = match ty {
+ Some(ty) if colon_token.is_none() => ty,
+ _ => return Ok(ImplItem::Verbatim(verbatim::between(begin, input))),
+ };
- if colon_token.is_some() || ty.is_none() {
- Ok(ImplItem::Verbatim(verbatim::between(begin, input)))
- } else {
- let (eq_token, ty) = ty.unwrap();
- Ok(ImplItem::Type(ImplItemType {
- attrs: Vec::new(),
- vis,
- defaultness,
- type_token,
- ident,
- generics,
- eq_token,
- ty,
- semi_token,
- }))
- }
+ Ok(ImplItem::Type(ImplItemType {
+ attrs: Vec::new(),
+ vis,
+ defaultness,
+ type_token,
+ ident,
+ generics,
+ eq_token,
+ ty,
+ semi_token,
+ }))
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
@@ -3132,14 +3151,6 @@ mod printing {
self.vis.to_tokens(tokens);
self.defaultness.to_tokens(tokens);
self.sig.to_tokens(tokens);
- if self.block.stmts.len() == 1 {
- if let Stmt::Item(Item::Verbatim(verbatim)) = &self.block.stmts[0] {
- if verbatim.to_string() == ";" {
- verbatim.to_tokens(tokens);
- return;
- }
- }
- }
self.block.brace_token.surround(tokens, |tokens| {
tokens.append_all(self.attrs.inner());
tokens.append_all(&self.block.stmts);
diff --git a/vendor/syn/src/lib.rs b/vendor/syn/src/lib.rs
index 72b9e7d89..74bd21b41 100644
--- a/vendor/syn/src/lib.rs
+++ b/vendor/syn/src/lib.rs
@@ -249,7 +249,7 @@
//! dynamic library libproc_macro from rustc toolchain.
// Syn types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/syn/2.0.8")]
+#![doc(html_root_url = "https://docs.rs/syn/2.0.14")]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![allow(non_camel_case_types)]
#![allow(
@@ -281,6 +281,7 @@
clippy::needless_doctest_main,
clippy::needless_pass_by_value,
clippy::never_loop,
+ clippy::range_plus_one,
clippy::redundant_else,
clippy::return_self_not_must_use,
clippy::similar_names,
diff --git a/vendor/syn/src/meta.rs b/vendor/syn/src/meta.rs
index 766d5b703..b6bcf9830 100644
--- a/vendor/syn/src/meta.rs
+++ b/vendor/syn/src/meta.rs
@@ -401,6 +401,8 @@ fn parse_meta_path(input: ParseStream) -> Result<Path> {
if input.peek(Ident::peek_any) {
let ident = Ident::parse_any(input)?;
segments.push_value(PathSegment::from(ident));
+ } else if input.is_empty() {
+ return Err(input.error("expected nested attribute"));
} else if input.peek(Lit) {
return Err(input.error("unexpected literal in nested attribute, expected ident"));
} else {
diff --git a/vendor/syn/src/pat.rs b/vendor/syn/src/pat.rs
index 5833eeb33..2e6376b2f 100644
--- a/vendor/syn/src/pat.rs
+++ b/vendor/syn/src/pat.rs
@@ -543,17 +543,17 @@ pub(crate) mod parsing {
Member::Unnamed(_) => unreachable!(),
};
- let mut pat = Pat::Ident(PatIdent {
- attrs: Vec::new(),
- by_ref,
- mutability,
- ident: ident.clone(),
- subpat: None,
- });
-
- if boxed.is_some() {
- pat = Pat::Verbatim(verbatim::between(begin, input));
- }
+ let pat = if boxed.is_some() {
+ Pat::Verbatim(verbatim::between(begin, input))
+ } else {
+ Pat::Ident(PatIdent {
+ attrs: Vec::new(),
+ by_ref,
+ mutability,
+ ident: ident.clone(),
+ subpat: None,
+ })
+ };
Ok(FieldPat {
attrs: Vec::new(),
diff --git a/vendor/syn/src/punctuated.rs b/vendor/syn/src/punctuated.rs
index 7880eb29c..a4278081c 100644
--- a/vendor/syn/src/punctuated.rs
+++ b/vendor/syn/src/punctuated.rs
@@ -187,6 +187,18 @@ impl<T, P> Punctuated<T, P> {
}
}
+ /// Removes the trailing punctuation from this punctuated sequence, or
+ /// `None` if there isn't any.
+ pub fn pop_punct(&mut self) -> Option<P> {
+ if self.last.is_some() {
+ None
+ } else {
+ let (t, p) = self.inner.pop()?;
+ self.last = Some(Box::new(t));
+ Some(p)
+ }
+ }
+
/// Determines whether this punctuated sequence ends with a trailing
/// punctuation.
pub fn trailing_punct(&self) -> bool {