diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:39 +0000 |
commit | 1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch) | |
tree | 3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /vendor/syn/src/stmt.rs | |
parent | Releasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-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.rs | 246 |
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); + } + } } |