summaryrefslogtreecommitdiffstats
path: root/vendor/syn/src/stmt.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
commit1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch)
tree3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /vendor/syn/src/stmt.rs
parentReleasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.tar.xz
rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.zip
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/syn/src/stmt.rs')
-rw-r--r--vendor/syn/src/stmt.rs246
1 files changed, 175 insertions, 71 deletions
diff --git a/vendor/syn/src/stmt.rs b/vendor/syn/src/stmt.rs
index 58bd013ec..b5434f7ce 100644
--- a/vendor/syn/src/stmt.rs
+++ b/vendor/syn/src/stmt.rs
@@ -2,8 +2,6 @@ use super::*;
ast_struct! {
/// A braced block containing Rust statements.
- ///
- /// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct Block {
pub brace_token: token::Brace,
@@ -14,8 +12,6 @@ ast_struct! {
ast_enum! {
/// A statement, usually ending in a semicolon.
- ///
- /// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub enum Stmt {
/// A local (let) binding.
@@ -24,42 +20,71 @@ ast_enum! {
/// An item definition.
Item(Item),
- /// Expr without trailing semicolon.
- Expr(Expr),
+ /// Expression, with or without trailing semicolon.
+ Expr(Expr, Option<Token![;]>),
- /// Expression with trailing semicolon.
- Semi(Expr, Token![;]),
+ /// A macro invocation in statement position.
+ ///
+ /// Syntactically it's ambiguous which other kind of statement this
+ /// macro would expand to. It can be any of local variable (`let`),
+ /// item, or expression.
+ Macro(StmtMacro),
}
}
ast_struct! {
/// A local `let` binding: `let x: u64 = s.parse()?`.
- ///
- /// *This type is available only if Syn is built with the `"full"` feature.*
#[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
pub struct Local {
pub attrs: Vec<Attribute>,
pub let_token: Token![let],
pub pat: Pat,
- pub init: Option<(Token![=], Box<Expr>)>,
+ pub init: Option<LocalInit>,
pub semi_token: Token![;],
}
}
+ast_struct! {
+ /// The expression assigned in a local `let` binding, including optional
+ /// diverging `else` block.
+ ///
+ /// `LocalInit` represents `= s.parse()?` in `let x: u64 = s.parse()?` and
+ /// `= r else { return }` in `let Ok(x) = r else { return }`.
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
+ pub struct LocalInit {
+ pub eq_token: Token![=],
+ pub expr: Box<Expr>,
+ pub diverge: Option<(Token![else], Box<Expr>)>,
+ }
+}
+
+ast_struct! {
+ /// A macro invocation in statement position.
+ ///
+ /// Syntactically it's ambiguous which other kind of statement this macro
+ /// would expand to. It can be any of local variable (`let`), item, or
+ /// expression.
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
+ pub struct StmtMacro {
+ pub attrs: Vec<Attribute>,
+ pub mac: Macro,
+ pub semi_token: Option<Token![;]>,
+ }
+}
+
#[cfg(feature = "parsing")]
-pub mod parsing {
+pub(crate) mod parsing {
use super::*;
use crate::parse::discouraged::Speculative;
- use crate::parse::{Parse, ParseBuffer, ParseStream, Result};
+ use crate::parse::{Parse, ParseStream, Result};
use proc_macro2::TokenStream;
+ struct AllowNoSemi(bool);
+
impl Block {
/// Parse the body of a block as zero or more statements, possibly
/// including one trailing expression.
///
- /// *This function is available only if Syn is built with the `"parsing"`
- /// feature.*
- ///
/// # Example
///
/// ```
@@ -110,23 +135,25 @@ pub mod parsing {
pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
let mut stmts = Vec::new();
loop {
- while let Some(semi) = input.parse::<Option<Token![;]>>()? {
- stmts.push(Stmt::Semi(Expr::Verbatim(TokenStream::new()), semi));
+ while let semi @ Some(_) = input.parse()? {
+ stmts.push(Stmt::Expr(Expr::Verbatim(TokenStream::new()), semi));
}
if input.is_empty() {
break;
}
- let s = parse_stmt(input, true)?;
- let requires_semicolon = if let Stmt::Expr(s) = &s {
- expr::requires_terminator(s)
- } else {
- false
+ let stmt = parse_stmt(input, AllowNoSemi(true))?;
+ let requires_semicolon = match &stmt {
+ Stmt::Expr(stmt, None) => expr::requires_terminator(stmt),
+ Stmt::Macro(stmt) => {
+ stmt.semi_token.is_none() && !stmt.mac.delimiter.is_brace()
+ }
+ Stmt::Local(_) | Stmt::Item(_) | Stmt::Expr(_, Some(_)) => false,
};
- stmts.push(s);
+ stmts.push(stmt);
if input.is_empty() {
break;
} else if requires_semicolon {
- return Err(input.error("unexpected token"));
+ return Err(input.error("unexpected token, expected `;`"));
}
}
Ok(stmts)
@@ -147,30 +174,33 @@ pub mod parsing {
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Stmt {
fn parse(input: ParseStream) -> Result<Self> {
- parse_stmt(input, false)
+ let allow_nosemi = AllowNoSemi(false);
+ parse_stmt(input, allow_nosemi)
}
}
- fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
- let begin = input.fork();
+ fn parse_stmt(input: ParseStream, allow_nosemi: AllowNoSemi) -> Result<Stmt> {
let mut attrs = input.call(Attribute::parse_outer)?;
// brace-style macros; paren and bracket macros get parsed as
// expression statements.
let ahead = input.fork();
+ let mut is_item_macro = false;
if let Ok(path) = ahead.call(Path::parse_mod_style) {
- if ahead.peek(Token![!])
- && (ahead.peek2(token::Brace)
+ if ahead.peek(Token![!]) {
+ if ahead.peek2(Ident) || ahead.peek2(Token![try]) {
+ is_item_macro = true;
+ } else if ahead.peek2(token::Brace)
&& !(ahead.peek3(Token![.]) || ahead.peek3(Token![?]))
- || ahead.peek2(Ident))
- {
- input.advance_to(&ahead);
- return stmt_mac(input, attrs, path);
+ {
+ input.advance_to(&ahead);
+ return stmt_mac(input, attrs, path).map(Stmt::Macro);
+ }
}
}
if input.peek(Token![let]) {
- stmt_local(input, attrs, begin)
+ stmt_local(input, attrs).map(Stmt::Local)
} else if input.peek(Token![pub])
|| input.peek(Token![crate]) && !input.peek2(Token![::])
|| input.peek(Token![extern])
@@ -180,7 +210,15 @@ pub mod parsing {
|| input.peek2(Ident)
&& !(input.peek2(Token![async])
&& (input.peek3(Token![move]) || input.peek3(Token![|]))))
- || input.peek(Token![const]) && !input.peek2(token::Brace)
+ || input.peek(Token![const])
+ && !(input.peek2(token::Brace)
+ || input.peek2(Token![static])
+ || input.peek2(Token![async])
+ && !(input.peek3(Token![unsafe])
+ || input.peek3(Token![extern])
+ || input.peek3(Token![fn]))
+ || input.peek2(Token![move])
+ || input.peek2(Token![|]))
|| input.peek(Token![unsafe]) && !input.peek2(token::Brace)
|| input.peek(Token![async])
&& (input.peek2(Token![unsafe])
@@ -198,6 +236,7 @@ pub mod parsing {
&& (input.peek2(Token![unsafe]) || input.peek2(Token![impl]))
|| input.peek(Token![impl])
|| input.peek(Token![macro])
+ || is_item_macro
{
let mut item: Item = input.parse()?;
attrs.extend(item.replace_attrs(Vec::new()));
@@ -208,15 +247,13 @@ pub mod parsing {
}
}
- fn stmt_mac(input: ParseStream, attrs: Vec<Attribute>, path: Path) -> Result<Stmt> {
+ fn stmt_mac(input: ParseStream, attrs: Vec<Attribute>, path: Path) -> Result<StmtMacro> {
let bang_token: Token![!] = input.parse()?;
- let ident: Option<Ident> = input.parse()?;
let (delimiter, tokens) = mac::parse_delimiter(input)?;
let semi_token: Option<Token![;]> = input.parse()?;
- Ok(Stmt::Item(Item::Macro(ItemMacro {
+ Ok(StmtMacro {
attrs,
- ident,
mac: Macro {
path,
bang_token,
@@ -224,13 +261,13 @@ pub mod parsing {
tokens,
},
semi_token,
- })))
+ })
}
- fn stmt_local(input: ParseStream, attrs: Vec<Attribute>, begin: ParseBuffer) -> Result<Stmt> {
+ fn stmt_local(input: ParseStream, attrs: Vec<Attribute>) -> Result<Local> {
let let_token: Token![let] = input.parse()?;
- let mut pat: Pat = pat::parsing::multi_pat_with_leading_vert(input)?;
+ let mut pat = Pat::parse_single(input)?;
if input.peek(Token![:]) {
let colon_token: Token![:] = input.parse()?;
let ty: Type = input.parse()?;
@@ -242,39 +279,45 @@ pub mod parsing {
});
}
- let init = if input.peek(Token![=]) {
- let eq_token: Token![=] = input.parse()?;
- let init: Expr = input.parse()?;
-
- if input.peek(Token![else]) {
- input.parse::<Token![else]>()?;
- let content;
- braced!(content in input);
- content.call(Block::parse_within)?;
- let verbatim = Expr::Verbatim(verbatim::between(begin, input));
- let semi_token: Token![;] = input.parse()?;
- return Ok(Stmt::Semi(verbatim, semi_token));
- }
+ let init = if let Some(eq_token) = input.parse()? {
+ let eq_token: Token![=] = eq_token;
+ let expr: Expr = input.parse()?;
+
+ let diverge = if let Some(else_token) = input.parse()? {
+ let else_token: Token![else] = else_token;
+ let diverge = ExprBlock {
+ attrs: Vec::new(),
+ label: None,
+ block: input.parse()?,
+ };
+ Some((else_token, Box::new(Expr::Block(diverge))))
+ } else {
+ None
+ };
- Some((eq_token, Box::new(init)))
+ Some(LocalInit {
+ eq_token,
+ expr: Box::new(expr),
+ diverge,
+ })
} else {
None
};
let semi_token: Token![;] = input.parse()?;
- Ok(Stmt::Local(Local {
+ Ok(Local {
attrs,
let_token,
pat,
init,
semi_token,
- }))
+ })
}
fn stmt_expr(
input: ParseStream,
- allow_nosemi: bool,
+ allow_nosemi: AllowNoSemi,
mut attrs: Vec<Attribute>,
) -> Result<Stmt> {
let mut e = expr::parsing::expr_early(input)?;
@@ -283,20 +326,68 @@ pub mod parsing {
loop {
attr_target = match attr_target {
Expr::Assign(e) => &mut e.left,
- Expr::AssignOp(e) => &mut e.left,
Expr::Binary(e) => &mut e.left,
- _ => break,
+ Expr::Cast(e) => &mut e.expr,
+ Expr::Array(_)
+ | Expr::Async(_)
+ | Expr::Await(_)
+ | Expr::Block(_)
+ | Expr::Break(_)
+ | Expr::Call(_)
+ | Expr::Closure(_)
+ | Expr::Const(_)
+ | Expr::Continue(_)
+ | Expr::Field(_)
+ | Expr::ForLoop(_)
+ | Expr::Group(_)
+ | Expr::If(_)
+ | Expr::Index(_)
+ | Expr::Infer(_)
+ | Expr::Let(_)
+ | Expr::Lit(_)
+ | Expr::Loop(_)
+ | Expr::Macro(_)
+ | Expr::Match(_)
+ | Expr::MethodCall(_)
+ | Expr::Paren(_)
+ | Expr::Path(_)
+ | Expr::Range(_)
+ | Expr::Reference(_)
+ | Expr::Repeat(_)
+ | Expr::Return(_)
+ | Expr::Struct(_)
+ | Expr::Try(_)
+ | Expr::TryBlock(_)
+ | Expr::Tuple(_)
+ | Expr::Unary(_)
+ | Expr::Unsafe(_)
+ | Expr::While(_)
+ | Expr::Yield(_)
+ | Expr::Verbatim(_) => break,
};
}
attrs.extend(attr_target.replace_attrs(Vec::new()));
attr_target.replace_attrs(attrs);
- if input.peek(Token![;]) {
- return Ok(Stmt::Semi(e, input.parse()?));
+ let semi_token: Option<Token![;]> = input.parse()?;
+
+ match e {
+ Expr::Macro(ExprMacro { attrs, mac })
+ if semi_token.is_some() || mac.delimiter.is_brace() =>
+ {
+ return Ok(Stmt::Macro(StmtMacro {
+ attrs,
+ mac,
+ semi_token,
+ }));
+ }
+ _ => {}
}
- if allow_nosemi || !expr::requires_terminator(&e) {
- Ok(Stmt::Expr(e))
+ if semi_token.is_some() {
+ Ok(Stmt::Expr(e, semi_token))
+ } else if allow_nosemi.0 || !expr::requires_terminator(&e) {
+ Ok(Stmt::Expr(e, None))
} else {
Err(input.error("expected semicolon"))
}
@@ -324,11 +415,11 @@ mod printing {
match self {
Stmt::Local(local) => local.to_tokens(tokens),
Stmt::Item(item) => item.to_tokens(tokens),
- Stmt::Expr(expr) => expr.to_tokens(tokens),
- Stmt::Semi(expr, semi) => {
+ Stmt::Expr(expr, semi) => {
expr.to_tokens(tokens);
semi.to_tokens(tokens);
}
+ Stmt::Macro(mac) => mac.to_tokens(tokens),
}
}
}
@@ -339,11 +430,24 @@ mod printing {
expr::printing::outer_attrs_to_tokens(&self.attrs, tokens);
self.let_token.to_tokens(tokens);
self.pat.to_tokens(tokens);
- if let Some((eq_token, init)) = &self.init {
- eq_token.to_tokens(tokens);
- init.to_tokens(tokens);
+ if let Some(init) = &self.init {
+ init.eq_token.to_tokens(tokens);
+ init.expr.to_tokens(tokens);
+ if let Some((else_token, diverge)) = &init.diverge {
+ else_token.to_tokens(tokens);
+ diverge.to_tokens(tokens);
+ }
}
self.semi_token.to_tokens(tokens);
}
}
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ impl ToTokens for StmtMacro {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ expr::printing::outer_attrs_to_tokens(&self.attrs, tokens);
+ self.mac.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
}