1use crate::attr::Attribute;
2#[cfg(all(feature = "parsing", feature = "full"))]
3use crate::error::Result;
4#[cfg(feature = "parsing")]
5use crate::ext::IdentExt as _;
6#[cfg(feature = "full")]
7use crate::generics::BoundLifetimes;
8use crate::ident::Ident;
9#[cfg(any(feature = "parsing", feature = "full"))]
10use crate::lifetime::Lifetime;
11use crate::lit::Lit;
12use crate::mac::Macro;
13use crate::op::{BinOp, UnOp};
14#[cfg(feature = "parsing")]
15use crate::parse::ParseStream;
16#[cfg(feature = "full")]
17use crate::pat::Pat;
18use crate::path::{AngleBracketedGenericArguments, Path, QSelf};
19use crate::punctuated::Punctuated;
20#[cfg(feature = "full")]
21use crate::stmt::Block;
22use crate::token;
23#[cfg(feature = "full")]
24use crate::ty::ReturnType;
25use crate::ty::Type;
26use alloc::boxed::Box;
27use alloc::vec::Vec;
28#[cfg(feature = "printing")]
29use core::fmt::{self, Display};
30use core::hash::{Hash, Hasher};
31#[cfg(all(feature = "parsing", feature = "full"))]
32use core::mem;
33use proc_macro2::{Span, TokenStream};
34#[cfg(feature = "printing")]
35use quote::IdentFragment;
36
37#[doc = r" A Rust expression."]
#[doc = r""]
#[doc =
r#" *This type is available only if Syn is built with the `"derive"` or `"full"`"#]
#[doc =
r#" feature, but most of the variants are not available unless "full" is enabled.*"#]
#[doc = r""]
#[doc = r" # Syntax tree enums"]
#[doc = r""]
#[doc =
r" This type is a syntax tree enum. In Syn this and other syntax tree enums"]
#[doc = r" are designed to be traversed using the following rebinding idiom."]
#[doc = r""]
#[doc = r" ```"]
#[doc = r" # use syn::Expr;"]
#[doc = r" #"]
#[doc = r" # fn example(expr: Expr) {"]
#[doc = r" # const IGNORE: &str = stringify! {"]
#[doc = r" let expr: Expr = /* ... */;"]
#[doc = r" # };"]
#[doc = r" match expr {"]
#[doc = r" Expr::MethodCall(expr) => {"]
#[doc = r" /* ... */"]
#[doc = r" }"]
#[doc = r" Expr::Cast(expr) => {"]
#[doc = r" /* ... */"]
#[doc = r" }"]
#[doc = r" Expr::If(expr) => {"]
#[doc = r" /* ... */"]
#[doc = r" }"]
#[doc = r""]
#[doc = r" /* ... */"]
#[doc = r" # _ => {}"]
#[doc = r" # }"]
#[doc = r" # }"]
#[doc = r" ```"]
#[doc = r""]
#[doc = r" We begin with a variable `expr` of type `Expr` that has no fields"]
#[doc =
r" (because it is an enum), and by matching on it and rebinding a variable"]
#[doc =
r" with the same name `expr` we effectively imbue our variable with all of"]
#[doc =
r" the data fields provided by the variant that it turned out to be. So for"]
#[doc =
r" example above if we ended up in the `MethodCall` case then we get to use"]
#[doc =
r" `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get"]
#[doc = r" to use `expr.cond`, `expr.then_branch`, `expr.else_branch`."]
#[doc = r""]
#[doc =
r" This approach avoids repeating the variant names twice on every line."]
#[doc = r""]
#[doc = r" ```"]
#[doc = r" # use syn::{Expr, ExprMethodCall};"]
#[doc = r" #"]
#[doc = r" # fn example(expr: Expr) {"]
#[doc = r" // Repetitive; recommend not doing this."]
#[doc = r" match expr {"]
#[doc = r" Expr::MethodCall(ExprMethodCall { method, args, .. }) => {"]
#[doc = r" # }"]
#[doc = r" # _ => {}"]
#[doc = r" # }"]
#[doc = r" # }"]
#[doc = r" ```"]
#[doc = r""]
#[doc =
r" In general, the name to which a syntax tree enum variant is bound should"]
#[doc = r" be a suitable name for the complete syntax tree enum type."]
#[doc = r""]
#[doc = r" ```"]
#[doc = r" # use syn::{Expr, ExprField};"]
#[doc = r" #"]
#[doc = r" # fn example(discriminant: ExprField) {"]
#[doc =
r" // Binding is called `base` which is the name I would use if I were"]
#[doc = r" // assigning `*discriminant.base` without an `if let`."]
#[doc = r" if let Expr::Tuple(base) = *discriminant.base {"]
#[doc = r" # }"]
#[doc = r" # }"]
#[doc = r" ```"]
#[doc = r""]
#[doc =
r" A sign that you may not be choosing the right variable names is if you"]
#[doc = r" see names getting repeated in your code, like accessing"]
#[doc = r" `receiver.receiver` or `pat.pat` or `cond.cond`."]
#[non_exhaustive]
pub enum Expr {
#[doc = r" A slice literal expression: `[a, b, c, d]`."]
Array(ExprArray),
#[doc = r" An assignment expression: `a = compute()`."]
Assign(ExprAssign),
#[doc = r" An async block: `async { ... }`."]
Async(ExprAsync),
#[doc = r" An await expression: `fut.await`."]
Await(ExprAwait),
#[doc = r" A binary operation: `a + b`, `a += b`."]
Binary(ExprBinary),
#[doc = r" A blocked scope: `{ ... }`."]
Block(ExprBlock),
#[doc = r" A `break`, with an optional label to break and an optional"]
#[doc = r" expression."]
Break(ExprBreak),
#[doc = r" A function call expression: `invoke(a, b)`."]
Call(ExprCall),
#[doc = r" A cast expression: `foo as f64`."]
Cast(ExprCast),
#[doc = r" A closure expression: `|a, b| a + b`."]
Closure(ExprClosure),
#[doc = r" A const block: `const { ... }`."]
Const(ExprConst),
#[doc = r" A `continue`, with an optional label."]
Continue(ExprContinue),
#[doc =
r" Access of a named struct field (`obj.k`) or unnamed tuple struct"]
#[doc = r" field (`obj.0`)."]
Field(ExprField),
#[doc = r" A for loop: `for pat in expr { ... }`."]
ForLoop(ExprForLoop),
#[doc = r" An expression contained within invisible delimiters."]
#[doc = r""]
#[doc =
r" This variant is important for faithfully representing the precedence"]
#[doc = r" of expressions and is related to `None`-delimited spans in a"]
#[doc = r" `TokenStream`."]
Group(ExprGroup),
#[doc =
r" An `if` expression with an optional `else` block: `if expr { ... }"]
#[doc = r" else { ... }`."]
#[doc = r""]
#[doc = r" The `else` branch expression may only be an `If` or `Block`"]
#[doc = r" expression, not any of the other types of expression."]
If(ExprIf),
#[doc = r" A square bracketed indexing expression: `vector[2]`."]
Index(ExprIndex),
#[doc = r" The inferred value of a const generic argument, denoted `_`."]
Infer(ExprInfer),
#[doc = r" A `let` guard: `let Some(x) = opt`."]
Let(ExprLet),
#[doc = r#" A literal in place of an expression: `1`, `"foo"`."#]
Lit(ExprLit),
#[doc = r" Conditionless loop: `loop { ... }`."]
Loop(ExprLoop),
#[doc = r#" A macro invocation expression: `format!("{}", q)`."#]
Macro(ExprMacro),
#[doc =
r" A `match` expression: `match n { Some(n) => {}, None => {} }`."]
Match(ExprMatch),
#[doc = r" A method call expression: `x.foo::<T>(a, b)`."]
MethodCall(ExprMethodCall),
#[doc = r" A parenthesized expression: `(a + b)`."]
Paren(ExprParen),
#[doc = r" A path like `core::mem::replace` possibly containing generic"]
#[doc = r" parameters and a qualified self-type."]
#[doc = r""]
#[doc = r" A plain identifier like `x` is a path of length 1."]
Path(ExprPath),
#[doc = r" A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`."]
Range(ExprRange),
#[doc = r" Address-of operation: `&raw const place` or `&raw mut place`."]
RawAddr(ExprRawAddr),
#[doc = r" A referencing operation: `&a` or `&mut a`."]
Reference(ExprReference),
#[doc =
r" An array literal constructed from one repeated element: `[0u8; N]`."]
Repeat(ExprRepeat),
#[doc = r" A `return`, with an optional value to be returned."]
Return(ExprReturn),
#[doc = r" A struct literal expression: `Point { x: 1, y: 1 }`."]
#[doc = r""]
#[doc =
r" The `rest` provides the value of the remaining fields as in `S { a:"]
#[doc = r" 1, b: 1, ..rest }`."]
Struct(ExprStruct),
#[doc = r" A try-expression: `expr?`."]
Try(ExprTry),
#[doc = r" A try block: `try { ... }`."]
TryBlock(ExprTryBlock),
#[doc = r" A tuple expression: `(a, b, c, d)`."]
Tuple(ExprTuple),
#[doc = r" A unary operation: `!x`, `*x`."]
Unary(ExprUnary),
#[doc = r" An unsafe block: `unsafe { ... }`."]
Unsafe(ExprUnsafe),
#[doc = r" Tokens in expression position not interpreted by Syn."]
Verbatim(TokenStream),
#[doc = r" A while loop: `while expr { ... }`."]
While(ExprWhile),
#[doc = r" A yield expression: `yield expr`."]
Yield(ExprYield),
}
impl From<ExprArray> for Expr {
fn from(e: ExprArray) -> Expr { Expr::Array(e) }
}
impl From<ExprAssign> for Expr {
fn from(e: ExprAssign) -> Expr { Expr::Assign(e) }
}
impl From<ExprAsync> for Expr {
fn from(e: ExprAsync) -> Expr { Expr::Async(e) }
}
impl From<ExprAwait> for Expr {
fn from(e: ExprAwait) -> Expr { Expr::Await(e) }
}
impl From<ExprBinary> for Expr {
fn from(e: ExprBinary) -> Expr { Expr::Binary(e) }
}
impl From<ExprBlock> for Expr {
fn from(e: ExprBlock) -> Expr { Expr::Block(e) }
}
impl From<ExprBreak> for Expr {
fn from(e: ExprBreak) -> Expr { Expr::Break(e) }
}
impl From<ExprCall> for Expr {
fn from(e: ExprCall) -> Expr { Expr::Call(e) }
}
impl From<ExprCast> for Expr {
fn from(e: ExprCast) -> Expr { Expr::Cast(e) }
}
impl From<ExprClosure> for Expr {
fn from(e: ExprClosure) -> Expr { Expr::Closure(e) }
}
impl From<ExprConst> for Expr {
fn from(e: ExprConst) -> Expr { Expr::Const(e) }
}
impl From<ExprContinue> for Expr {
fn from(e: ExprContinue) -> Expr { Expr::Continue(e) }
}
impl From<ExprField> for Expr {
fn from(e: ExprField) -> Expr { Expr::Field(e) }
}
impl From<ExprForLoop> for Expr {
fn from(e: ExprForLoop) -> Expr { Expr::ForLoop(e) }
}
impl From<ExprGroup> for Expr {
fn from(e: ExprGroup) -> Expr { Expr::Group(e) }
}
impl From<ExprIf> for Expr {
fn from(e: ExprIf) -> Expr { Expr::If(e) }
}
impl From<ExprIndex> for Expr {
fn from(e: ExprIndex) -> Expr { Expr::Index(e) }
}
impl From<ExprInfer> for Expr {
fn from(e: ExprInfer) -> Expr { Expr::Infer(e) }
}
impl From<ExprLet> for Expr {
fn from(e: ExprLet) -> Expr { Expr::Let(e) }
}
impl From<ExprLit> for Expr {
fn from(e: ExprLit) -> Expr { Expr::Lit(e) }
}
impl From<ExprLoop> for Expr {
fn from(e: ExprLoop) -> Expr { Expr::Loop(e) }
}
impl From<ExprMacro> for Expr {
fn from(e: ExprMacro) -> Expr { Expr::Macro(e) }
}
impl From<ExprMatch> for Expr {
fn from(e: ExprMatch) -> Expr { Expr::Match(e) }
}
impl From<ExprMethodCall> for Expr {
fn from(e: ExprMethodCall) -> Expr { Expr::MethodCall(e) }
}
impl From<ExprParen> for Expr {
fn from(e: ExprParen) -> Expr { Expr::Paren(e) }
}
impl From<ExprPath> for Expr {
fn from(e: ExprPath) -> Expr { Expr::Path(e) }
}
impl From<ExprRange> for Expr {
fn from(e: ExprRange) -> Expr { Expr::Range(e) }
}
impl From<ExprRawAddr> for Expr {
fn from(e: ExprRawAddr) -> Expr { Expr::RawAddr(e) }
}
impl From<ExprReference> for Expr {
fn from(e: ExprReference) -> Expr { Expr::Reference(e) }
}
impl From<ExprRepeat> for Expr {
fn from(e: ExprRepeat) -> Expr { Expr::Repeat(e) }
}
impl From<ExprReturn> for Expr {
fn from(e: ExprReturn) -> Expr { Expr::Return(e) }
}
impl From<ExprStruct> for Expr {
fn from(e: ExprStruct) -> Expr { Expr::Struct(e) }
}
impl From<ExprTry> for Expr {
fn from(e: ExprTry) -> Expr { Expr::Try(e) }
}
impl From<ExprTryBlock> for Expr {
fn from(e: ExprTryBlock) -> Expr { Expr::TryBlock(e) }
}
impl From<ExprTuple> for Expr {
fn from(e: ExprTuple) -> Expr { Expr::Tuple(e) }
}
impl From<ExprUnary> for Expr {
fn from(e: ExprUnary) -> Expr { Expr::Unary(e) }
}
impl From<ExprUnsafe> for Expr {
fn from(e: ExprUnsafe) -> Expr { Expr::Unsafe(e) }
}
impl From<ExprWhile> for Expr {
fn from(e: ExprWhile) -> Expr { Expr::While(e) }
}
impl From<ExprYield> for Expr {
fn from(e: ExprYield) -> Expr { Expr::Yield(e) }
}
impl ::quote::ToTokens for Expr {
fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
match self {
Expr::Array(_e) => _e.to_tokens(tokens),
Expr::Assign(_e) => _e.to_tokens(tokens),
Expr::Async(_e) => _e.to_tokens(tokens),
Expr::Await(_e) => _e.to_tokens(tokens),
Expr::Binary(_e) => _e.to_tokens(tokens),
Expr::Block(_e) => _e.to_tokens(tokens),
Expr::Break(_e) => _e.to_tokens(tokens),
Expr::Call(_e) => _e.to_tokens(tokens),
Expr::Cast(_e) => _e.to_tokens(tokens),
Expr::Closure(_e) => _e.to_tokens(tokens),
Expr::Const(_e) => _e.to_tokens(tokens),
Expr::Continue(_e) => _e.to_tokens(tokens),
Expr::Field(_e) => _e.to_tokens(tokens),
Expr::ForLoop(_e) => _e.to_tokens(tokens),
Expr::Group(_e) => _e.to_tokens(tokens),
Expr::If(_e) => _e.to_tokens(tokens),
Expr::Index(_e) => _e.to_tokens(tokens),
Expr::Infer(_e) => _e.to_tokens(tokens),
Expr::Let(_e) => _e.to_tokens(tokens),
Expr::Lit(_e) => _e.to_tokens(tokens),
Expr::Loop(_e) => _e.to_tokens(tokens),
Expr::Macro(_e) => _e.to_tokens(tokens),
Expr::Match(_e) => _e.to_tokens(tokens),
Expr::MethodCall(_e) => _e.to_tokens(tokens),
Expr::Paren(_e) => _e.to_tokens(tokens),
Expr::Path(_e) => _e.to_tokens(tokens),
Expr::Range(_e) => _e.to_tokens(tokens),
Expr::RawAddr(_e) => _e.to_tokens(tokens),
Expr::Reference(_e) => _e.to_tokens(tokens),
Expr::Repeat(_e) => _e.to_tokens(tokens),
Expr::Return(_e) => _e.to_tokens(tokens),
Expr::Struct(_e) => _e.to_tokens(tokens),
Expr::Try(_e) => _e.to_tokens(tokens),
Expr::TryBlock(_e) => _e.to_tokens(tokens),
Expr::Tuple(_e) => _e.to_tokens(tokens),
Expr::Unary(_e) => _e.to_tokens(tokens),
Expr::Unsafe(_e) => _e.to_tokens(tokens),
Expr::Verbatim(_e) => _e.to_tokens(tokens),
Expr::While(_e) => _e.to_tokens(tokens),
Expr::Yield(_e) => _e.to_tokens(tokens),
}
}
}ast_enum_of_structs! {
38 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
113 #[non_exhaustive]
114 pub enum Expr {
115 Array(ExprArray),
117
118 Assign(ExprAssign),
120
121 Async(ExprAsync),
123
124 Await(ExprAwait),
126
127 Binary(ExprBinary),
129
130 Block(ExprBlock),
132
133 Break(ExprBreak),
136
137 Call(ExprCall),
139
140 Cast(ExprCast),
142
143 Closure(ExprClosure),
145
146 Const(ExprConst),
148
149 Continue(ExprContinue),
151
152 Field(ExprField),
155
156 ForLoop(ExprForLoop),
158
159 Group(ExprGroup),
165
166 If(ExprIf),
172
173 Index(ExprIndex),
175
176 Infer(ExprInfer),
178
179 Let(ExprLet),
181
182 Lit(ExprLit),
184
185 Loop(ExprLoop),
187
188 Macro(ExprMacro),
190
191 Match(ExprMatch),
193
194 MethodCall(ExprMethodCall),
196
197 Paren(ExprParen),
199
200 Path(ExprPath),
205
206 Range(ExprRange),
208
209 RawAddr(ExprRawAddr),
211
212 Reference(ExprReference),
214
215 Repeat(ExprRepeat),
217
218 Return(ExprReturn),
220
221 Struct(ExprStruct),
226
227 Try(ExprTry),
229
230 TryBlock(ExprTryBlock),
232
233 Tuple(ExprTuple),
235
236 Unary(ExprUnary),
238
239 Unsafe(ExprUnsafe),
241
242 Verbatim(TokenStream),
244
245 While(ExprWhile),
247
248 Yield(ExprYield),
250
251 }
269}
270
271#[doc = r" A slice literal expression: `[a, b, c, d]`."]
pub struct ExprArray {
pub attrs: Vec<Attribute>,
pub bracket_token: token::Bracket,
pub elems: Punctuated<Expr, crate::token::Comma>,
}ast_struct! {
272 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
274 pub struct ExprArray #full {
275 pub attrs: Vec<Attribute>,
276 pub bracket_token: token::Bracket,
277 pub elems: Punctuated<Expr, Token![,]>,
278 }
279}
280
281#[doc = r" An assignment expression: `a = compute()`."]
pub struct ExprAssign {
pub attrs: Vec<Attribute>,
pub left: Box<Expr>,
pub eq_token: crate::token::Eq,
pub right: Box<Expr>,
}ast_struct! {
282 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
284 pub struct ExprAssign #full {
285 pub attrs: Vec<Attribute>,
286 pub left: Box<Expr>,
287 pub eq_token: Token![=],
288 pub right: Box<Expr>,
289 }
290}
291
292#[doc = r" An async block: `async { ... }`."]
pub struct ExprAsync {
pub attrs: Vec<Attribute>,
pub async_token: crate::token::Async,
pub capture: Option<crate::token::Move>,
pub block: Block,
}ast_struct! {
293 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
295 pub struct ExprAsync #full {
296 pub attrs: Vec<Attribute>,
297 pub async_token: Token![async],
298 pub capture: Option<Token![move]>,
299 pub block: Block,
300 }
301}
302
303#[doc = r" An await expression: `fut.await`."]
pub struct ExprAwait {
pub attrs: Vec<Attribute>,
pub base: Box<Expr>,
pub dot_token: crate::token::Dot,
pub await_token: crate::token::Await,
}ast_struct! {
304 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
306 pub struct ExprAwait #full {
307 pub attrs: Vec<Attribute>,
308 pub base: Box<Expr>,
309 pub dot_token: Token![.],
310 pub await_token: Token![await],
311 }
312}
313
314#[doc = r" A binary operation: `a + b`, `a += b`."]
pub struct ExprBinary {
pub attrs: Vec<Attribute>,
pub left: Box<Expr>,
pub op: BinOp,
pub right: Box<Expr>,
}ast_struct! {
315 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
317 pub struct ExprBinary {
318 pub attrs: Vec<Attribute>,
319 pub left: Box<Expr>,
320 pub op: BinOp,
321 pub right: Box<Expr>,
322 }
323}
324
325#[doc = r" A blocked scope: `{ ... }`."]
pub struct ExprBlock {
pub attrs: Vec<Attribute>,
pub label: Option<Label>,
pub block: Block,
}ast_struct! {
326 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
328 pub struct ExprBlock #full {
329 pub attrs: Vec<Attribute>,
330 pub label: Option<Label>,
331 pub block: Block,
332 }
333}
334
335#[doc = r" A `break`, with an optional label to break and an optional"]
#[doc = r" expression."]
pub struct ExprBreak {
pub attrs: Vec<Attribute>,
pub break_token: crate::token::Break,
pub label: Option<Lifetime>,
pub expr: Option<Box<Expr>>,
}ast_struct! {
336 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
339 pub struct ExprBreak #full {
340 pub attrs: Vec<Attribute>,
341 pub break_token: Token![break],
342 pub label: Option<Lifetime>,
343 pub expr: Option<Box<Expr>>,
344 }
345}
346
347#[doc = r" A function call expression: `invoke(a, b)`."]
pub struct ExprCall {
pub attrs: Vec<Attribute>,
pub func: Box<Expr>,
pub paren_token: token::Paren,
pub args: Punctuated<Expr, crate::token::Comma>,
}ast_struct! {
348 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
350 pub struct ExprCall {
351 pub attrs: Vec<Attribute>,
352 pub func: Box<Expr>,
353 pub paren_token: token::Paren,
354 pub args: Punctuated<Expr, Token![,]>,
355 }
356}
357
358#[doc = r" A cast expression: `foo as f64`."]
pub struct ExprCast {
pub attrs: Vec<Attribute>,
pub expr: Box<Expr>,
pub as_token: crate::token::As,
pub ty: Box<Type>,
}ast_struct! {
359 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
361 pub struct ExprCast {
362 pub attrs: Vec<Attribute>,
363 pub expr: Box<Expr>,
364 pub as_token: Token![as],
365 pub ty: Box<Type>,
366 }
367}
368
369#[doc = r" A closure expression: `|a, b| a + b`."]
pub struct ExprClosure {
pub attrs: Vec<Attribute>,
pub lifetimes: Option<BoundLifetimes>,
pub constness: Option<crate::token::Const>,
pub movability: Option<crate::token::Static>,
pub asyncness: Option<crate::token::Async>,
pub capture: Option<crate::token::Move>,
pub or1_token: crate::token::Or,
pub inputs: Punctuated<Pat, crate::token::Comma>,
pub or2_token: crate::token::Or,
pub output: ReturnType,
pub body: Box<Expr>,
}ast_struct! {
370 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
372 pub struct ExprClosure #full {
373 pub attrs: Vec<Attribute>,
374 pub lifetimes: Option<BoundLifetimes>,
375 pub constness: Option<Token![const]>,
376 pub movability: Option<Token![static]>,
377 pub asyncness: Option<Token![async]>,
378 pub capture: Option<Token![move]>,
379 pub or1_token: Token![|],
380 pub inputs: Punctuated<Pat, Token![,]>,
381 pub or2_token: Token![|],
382 pub output: ReturnType,
383 pub body: Box<Expr>,
384 }
385}
386
387#[doc = r" A const block: `const { ... }`."]
pub struct ExprConst {
pub attrs: Vec<Attribute>,
pub const_token: crate::token::Const,
pub block: Block,
}ast_struct! {
388 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
390 pub struct ExprConst #full {
391 pub attrs: Vec<Attribute>,
392 pub const_token: Token![const],
393 pub block: Block,
394 }
395}
396
397#[doc = r" A `continue`, with an optional label."]
pub struct ExprContinue {
pub attrs: Vec<Attribute>,
pub continue_token: crate::token::Continue,
pub label: Option<Lifetime>,
}ast_struct! {
398 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
400 pub struct ExprContinue #full {
401 pub attrs: Vec<Attribute>,
402 pub continue_token: Token![continue],
403 pub label: Option<Lifetime>,
404 }
405}
406
407#[doc = r" Access of a named struct field (`obj.k`) or unnamed tuple struct"]
#[doc = r" field (`obj.0`)."]
pub struct ExprField {
pub attrs: Vec<Attribute>,
pub base: Box<Expr>,
pub dot_token: crate::token::Dot,
pub member: Member,
}ast_struct! {
408 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
411 pub struct ExprField {
412 pub attrs: Vec<Attribute>,
413 pub base: Box<Expr>,
414 pub dot_token: Token![.],
415 pub member: Member,
416 }
417}
418
419#[doc = r" A for loop: `for pat in expr { ... }`."]
pub struct ExprForLoop {
pub attrs: Vec<Attribute>,
pub label: Option<Label>,
pub for_token: crate::token::For,
pub pat: Box<Pat>,
pub in_token: crate::token::In,
pub expr: Box<Expr>,
pub body: Block,
}ast_struct! {
420 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
422 pub struct ExprForLoop #full {
423 pub attrs: Vec<Attribute>,
424 pub label: Option<Label>,
425 pub for_token: Token![for],
426 pub pat: Box<Pat>,
427 pub in_token: Token![in],
428 pub expr: Box<Expr>,
429 pub body: Block,
430 }
431}
432
433#[doc = r" An expression contained within invisible delimiters."]
#[doc = r""]
#[doc =
r" This variant is important for faithfully representing the precedence"]
#[doc = r" of expressions and is related to `None`-delimited spans in a"]
#[doc = r" `TokenStream`."]
pub struct ExprGroup {
pub attrs: Vec<Attribute>,
pub group_token: token::Group,
pub expr: Box<Expr>,
}ast_struct! {
434 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
440 pub struct ExprGroup {
441 pub attrs: Vec<Attribute>,
442 pub group_token: token::Group,
443 pub expr: Box<Expr>,
444 }
445}
446
447#[doc =
r" An `if` expression with an optional `else` block: `if expr { ... }"]
#[doc = r" else { ... }`."]
#[doc = r""]
#[doc = r" The `else` branch expression may only be an `If` or `Block`"]
#[doc = r" expression, not any of the other types of expression."]
pub struct ExprIf {
pub attrs: Vec<Attribute>,
pub if_token: crate::token::If,
pub cond: Box<Expr>,
pub then_branch: Block,
pub else_branch: Option<(crate::token::Else, Box<Expr>)>,
}ast_struct! {
448 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
454 pub struct ExprIf #full {
455 pub attrs: Vec<Attribute>,
456 pub if_token: Token![if],
457 pub cond: Box<Expr>,
458 pub then_branch: Block,
459 pub else_branch: Option<(Token![else], Box<Expr>)>,
460 }
461}
462
463#[doc = r" A square bracketed indexing expression: `vector[2]`."]
pub struct ExprIndex {
pub attrs: Vec<Attribute>,
pub expr: Box<Expr>,
pub bracket_token: token::Bracket,
pub index: Box<Expr>,
}ast_struct! {
464 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
466 pub struct ExprIndex {
467 pub attrs: Vec<Attribute>,
468 pub expr: Box<Expr>,
469 pub bracket_token: token::Bracket,
470 pub index: Box<Expr>,
471 }
472}
473
474#[doc = r" The inferred value of a const generic argument, denoted `_`."]
pub struct ExprInfer {
pub attrs: Vec<Attribute>,
pub underscore_token: crate::token::Underscore,
}ast_struct! {
475 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
477 pub struct ExprInfer #full {
478 pub attrs: Vec<Attribute>,
479 pub underscore_token: Token![_],
480 }
481}
482
483#[doc = r" A `let` guard: `let Some(x) = opt`."]
pub struct ExprLet {
pub attrs: Vec<Attribute>,
pub let_token: crate::token::Let,
pub pat: Box<Pat>,
pub eq_token: crate::token::Eq,
pub expr: Box<Expr>,
}ast_struct! {
484 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
486 pub struct ExprLet #full {
487 pub attrs: Vec<Attribute>,
488 pub let_token: Token![let],
489 pub pat: Box<Pat>,
490 pub eq_token: Token![=],
491 pub expr: Box<Expr>,
492 }
493}
494
495#[doc = r#" A literal in place of an expression: `1`, `"foo"`."#]
pub struct ExprLit {
pub attrs: Vec<Attribute>,
pub lit: Lit,
}ast_struct! {
496 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
498 pub struct ExprLit {
499 pub attrs: Vec<Attribute>,
500 pub lit: Lit,
501 }
502}
503
504#[doc = r" Conditionless loop: `loop { ... }`."]
pub struct ExprLoop {
pub attrs: Vec<Attribute>,
pub label: Option<Label>,
pub loop_token: crate::token::Loop,
pub body: Block,
}ast_struct! {
505 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
507 pub struct ExprLoop #full {
508 pub attrs: Vec<Attribute>,
509 pub label: Option<Label>,
510 pub loop_token: Token![loop],
511 pub body: Block,
512 }
513}
514
515#[doc = r#" A macro invocation expression: `format!("{}", q)`."#]
pub struct ExprMacro {
pub attrs: Vec<Attribute>,
pub mac: Macro,
}ast_struct! {
516 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
518 pub struct ExprMacro {
519 pub attrs: Vec<Attribute>,
520 pub mac: Macro,
521 }
522}
523
524#[doc = r" A `match` expression: `match n { Some(n) => {}, None => {} }`."]
pub struct ExprMatch {
pub attrs: Vec<Attribute>,
pub match_token: crate::token::Match,
pub expr: Box<Expr>,
pub brace_token: token::Brace,
pub arms: Vec<Arm>,
}ast_struct! {
525 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
527 pub struct ExprMatch #full {
528 pub attrs: Vec<Attribute>,
529 pub match_token: Token![match],
530 pub expr: Box<Expr>,
531 pub brace_token: token::Brace,
532 pub arms: Vec<Arm>,
533 }
534}
535
536#[doc = r" A method call expression: `x.foo::<T>(a, b)`."]
pub struct ExprMethodCall {
pub attrs: Vec<Attribute>,
pub receiver: Box<Expr>,
pub dot_token: crate::token::Dot,
pub method: Ident,
pub turbofish: Option<AngleBracketedGenericArguments>,
pub paren_token: token::Paren,
pub args: Punctuated<Expr, crate::token::Comma>,
}ast_struct! {
537 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
539 pub struct ExprMethodCall {
540 pub attrs: Vec<Attribute>,
541 pub receiver: Box<Expr>,
542 pub dot_token: Token![.],
543 pub method: Ident,
544 pub turbofish: Option<AngleBracketedGenericArguments>,
545 pub paren_token: token::Paren,
546 pub args: Punctuated<Expr, Token![,]>,
547 }
548}
549
550#[doc = r" A parenthesized expression: `(a + b)`."]
pub struct ExprParen {
pub attrs: Vec<Attribute>,
pub paren_token: token::Paren,
pub expr: Box<Expr>,
}ast_struct! {
551 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
553 pub struct ExprParen {
554 pub attrs: Vec<Attribute>,
555 pub paren_token: token::Paren,
556 pub expr: Box<Expr>,
557 }
558}
559
560#[doc = r" A path like `core::mem::replace` possibly containing generic"]
#[doc = r" parameters and a qualified self-type."]
#[doc = r""]
#[doc = r" A plain identifier like `x` is a path of length 1."]
pub struct ExprPath {
pub attrs: Vec<Attribute>,
pub qself: Option<QSelf>,
pub path: Path,
}ast_struct! {
561 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
566 pub struct ExprPath {
567 pub attrs: Vec<Attribute>,
568 pub qself: Option<QSelf>,
569 pub path: Path,
570 }
571}
572
573#[doc = r" A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`."]
pub struct ExprRange {
pub attrs: Vec<Attribute>,
pub start: Option<Box<Expr>>,
pub limits: RangeLimits,
pub end: Option<Box<Expr>>,
}ast_struct! {
574 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
576 pub struct ExprRange #full {
577 pub attrs: Vec<Attribute>,
578 pub start: Option<Box<Expr>>,
579 pub limits: RangeLimits,
580 pub end: Option<Box<Expr>>,
581 }
582}
583
584#[doc = r" Address-of operation: `&raw const place` or `&raw mut place`."]
pub struct ExprRawAddr {
pub attrs: Vec<Attribute>,
pub and_token: crate::token::And,
pub raw: crate::token::Raw,
pub mutability: PointerMutability,
pub expr: Box<Expr>,
}ast_struct! {
585 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
587 pub struct ExprRawAddr #full {
588 pub attrs: Vec<Attribute>,
589 pub and_token: Token![&],
590 pub raw: Token![raw],
591 pub mutability: PointerMutability,
592 pub expr: Box<Expr>,
593 }
594}
595
596#[doc = r" A referencing operation: `&a` or `&mut a`."]
pub struct ExprReference {
pub attrs: Vec<Attribute>,
pub and_token: crate::token::And,
pub mutability: Option<crate::token::Mut>,
pub expr: Box<Expr>,
}ast_struct! {
597 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
599 pub struct ExprReference {
600 pub attrs: Vec<Attribute>,
601 pub and_token: Token![&],
602 pub mutability: Option<Token![mut]>,
603 pub expr: Box<Expr>,
604 }
605}
606
607#[doc =
r" An array literal constructed from one repeated element: `[0u8; N]`."]
pub struct ExprRepeat {
pub attrs: Vec<Attribute>,
pub bracket_token: token::Bracket,
pub expr: Box<Expr>,
pub semi_token: crate::token::Semi,
pub len: Box<Expr>,
}ast_struct! {
608 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
610 pub struct ExprRepeat #full {
611 pub attrs: Vec<Attribute>,
612 pub bracket_token: token::Bracket,
613 pub expr: Box<Expr>,
614 pub semi_token: Token![;],
615 pub len: Box<Expr>,
616 }
617}
618
619#[doc = r" A `return`, with an optional value to be returned."]
pub struct ExprReturn {
pub attrs: Vec<Attribute>,
pub return_token: crate::token::Return,
pub expr: Option<Box<Expr>>,
}ast_struct! {
620 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
622 pub struct ExprReturn #full {
623 pub attrs: Vec<Attribute>,
624 pub return_token: Token![return],
625 pub expr: Option<Box<Expr>>,
626 }
627}
628
629#[doc = r" A struct literal expression: `Point { x: 1, y: 1 }`."]
#[doc = r""]
#[doc =
r" The `rest` provides the value of the remaining fields as in `S { a:"]
#[doc = r" 1, b: 1, ..rest }`."]
pub struct ExprStruct {
pub attrs: Vec<Attribute>,
pub qself: Option<QSelf>,
pub path: Path,
pub brace_token: token::Brace,
pub fields: Punctuated<FieldValue, crate::token::Comma>,
pub dot2_token: Option<crate::token::DotDot>,
pub rest: Option<Box<Expr>>,
}ast_struct! {
630 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
635 pub struct ExprStruct {
636 pub attrs: Vec<Attribute>,
637 pub qself: Option<QSelf>,
638 pub path: Path,
639 pub brace_token: token::Brace,
640 pub fields: Punctuated<FieldValue, Token![,]>,
641 pub dot2_token: Option<Token![..]>,
642 pub rest: Option<Box<Expr>>,
643 }
644}
645
646#[doc = r" A try-expression: `expr?`."]
pub struct ExprTry {
pub attrs: Vec<Attribute>,
pub expr: Box<Expr>,
pub question_token: crate::token::Question,
}ast_struct! {
647 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
649 pub struct ExprTry #full {
650 pub attrs: Vec<Attribute>,
651 pub expr: Box<Expr>,
652 pub question_token: Token![?],
653 }
654}
655
656#[doc = r" A try block: `try { ... }`."]
pub struct ExprTryBlock {
pub attrs: Vec<Attribute>,
pub try_token: crate::token::Try,
pub block: Block,
}ast_struct! {
657 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
659 pub struct ExprTryBlock #full {
660 pub attrs: Vec<Attribute>,
661 pub try_token: Token![try],
662 pub block: Block,
663 }
664}
665
666#[doc = r" A tuple expression: `(a, b, c, d)`."]
pub struct ExprTuple {
pub attrs: Vec<Attribute>,
pub paren_token: token::Paren,
pub elems: Punctuated<Expr, crate::token::Comma>,
}ast_struct! {
667 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
669 pub struct ExprTuple {
670 pub attrs: Vec<Attribute>,
671 pub paren_token: token::Paren,
672 pub elems: Punctuated<Expr, Token![,]>,
673 }
674}
675
676#[doc = r" A unary operation: `!x`, `*x`."]
pub struct ExprUnary {
pub attrs: Vec<Attribute>,
pub op: UnOp,
pub expr: Box<Expr>,
}ast_struct! {
677 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
679 pub struct ExprUnary {
680 pub attrs: Vec<Attribute>,
681 pub op: UnOp,
682 pub expr: Box<Expr>,
683 }
684}
685
686#[doc = r" An unsafe block: `unsafe { ... }`."]
pub struct ExprUnsafe {
pub attrs: Vec<Attribute>,
pub unsafe_token: crate::token::Unsafe,
pub block: Block,
}ast_struct! {
687 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
689 pub struct ExprUnsafe #full {
690 pub attrs: Vec<Attribute>,
691 pub unsafe_token: Token![unsafe],
692 pub block: Block,
693 }
694}
695
696#[doc = r" A while loop: `while expr { ... }`."]
pub struct ExprWhile {
pub attrs: Vec<Attribute>,
pub label: Option<Label>,
pub while_token: crate::token::While,
pub cond: Box<Expr>,
pub body: Block,
}ast_struct! {
697 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
699 pub struct ExprWhile #full {
700 pub attrs: Vec<Attribute>,
701 pub label: Option<Label>,
702 pub while_token: Token![while],
703 pub cond: Box<Expr>,
704 pub body: Block,
705 }
706}
707
708#[doc = r" A yield expression: `yield expr`."]
pub struct ExprYield {
pub attrs: Vec<Attribute>,
pub yield_token: crate::token::Yield,
pub expr: Option<Box<Expr>>,
}ast_struct! {
709 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
711 pub struct ExprYield #full {
712 pub attrs: Vec<Attribute>,
713 pub yield_token: Token![yield],
714 pub expr: Option<Box<Expr>>,
715 }
716}
717
718impl Expr {
719 pub const PLACEHOLDER: Self = Expr::Path(ExprPath {
739 attrs: Vec::new(),
740 qself: None,
741 path: Path {
742 leading_colon: None,
743 segments: Punctuated::new(),
744 },
745 });
746
747 #[cfg(all(feature = "full", feature = "parsing"))]
829 #[cfg_attr(docsrs, doc(cfg(all(feature = "full", feature = "parsing"))))]
830 pub fn parse_without_eager_brace(input: ParseStream) -> Result<Expr> {
831 parsing::ambiguous_expr(input, parsing::AllowStruct(false))
832 }
833
834 #[cfg(all(feature = "full", feature = "parsing"))]
891 #[cfg_attr(docsrs, doc(cfg(all(feature = "full", feature = "parsing"))))]
892 pub fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
893 parsing::parse_with_earlier_boundary_rule(input)
894 }
895
896 #[cfg(feature = "parsing")]
907 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
908 pub fn peek(input: ParseStream) -> bool {
909 input.peek(Ident::peek_any) && !input.peek(crate::token::AsToken![as]) || input.peek(token::Paren) || input.peek(token::Bracket) || input.peek(token::Brace) || input.peek(Lit) || input.peek(crate::token::NotToken![!]) && !input.peek(crate::token::NeToken![!=]) || input.peek(crate::token::MinusToken![-]) && !input.peek(crate::token::MinusEqToken![-=]) && !input.peek(crate::token::RArrowToken![->]) || input.peek(crate::token::StarToken![*]) && !input.peek(crate::token::StarEqToken![*=]) || input.peek(crate::token::OrToken![|]) && !input.peek(crate::token::OrEqToken![|=]) || input.peek(crate::token::AndToken![&]) && !input.peek(crate::token::AndEqToken![&=]) || input.peek(crate::token::DotDotToken![..]) || input.peek(crate::token::LtToken![<]) && !input.peek(crate::token::LeToken![<=]) && !input.peek(crate::token::ShlEqToken![<<=]) || input.peek(crate::token::PathSepToken![::]) || input.peek(Lifetime) || input.peek(crate::token::PoundToken![#]) }
925
926 #[cfg(all(feature = "parsing", feature = "full"))]
927 pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
928 match self {
929 Expr::Array(ExprArray { attrs, .. })
930 | Expr::Assign(ExprAssign { attrs, .. })
931 | Expr::Async(ExprAsync { attrs, .. })
932 | Expr::Await(ExprAwait { attrs, .. })
933 | Expr::Binary(ExprBinary { attrs, .. })
934 | Expr::Block(ExprBlock { attrs, .. })
935 | Expr::Break(ExprBreak { attrs, .. })
936 | Expr::Call(ExprCall { attrs, .. })
937 | Expr::Cast(ExprCast { attrs, .. })
938 | Expr::Closure(ExprClosure { attrs, .. })
939 | Expr::Const(ExprConst { attrs, .. })
940 | Expr::Continue(ExprContinue { attrs, .. })
941 | Expr::Field(ExprField { attrs, .. })
942 | Expr::ForLoop(ExprForLoop { attrs, .. })
943 | Expr::Group(ExprGroup { attrs, .. })
944 | Expr::If(ExprIf { attrs, .. })
945 | Expr::Index(ExprIndex { attrs, .. })
946 | Expr::Infer(ExprInfer { attrs, .. })
947 | Expr::Let(ExprLet { attrs, .. })
948 | Expr::Lit(ExprLit { attrs, .. })
949 | Expr::Loop(ExprLoop { attrs, .. })
950 | Expr::Macro(ExprMacro { attrs, .. })
951 | Expr::Match(ExprMatch { attrs, .. })
952 | Expr::MethodCall(ExprMethodCall { attrs, .. })
953 | Expr::Paren(ExprParen { attrs, .. })
954 | Expr::Path(ExprPath { attrs, .. })
955 | Expr::Range(ExprRange { attrs, .. })
956 | Expr::RawAddr(ExprRawAddr { attrs, .. })
957 | Expr::Reference(ExprReference { attrs, .. })
958 | Expr::Repeat(ExprRepeat { attrs, .. })
959 | Expr::Return(ExprReturn { attrs, .. })
960 | Expr::Struct(ExprStruct { attrs, .. })
961 | Expr::Try(ExprTry { attrs, .. })
962 | Expr::TryBlock(ExprTryBlock { attrs, .. })
963 | Expr::Tuple(ExprTuple { attrs, .. })
964 | Expr::Unary(ExprUnary { attrs, .. })
965 | Expr::Unsafe(ExprUnsafe { attrs, .. })
966 | Expr::While(ExprWhile { attrs, .. })
967 | Expr::Yield(ExprYield { attrs, .. }) => mem::replace(attrs, new),
968 Expr::Verbatim(_) => Vec::new(),
969 }
970 }
971}
972
973#[doc =
r" A struct or tuple struct field accessed in a struct literal or field"]
#[doc = r" expression."]
pub enum Member {
#[doc = r" A named field like `self.x`."]
Named(Ident),
#[doc = r" An unnamed field like `self.0`."]
Unnamed(Index),
}ast_enum! {
974 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
977 pub enum Member {
978 Named(Ident),
980 Unnamed(Index),
982 }
983}
984
985impl From<Ident> for Member {
986 fn from(ident: Ident) -> Member {
987 Member::Named(ident)
988 }
989}
990
991impl From<Index> for Member {
992 fn from(index: Index) -> Member {
993 Member::Unnamed(index)
994 }
995}
996
997impl From<usize> for Member {
998 fn from(index: usize) -> Member {
999 Member::Unnamed(Index::from(index))
1000 }
1001}
1002
1003impl Eq for Member {}
1004
1005impl PartialEq for Member {
1006 fn eq(&self, other: &Self) -> bool {
1007 match (self, other) {
1008 (Member::Named(this), Member::Named(other)) => this == other,
1009 (Member::Unnamed(this), Member::Unnamed(other)) => this == other,
1010 _ => false,
1011 }
1012 }
1013}
1014
1015impl Hash for Member {
1016 fn hash<H: Hasher>(&self, state: &mut H) {
1017 match self {
1018 Member::Named(m) => m.hash(state),
1019 Member::Unnamed(m) => m.hash(state),
1020 }
1021 }
1022}
1023
1024#[cfg(feature = "printing")]
1025impl IdentFragment for Member {
1026 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1027 match self {
1028 Member::Named(m) => Display::fmt(m, formatter),
1029 Member::Unnamed(m) => Display::fmt(&m.index, formatter),
1030 }
1031 }
1032
1033 fn span(&self) -> Option<Span> {
1034 match self {
1035 Member::Named(m) => Some(m.span()),
1036 Member::Unnamed(m) => Some(m.span),
1037 }
1038 }
1039}
1040
1041#[cfg(any(feature = "parsing", feature = "printing"))]
1042impl Member {
1043 pub(crate) fn is_named(&self) -> bool {
1044 match self {
1045 Member::Named(_) => true,
1046 Member::Unnamed(_) => false,
1047 }
1048 }
1049}
1050
1051#[doc = r" The index of an unnamed tuple struct field."]
pub struct Index {
pub index: u32,
pub span: Span,
}ast_struct! {
1052 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
1054 pub struct Index {
1055 pub index: u32,
1056 pub span: Span,
1057 }
1058}
1059
1060impl From<usize> for Index {
1061 fn from(index: usize) -> Index {
1062 if !(index < u32::MAX as usize) {
::core::panicking::panic("assertion failed: index < u32::MAX as usize")
};assert!(index < u32::MAX as usize);
1063 Index {
1064 index: index as u32,
1065 span: Span::call_site(),
1066 }
1067 }
1068}
1069
1070impl Eq for Index {}
1071
1072impl PartialEq for Index {
1073 fn eq(&self, other: &Self) -> bool {
1074 self.index == other.index
1075 }
1076}
1077
1078impl Hash for Index {
1079 fn hash<H: Hasher>(&self, state: &mut H) {
1080 self.index.hash(state);
1081 }
1082}
1083
1084#[cfg(feature = "printing")]
1085impl IdentFragment for Index {
1086 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1087 Display::fmt(&self.index, formatter)
1088 }
1089
1090 fn span(&self) -> Option<Span> {
1091 Some(self.span)
1092 }
1093}
1094
1095#[doc = r" A field-value pair in a struct literal."]
pub struct FieldValue {
pub attrs: Vec<Attribute>,
pub member: Member,
#[doc = r" The colon in `Struct { x: x }`. If written in shorthand like"]
#[doc = r" `Struct { x }`, there is no colon."]
pub colon_token: Option<crate::token::Colon>,
pub expr: Expr,
}ast_struct! {
1096 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
1098 pub struct FieldValue {
1099 pub attrs: Vec<Attribute>,
1100 pub member: Member,
1101
1102 pub colon_token: Option<Token![:]>,
1105
1106 pub expr: Expr,
1107 }
1108}
1109
1110#[cfg(feature = "full")]
1111#[doc = r" A lifetime labeling a `for`, `while`, or `loop`."]
pub struct Label {
pub name: Lifetime,
pub colon_token: crate::token::Colon,
}ast_struct! {
1112 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1114 pub struct Label {
1115 pub name: Lifetime,
1116 pub colon_token: Token![:],
1117 }
1118}
1119
1120#[cfg(feature = "full")]
1121#[doc = r" One arm of a `match` expression: `0..=10 => { return true; }`."]
#[doc = r""]
#[doc = r" As in:"]
#[doc = r""]
#[doc = r" ```"]
#[doc = r" # fn f() -> bool {"]
#[doc = r" # let n = 0;"]
#[doc = r" match n {"]
#[doc = r" 0..=10 => {"]
#[doc = r" return true;"]
#[doc = r" }"]
#[doc = r" // ..."]
#[doc = r" # _ => {}"]
#[doc = r" }"]
#[doc = r" # false"]
#[doc = r" # }"]
#[doc = r" ```"]
pub struct Arm {
pub attrs: Vec<Attribute>,
pub pat: Pat,
pub guard: Option<(crate::token::If, Box<Expr>)>,
pub fat_arrow_token: crate::token::FatArrow,
pub body: Box<Expr>,
pub comma: Option<crate::token::Comma>,
}ast_struct! {
1122 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1140 pub struct Arm {
1141 pub attrs: Vec<Attribute>,
1142 pub pat: Pat,
1143 pub guard: Option<(Token![if], Box<Expr>)>,
1144 pub fat_arrow_token: Token![=>],
1145 pub body: Box<Expr>,
1146 pub comma: Option<Token![,]>,
1147 }
1148}
1149
1150#[cfg(feature = "full")]
1151#[doc = r" Limit types of a range, inclusive or exclusive."]
pub enum RangeLimits {
#[doc = r" Inclusive at the beginning, exclusive at the end."]
HalfOpen(crate::token::DotDot),
#[doc = r" Inclusive at the beginning and end."]
Closed(crate::token::DotDotEq),
}ast_enum! {
1152 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1154 pub enum RangeLimits {
1155 HalfOpen(Token![..]),
1157 Closed(Token![..=]),
1159 }
1160}
1161
1162#[cfg(feature = "full")]
1163#[doc =
r" Mutability of a raw pointer (`*const T`, `*mut T`), in which non-mutable"]
#[doc = r" isn't the implicit default."]
pub enum PointerMutability {
Const(crate::token::Const),
Mut(crate::token::Mut),
}ast_enum! {
1164 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1167 pub enum PointerMutability {
1168 Const(Token![const]),
1169 Mut(Token![mut]),
1170 }
1171}
1172
1173#[cfg(feature = "parsing")]
1174pub(crate) mod parsing {
1175 #[cfg(feature = "full")]
1176 use crate::attr;
1177 use crate::attr::Attribute;
1178 #[cfg(feature = "full")]
1179 use crate::classify;
1180 use crate::error::{Error, Result};
1181 #[cfg(feature = "full")]
1182 use crate::expr::{
1183 Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
1184 ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
1185 ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
1186 ExprWhile, ExprYield, Label, PointerMutability, RangeLimits,
1187 };
1188 use crate::expr::{
1189 Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
1190 ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
1191 FieldValue, Index, Member,
1192 };
1193 #[cfg(feature = "full")]
1194 use crate::generics::{self, BoundLifetimes};
1195 use crate::ident::Ident;
1196 #[cfg(feature = "full")]
1197 use crate::lifetime::Lifetime;
1198 use crate::lit::{Lit, LitFloat, LitInt};
1199 use crate::mac::{self, Macro};
1200 use crate::op::BinOp;
1201 use crate::parse::discouraged::Speculative as _;
1202 #[cfg(feature = "full")]
1203 use crate::parse::ParseBuffer;
1204 use crate::parse::{Parse, ParseStream};
1205 #[cfg(feature = "full")]
1206 use crate::pat::{Pat, PatType};
1207 use crate::path::{self, AngleBracketedGenericArguments, Path, QSelf};
1208 use crate::precedence::Precedence;
1209 use crate::punctuated::Punctuated;
1210 #[cfg(feature = "full")]
1211 use crate::stmt::Block;
1212 use crate::token;
1213 use crate::ty;
1214 #[cfg(feature = "full")]
1215 use crate::ty::{ReturnType, Type};
1216 use crate::verbatim;
1217 use alloc::boxed::Box;
1218 use alloc::format;
1219 use alloc::string::ToString;
1220 use alloc::vec::Vec;
1221 use core::mem;
1222 #[cfg(feature = "full")]
1223 use proc_macro2::{Span, TokenStream};
1224
1225 #[cfg(feature = "full")]
1231 pub(super) struct AllowStruct(pub bool);
1232
1233 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1234 impl Parse for Expr {
1235 fn parse(input: ParseStream) -> Result<Self> {
1236 ambiguous_expr(
1237 input,
1238 #[cfg(feature = "full")]
1239 AllowStruct(true),
1240 )
1241 }
1242 }
1243
1244 #[cfg(feature = "full")]
1245 pub(super) fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
1246 let mut attrs = input.call(expr_attrs)?;
1247 let mut expr = if input.peek(token::Group) {
1248 let allow_struct = AllowStruct(true);
1249 let atom = expr_group(input, allow_struct)?;
1250 if continue_parsing_early(&atom) {
1251 trailer_helper(input, atom)?
1252 } else {
1253 atom
1254 }
1255 } else if input.peek(crate::token::IfToken![if]) {
1256 Expr::If(input.parse()?)
1257 } else if input.peek(crate::token::WhileToken![while]) {
1258 Expr::While(input.parse()?)
1259 } else if input.peek(crate::token::ForToken![for])
1260 && !generics::parsing::choose_generics_over_qpath_after_keyword(input)
1261 {
1262 Expr::ForLoop(input.parse()?)
1263 } else if input.peek(crate::token::LoopToken![loop]) {
1264 Expr::Loop(input.parse()?)
1265 } else if input.peek(crate::token::MatchToken![match]) {
1266 Expr::Match(input.parse()?)
1267 } else if input.peek(crate::token::TryToken![try]) && input.peek2(token::Brace) {
1268 Expr::TryBlock(input.parse()?)
1269 } else if input.peek(crate::token::UnsafeToken![unsafe]) {
1270 Expr::Unsafe(input.parse()?)
1271 } else if input.peek(crate::token::ConstToken![const]) && input.peek2(token::Brace) {
1272 Expr::Const(input.parse()?)
1273 } else if input.peek(token::Brace) {
1274 Expr::Block(input.parse()?)
1275 } else if input.peek(Lifetime) {
1276 atom_labeled(input)?
1277 } else {
1278 let allow_struct = AllowStruct(true);
1279 unary_expr(input, allow_struct)?
1280 };
1281
1282 if continue_parsing_early(&expr) {
1283 attrs.extend(expr.replace_attrs(Vec::new()));
1284 expr.replace_attrs(attrs);
1285
1286 let allow_struct = AllowStruct(true);
1287 return parse_expr(input, expr, allow_struct, Precedence::MIN);
1288 }
1289
1290 if input.peek(crate::token::DotToken![.]) && !input.peek(crate::token::DotDotToken![..]) || input.peek(crate::token::QuestionToken![?]) {
1291 expr = trailer_helper(input, expr)?;
1292
1293 attrs.extend(expr.replace_attrs(Vec::new()));
1294 expr.replace_attrs(attrs);
1295
1296 let allow_struct = AllowStruct(true);
1297 return parse_expr(input, expr, allow_struct, Precedence::MIN);
1298 }
1299
1300 attrs.extend(expr.replace_attrs(Vec::new()));
1301 expr.replace_attrs(attrs);
1302 Ok(expr)
1303 }
1304
1305 #[cfg(feature = "full")]
1306 impl Copy for AllowStruct {}
1307
1308 #[cfg(feature = "full")]
1309 impl Clone for AllowStruct {
1310 fn clone(&self) -> Self {
1311 *self
1312 }
1313 }
1314
1315 #[cfg(feature = "full")]
1316 fn parse_expr(
1317 input: ParseStream,
1318 mut lhs: Expr,
1319 allow_struct: AllowStruct,
1320 base: Precedence,
1321 ) -> Result<Expr> {
1322 loop {
1323 let ahead = input.fork();
1324 if let Expr::Range(_) = lhs {
1325 break;
1327 } else if let Ok(op) = ahead.parse::<BinOp>() {
1328 let precedence = Precedence::of_binop(&op);
1329 if precedence < base {
1330 break;
1331 }
1332 if precedence == Precedence::Assign {
1333 if let Expr::Range(_) = lhs {
1334 break;
1335 }
1336 }
1337 if precedence == Precedence::Compare {
1338 if let Expr::Binary(lhs) = &lhs {
1339 if Precedence::of_binop(&lhs.op) == Precedence::Compare {
1340 return Err(input.error("comparison operators cannot be chained"));
1341 }
1342 }
1343 }
1344 input.advance_to(&ahead);
1345 let right = parse_binop_rhs(input, allow_struct, precedence)?;
1346 lhs = Expr::Binary(ExprBinary {
1347 attrs: Vec::new(),
1348 left: Box::new(lhs),
1349 op,
1350 right,
1351 });
1352 } else if Precedence::Assign >= base
1353 && input.peek(crate::token::EqToken![=])
1354 && !input.peek(crate::token::FatArrowToken![=>])
1355 && match lhs {
1356 Expr::Range(_) => false,
1357 _ => true,
1358 }
1359 {
1360 let eq_token: crate::token::EqToken![=] = input.parse()?;
1361 let right = parse_binop_rhs(input, allow_struct, Precedence::Assign)?;
1362 lhs = Expr::Assign(ExprAssign {
1363 attrs: Vec::new(),
1364 left: Box::new(lhs),
1365 eq_token,
1366 right,
1367 });
1368 } else if Precedence::Range >= base && input.peek(crate::token::DotDotToken![..]) {
1369 let limits: RangeLimits = input.parse()?;
1370 let end = parse_range_end(input, &limits, allow_struct)?;
1371 lhs = Expr::Range(ExprRange {
1372 attrs: Vec::new(),
1373 start: Some(Box::new(lhs)),
1374 limits,
1375 end,
1376 });
1377 } else if Precedence::Cast >= base && input.peek(crate::token::AsToken![as]) {
1378 let as_token: crate::token::AsToken![as] = input.parse()?;
1379 let allow_plus = false;
1380 let allow_group_generic = false;
1381 let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1382 check_cast(input)?;
1383 lhs = Expr::Cast(ExprCast {
1384 attrs: Vec::new(),
1385 expr: Box::new(lhs),
1386 as_token,
1387 ty: Box::new(ty),
1388 });
1389 } else {
1390 break;
1391 }
1392 }
1393 Ok(lhs)
1394 }
1395
1396 #[cfg(not(feature = "full"))]
1397 fn parse_expr(input: ParseStream, mut lhs: Expr, base: Precedence) -> Result<Expr> {
1398 loop {
1399 let ahead = input.fork();
1400 if let Ok(op) = ahead.parse::<BinOp>() {
1401 let precedence = Precedence::of_binop(&op);
1402 if precedence < base {
1403 break;
1404 }
1405 if precedence == Precedence::Compare {
1406 if let Expr::Binary(lhs) = &lhs {
1407 if Precedence::of_binop(&lhs.op) == Precedence::Compare {
1408 return Err(input.error("comparison operators cannot be chained"));
1409 }
1410 }
1411 }
1412 input.advance_to(&ahead);
1413 let right = parse_binop_rhs(input, precedence)?;
1414 lhs = Expr::Binary(ExprBinary {
1415 attrs: Vec::new(),
1416 left: Box::new(lhs),
1417 op,
1418 right,
1419 });
1420 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1421 let as_token: Token![as] = input.parse()?;
1422 let allow_plus = false;
1423 let allow_group_generic = false;
1424 let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1425 check_cast(input)?;
1426 lhs = Expr::Cast(ExprCast {
1427 attrs: Vec::new(),
1428 expr: Box::new(lhs),
1429 as_token,
1430 ty: Box::new(ty),
1431 });
1432 } else {
1433 break;
1434 }
1435 }
1436 Ok(lhs)
1437 }
1438
1439 fn parse_binop_rhs(
1440 input: ParseStream,
1441 #[cfg(feature = "full")] allow_struct: AllowStruct,
1442 precedence: Precedence,
1443 ) -> Result<Box<Expr>> {
1444 let mut rhs = unary_expr(
1445 input,
1446 #[cfg(feature = "full")]
1447 allow_struct,
1448 )?;
1449 loop {
1450 let next = peek_precedence(input);
1451 if next > precedence || next == precedence && precedence == Precedence::Assign {
1452 let cursor = input.cursor();
1453 rhs = parse_expr(
1454 input,
1455 rhs,
1456 #[cfg(feature = "full")]
1457 allow_struct,
1458 next,
1459 )?;
1460 if cursor == input.cursor() {
1461 break;
1466 }
1467 } else {
1468 break;
1469 }
1470 }
1471 Ok(Box::new(rhs))
1472 }
1473
1474 fn peek_precedence(input: ParseStream) -> Precedence {
1475 if let Ok(op) = input.fork().parse() {
1476 Precedence::of_binop(&op)
1477 } else if input.peek(crate::token::EqToken![=]) && !input.peek(crate::token::FatArrowToken![=>]) {
1478 Precedence::Assign
1479 } else if input.peek(crate::token::DotDotToken![..]) {
1480 Precedence::Range
1481 } else if input.peek(crate::token::AsToken![as]) {
1482 Precedence::Cast
1483 } else {
1484 Precedence::MIN
1485 }
1486 }
1487
1488 pub(super) fn ambiguous_expr(
1490 input: ParseStream,
1491 #[cfg(feature = "full")] allow_struct: AllowStruct,
1492 ) -> Result<Expr> {
1493 let lhs = unary_expr(
1494 input,
1495 #[cfg(feature = "full")]
1496 allow_struct,
1497 )?;
1498 parse_expr(
1499 input,
1500 lhs,
1501 #[cfg(feature = "full")]
1502 allow_struct,
1503 Precedence::MIN,
1504 )
1505 }
1506
1507 #[cfg(feature = "full")]
1508 fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> {
1509 let mut attrs = Vec::new();
1510 while !input.peek(token::Group) && input.peek(crate::token::PoundToken![#]) {
1511 attrs.push(input.call(attr::parsing::single_parse_outer)?);
1512 }
1513 Ok(attrs)
1514 }
1515
1516 #[cfg(feature = "full")]
1521 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1522 let begin = input.fork();
1523 let attrs = input.call(expr_attrs)?;
1524 if input.peek(token::Group) {
1525 return trailer_expr(begin, attrs, input, allow_struct);
1526 }
1527
1528 if input.peek(crate::token::AndToken![&]) {
1529 let and_token: crate::token::AndToken![&] = input.parse()?;
1530 let raw: Option<crate::token::RawToken![raw]> = if input.peek(crate::token::RawToken![raw])
1531 && (input.peek2(crate::token::MutToken![mut]) || input.peek2(crate::token::ConstToken![const]))
1532 {
1533 Some(input.parse()?)
1534 } else {
1535 None
1536 };
1537 let mutability: Option<crate::token::MutToken![mut]> = input.parse()?;
1538 let const_token: Option<crate::token::ConstToken![const]> = if raw.is_some() && mutability.is_none() {
1539 Some(input.parse()?)
1540 } else {
1541 None
1542 };
1543 let expr = Box::new(unary_expr(input, allow_struct)?);
1544 if let Some(raw) = raw {
1545 Ok(Expr::RawAddr(ExprRawAddr {
1546 attrs,
1547 and_token,
1548 raw,
1549 mutability: match mutability {
1550 Some(mut_token) => PointerMutability::Mut(mut_token),
1551 None => PointerMutability::Const(const_token.unwrap()),
1552 },
1553 expr,
1554 }))
1555 } else {
1556 Ok(Expr::Reference(ExprReference {
1557 attrs,
1558 and_token,
1559 mutability,
1560 expr,
1561 }))
1562 }
1563 } else if input.peek(crate::token::StarToken![*]) || input.peek(crate::token::NotToken![!]) || input.peek(crate::token::MinusToken![-]) {
1564 expr_unary(input, attrs, allow_struct).map(Expr::Unary)
1565 } else {
1566 trailer_expr(begin, attrs, input, allow_struct)
1567 }
1568 }
1569
1570 #[cfg(not(feature = "full"))]
1571 fn unary_expr(input: ParseStream) -> Result<Expr> {
1572 if input.peek(Token![&]) {
1573 Ok(Expr::Reference(ExprReference {
1574 attrs: Vec::new(),
1575 and_token: input.parse()?,
1576 mutability: input.parse()?,
1577 expr: Box::new(unary_expr(input)?),
1578 }))
1579 } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1580 Ok(Expr::Unary(ExprUnary {
1581 attrs: Vec::new(),
1582 op: input.parse()?,
1583 expr: Box::new(unary_expr(input)?),
1584 }))
1585 } else {
1586 trailer_expr(input)
1587 }
1588 }
1589
1590 #[cfg(feature = "full")]
1597 fn trailer_expr(
1598 begin: ParseBuffer,
1599 mut attrs: Vec<Attribute>,
1600 input: ParseStream,
1601 allow_struct: AllowStruct,
1602 ) -> Result<Expr> {
1603 let atom = atom_expr(input, allow_struct)?;
1604 let mut e = trailer_helper(input, atom)?;
1605
1606 if let Expr::Verbatim(tokens) = &mut e {
1607 *tokens = verbatim::between(&begin, input);
1608 } else if !attrs.is_empty() {
1609 if let Expr::Range(range) = e {
1610 let spans: &[Span] = match &range.limits {
1611 RangeLimits::HalfOpen(limits) => &limits.spans,
1612 RangeLimits::Closed(limits) => &limits.spans,
1613 };
1614 return Err(crate::error::new2(
1615 spans[0],
1616 *spans.last().unwrap(),
1617 "attributes are not allowed on range expressions starting with `..`",
1618 ));
1619 }
1620 let inner_attrs = e.replace_attrs(Vec::new());
1621 attrs.extend(inner_attrs);
1622 e.replace_attrs(attrs);
1623 }
1624
1625 Ok(e)
1626 }
1627
1628 #[cfg(feature = "full")]
1629 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
1630 loop {
1631 if input.peek(token::Paren) {
1632 let content;
1633 e = Expr::Call(ExprCall {
1634 attrs: Vec::new(),
1635 func: Box::new(e),
1636 paren_token: match crate::__private::parse_parens(&input) {
crate::__private::Ok(parens) => {
content = parens.content;
_ = content;
parens.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in input),
1637 args: content.parse_terminated(Expr::parse, crate::token::CommaToken![,])?,
1638 });
1639 } else if input.peek(crate::token::DotToken![.])
1640 && !input.peek(crate::token::DotDotToken![..])
1641 && match e {
1642 Expr::Range(_) => false,
1643 _ => true,
1644 }
1645 {
1646 let mut dot_token: crate::token::DotToken![.] = input.parse()?;
1647
1648 let float_token: Option<LitFloat> = input.parse()?;
1649 if let Some(float_token) = float_token {
1650 if multi_index(&mut e, &mut dot_token, float_token)? {
1651 continue;
1652 }
1653 }
1654
1655 let await_token: Option<crate::token::AwaitToken![await]> = input.parse()?;
1656 if let Some(await_token) = await_token {
1657 e = Expr::Await(ExprAwait {
1658 attrs: Vec::new(),
1659 base: Box::new(e),
1660 dot_token,
1661 await_token,
1662 });
1663 continue;
1664 }
1665
1666 let member: Member = input.parse()?;
1667 let turbofish = if member.is_named() && input.peek(crate::token::PathSepToken![::]) {
1668 Some(AngleBracketedGenericArguments::parse_turbofish(input)?)
1669 } else {
1670 None
1671 };
1672
1673 if turbofish.is_some() || input.peek(token::Paren) {
1674 if let Member::Named(method) = member {
1675 let content;
1676 e = Expr::MethodCall(ExprMethodCall {
1677 attrs: Vec::new(),
1678 receiver: Box::new(e),
1679 dot_token,
1680 method,
1681 turbofish,
1682 paren_token: match crate::__private::parse_parens(&input) {
crate::__private::Ok(parens) => {
content = parens.content;
_ = content;
parens.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in input),
1683 args: content.parse_terminated(Expr::parse, crate::token::CommaToken![,])?,
1684 });
1685 continue;
1686 }
1687 }
1688
1689 e = Expr::Field(ExprField {
1690 attrs: Vec::new(),
1691 base: Box::new(e),
1692 dot_token,
1693 member,
1694 });
1695 } else if input.peek(token::Bracket) {
1696 let content;
1697 e = Expr::Index(ExprIndex {
1698 attrs: Vec::new(),
1699 expr: Box::new(e),
1700 bracket_token: match crate::__private::parse_brackets(&input) {
crate::__private::Ok(brackets) => {
content = brackets.content;
_ = content;
brackets.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}bracketed!(content in input),
1701 index: content.parse()?,
1702 });
1703 } else if input.peek(crate::token::QuestionToken![?])
1704 && match e {
1705 Expr::Range(_) => false,
1706 _ => true,
1707 }
1708 {
1709 e = Expr::Try(ExprTry {
1710 attrs: Vec::new(),
1711 expr: Box::new(e),
1712 question_token: input.parse()?,
1713 });
1714 } else {
1715 break;
1716 }
1717 }
1718 Ok(e)
1719 }
1720
1721 #[cfg(not(feature = "full"))]
1722 fn trailer_expr(input: ParseStream) -> Result<Expr> {
1723 let mut e = atom_expr(input)?;
1724
1725 loop {
1726 if input.peek(token::Paren) {
1727 let content;
1728 e = Expr::Call(ExprCall {
1729 attrs: Vec::new(),
1730 func: Box::new(e),
1731 paren_token: parenthesized!(content in input),
1732 args: content.parse_terminated(Expr::parse, Token![,])?,
1733 });
1734 } else if input.peek(Token![.])
1735 && !input.peek(Token![..])
1736 && !input.peek2(Token![await])
1737 {
1738 let mut dot_token: Token![.] = input.parse()?;
1739
1740 let float_token: Option<LitFloat> = input.parse()?;
1741 if let Some(float_token) = float_token {
1742 if multi_index(&mut e, &mut dot_token, float_token)? {
1743 continue;
1744 }
1745 }
1746
1747 let member: Member = input.parse()?;
1748 let turbofish = if member.is_named() && input.peek(Token![::]) {
1749 let colon2_token: Token![::] = input.parse()?;
1750 let turbofish =
1751 AngleBracketedGenericArguments::do_parse(Some(colon2_token), input)?;
1752 Some(turbofish)
1753 } else {
1754 None
1755 };
1756
1757 if turbofish.is_some() || input.peek(token::Paren) {
1758 if let Member::Named(method) = member {
1759 let content;
1760 e = Expr::MethodCall(ExprMethodCall {
1761 attrs: Vec::new(),
1762 receiver: Box::new(e),
1763 dot_token,
1764 method,
1765 turbofish,
1766 paren_token: parenthesized!(content in input),
1767 args: content.parse_terminated(Expr::parse, Token![,])?,
1768 });
1769 continue;
1770 }
1771 }
1772
1773 e = Expr::Field(ExprField {
1774 attrs: Vec::new(),
1775 base: Box::new(e),
1776 dot_token,
1777 member,
1778 });
1779 } else if input.peek(token::Bracket) {
1780 let content;
1781 e = Expr::Index(ExprIndex {
1782 attrs: Vec::new(),
1783 expr: Box::new(e),
1784 bracket_token: bracketed!(content in input),
1785 index: content.parse()?,
1786 });
1787 } else {
1788 break;
1789 }
1790 }
1791
1792 Ok(e)
1793 }
1794
1795 #[cfg(feature = "full")]
1798 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1799 if input.peek(token::Group) {
1800 expr_group(input, allow_struct)
1801 } else if input.peek(Lit) {
1802 input.parse().map(Expr::Lit)
1803 } else if input.peek(crate::token::AsyncToken![async])
1804 && (input.peek2(token::Brace) || input.peek2(crate::token::MoveToken![move]) && input.peek3(token::Brace))
1805 {
1806 input.parse().map(Expr::Async)
1807 } else if input.peek(crate::token::TryToken![try]) && input.peek2(token::Brace) {
1808 input.parse().map(Expr::TryBlock)
1809 } else if input.peek(crate::token::OrToken![|])
1810 || input.peek(crate::token::MoveToken![move])
1811 || input.peek(crate::token::ForToken![for])
1812 && generics::parsing::choose_generics_over_qpath_after_keyword(input)
1813 || input.peek(crate::token::ConstToken![const]) && !input.peek2(token::Brace)
1814 || input.peek(crate::token::StaticToken![static])
1815 || input.peek(crate::token::AsyncToken![async]) && (input.peek2(crate::token::OrToken![|]) || input.peek2(crate::token::MoveToken![move]))
1816 {
1817 expr_closure(input, allow_struct).map(Expr::Closure)
1818 } else if token::parsing::peek_keyword(input.cursor(), "builtin") && input.peek2(crate::token::PoundToken![#])
1819 {
1820 expr_builtin(input)
1821 } else if input.peek(Ident)
1822 || input.peek(crate::token::PathSepToken![::])
1823 || input.peek(crate::token::LtToken![<])
1824 || input.peek(crate::token::SelfValueToken![self])
1825 || input.peek(crate::token::SelfTypeToken![Self])
1826 || input.peek(crate::token::SuperToken![super])
1827 || input.peek(crate::token::CrateToken![crate])
1828 || input.peek(crate::token::TryToken![try]) && (input.peek2(crate::token::NotToken![!]) || input.peek2(crate::token::PathSepToken![::]))
1829 {
1830 path_or_macro_or_struct(input, allow_struct)
1831 } else if input.peek(token::Paren) {
1832 paren_or_tuple(input)
1833 } else if input.peek(crate::token::BreakToken![break]) {
1834 expr_break(input, allow_struct).map(Expr::Break)
1835 } else if input.peek(crate::token::ContinueToken![continue]) {
1836 input.parse().map(Expr::Continue)
1837 } else if input.peek(crate::token::ReturnToken![return]) {
1838 input.parse().map(Expr::Return)
1839 } else if input.peek(crate::token::BecomeToken![become]) {
1840 expr_become(input)
1841 } else if input.peek(token::Bracket) {
1842 array_or_repeat(input)
1843 } else if input.peek(crate::token::LetToken![let]) {
1844 expr_let(input, allow_struct).map(Expr::Let)
1845 } else if input.peek(crate::token::IfToken![if]) {
1846 input.parse().map(Expr::If)
1847 } else if input.peek(crate::token::WhileToken![while]) {
1848 input.parse().map(Expr::While)
1849 } else if input.peek(crate::token::ForToken![for]) {
1850 input.parse().map(Expr::ForLoop)
1851 } else if input.peek(crate::token::LoopToken![loop]) {
1852 input.parse().map(Expr::Loop)
1853 } else if input.peek(crate::token::MatchToken![match]) {
1854 input.parse().map(Expr::Match)
1855 } else if input.peek(crate::token::YieldToken![yield]) {
1856 input.parse().map(Expr::Yield)
1857 } else if input.peek(crate::token::UnsafeToken![unsafe]) {
1858 input.parse().map(Expr::Unsafe)
1859 } else if input.peek(crate::token::ConstToken![const]) {
1860 input.parse().map(Expr::Const)
1861 } else if input.peek(token::Brace) {
1862 input.parse().map(Expr::Block)
1863 } else if input.peek(crate::token::DotDotToken![..]) {
1864 expr_range(input, allow_struct).map(Expr::Range)
1865 } else if input.peek(crate::token::UnderscoreToken![_]) {
1866 input.parse().map(Expr::Infer)
1867 } else if input.peek(Lifetime) {
1868 atom_labeled(input)
1869 } else {
1870 Err(input.error("expected an expression"))
1871 }
1872 }
1873
1874 #[cfg(feature = "full")]
1875 fn atom_labeled(input: ParseStream) -> Result<Expr> {
1876 let the_label: Label = input.parse()?;
1877 let mut expr = if input.peek(crate::token::WhileToken![while]) {
1878 Expr::While(input.parse()?)
1879 } else if input.peek(crate::token::ForToken![for]) {
1880 Expr::ForLoop(input.parse()?)
1881 } else if input.peek(crate::token::LoopToken![loop]) {
1882 Expr::Loop(input.parse()?)
1883 } else if input.peek(token::Brace) {
1884 Expr::Block(input.parse()?)
1885 } else {
1886 return Err(input.error("expected loop or block expression"));
1887 };
1888 match &mut expr {
1889 Expr::While(ExprWhile { label, .. })
1890 | Expr::ForLoop(ExprForLoop { label, .. })
1891 | Expr::Loop(ExprLoop { label, .. })
1892 | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
1893 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1894 }
1895 Ok(expr)
1896 }
1897
1898 #[cfg(not(feature = "full"))]
1899 fn atom_expr(input: ParseStream) -> Result<Expr> {
1900 if input.peek(token::Group) {
1901 expr_group(input)
1902 } else if input.peek(Lit) {
1903 input.parse().map(Expr::Lit)
1904 } else if input.peek(token::Paren) {
1905 paren_or_tuple(input)
1906 } else if input.peek(Ident)
1907 || input.peek(Token![::])
1908 || input.peek(Token![<])
1909 || input.peek(Token![self])
1910 || input.peek(Token![Self])
1911 || input.peek(Token![super])
1912 || input.peek(Token![crate])
1913 {
1914 path_or_macro_or_struct(input)
1915 } else if input.is_empty() {
1916 Err(input.error("expected an expression"))
1917 } else {
1918 if input.peek(token::Brace) {
1919 let scan = input.fork();
1920 let content;
1921 braced!(content in scan);
1922 if content.parse::<Expr>().is_ok() && content.is_empty() {
1923 let expr_block = verbatim::between(input, &scan);
1924 input.advance_to(&scan);
1925 return Ok(Expr::Verbatim(expr_block));
1926 }
1927 }
1928 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1929 }
1930 }
1931
1932 #[cfg(feature = "full")]
1933 fn expr_builtin(input: ParseStream) -> Result<Expr> {
1934 let begin = input.fork();
1935
1936 token::parsing::keyword(input, "builtin")?;
1937 input.parse::<crate::token::PoundToken![#]>()?;
1938 input.parse::<Ident>()?;
1939
1940 let args;
1941 match crate::__private::parse_parens(&input) {
crate::__private::Ok(parens) => {
args = parens.content;
_ = args;
parens.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
};parenthesized!(args in input);
1942 args.parse::<TokenStream>()?;
1943
1944 Ok(Expr::Verbatim(verbatim::between(&begin, input)))
1945 }
1946
1947 fn path_or_macro_or_struct(
1948 input: ParseStream,
1949 #[cfg(feature = "full")] allow_struct: AllowStruct,
1950 ) -> Result<Expr> {
1951 let expr_style = true;
1952 let (qself, path) = path::parsing::qpath(input, expr_style)?;
1953 rest_of_path_or_macro_or_struct(
1954 qself,
1955 path,
1956 input,
1957 #[cfg(feature = "full")]
1958 allow_struct,
1959 )
1960 }
1961
1962 fn rest_of_path_or_macro_or_struct(
1963 qself: Option<QSelf>,
1964 path: Path,
1965 input: ParseStream,
1966 #[cfg(feature = "full")] allow_struct: AllowStruct,
1967 ) -> Result<Expr> {
1968 if qself.is_none()
1969 && input.peek(crate::token::NotToken![!])
1970 && !input.peek(crate::token::NeToken![!=])
1971 && path.is_mod_style()
1972 {
1973 let bang_token: crate::token::NotToken![!] = input.parse()?;
1974 let (delimiter, tokens) = mac::parse_delimiter(input)?;
1975 return Ok(Expr::Macro(ExprMacro {
1976 attrs: Vec::new(),
1977 mac: Macro {
1978 path,
1979 bang_token,
1980 delimiter,
1981 tokens,
1982 },
1983 }));
1984 }
1985
1986 #[cfg(not(feature = "full"))]
1987 let allow_struct = (true,);
1988 if allow_struct.0 && input.peek(token::Brace) {
1989 return expr_struct_helper(input, qself, path).map(Expr::Struct);
1990 }
1991
1992 Ok(Expr::Path(ExprPath {
1993 attrs: Vec::new(),
1994 qself,
1995 path,
1996 }))
1997 }
1998
1999 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2000 impl Parse for ExprMacro {
2001 fn parse(input: ParseStream) -> Result<Self> {
2002 Ok(ExprMacro {
2003 attrs: Vec::new(),
2004 mac: input.parse()?,
2005 })
2006 }
2007 }
2008
2009 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
2010 let content;
2011 let paren_token = match crate::__private::parse_parens(&input) {
crate::__private::Ok(parens) => {
content = parens.content;
_ = content;
parens.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in input);
2012 if content.is_empty() {
2013 return Ok(Expr::Tuple(ExprTuple {
2014 attrs: Vec::new(),
2015 paren_token,
2016 elems: Punctuated::new(),
2017 }));
2018 }
2019
2020 let first: Expr = content.parse()?;
2021 if content.is_empty() {
2022 return Ok(Expr::Paren(ExprParen {
2023 attrs: Vec::new(),
2024 paren_token,
2025 expr: Box::new(first),
2026 }));
2027 }
2028
2029 let mut elems = Punctuated::new();
2030 elems.push_value(first);
2031 while !content.is_empty() {
2032 let punct = content.parse()?;
2033 elems.push_punct(punct);
2034 if content.is_empty() {
2035 break;
2036 }
2037 let value = content.parse()?;
2038 elems.push_value(value);
2039 }
2040 Ok(Expr::Tuple(ExprTuple {
2041 attrs: Vec::new(),
2042 paren_token,
2043 elems,
2044 }))
2045 }
2046
2047 #[cfg(feature = "full")]
2048 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
2049 let content;
2050 let bracket_token = match crate::__private::parse_brackets(&input) {
crate::__private::Ok(brackets) => {
content = brackets.content;
_ = content;
brackets.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}bracketed!(content in input);
2051 if content.is_empty() {
2052 return Ok(Expr::Array(ExprArray {
2053 attrs: Vec::new(),
2054 bracket_token,
2055 elems: Punctuated::new(),
2056 }));
2057 }
2058
2059 let first: Expr = content.parse()?;
2060 if content.is_empty() || content.peek(crate::token::CommaToken![,]) {
2061 let mut elems = Punctuated::new();
2062 elems.push_value(first);
2063 while !content.is_empty() {
2064 let punct = content.parse()?;
2065 elems.push_punct(punct);
2066 if content.is_empty() {
2067 break;
2068 }
2069 let value = content.parse()?;
2070 elems.push_value(value);
2071 }
2072 Ok(Expr::Array(ExprArray {
2073 attrs: Vec::new(),
2074 bracket_token,
2075 elems,
2076 }))
2077 } else if content.peek(crate::token::SemiToken![;]) {
2078 let semi_token: crate::token::SemiToken![;] = content.parse()?;
2079 let len: Expr = content.parse()?;
2080 Ok(Expr::Repeat(ExprRepeat {
2081 attrs: Vec::new(),
2082 bracket_token,
2083 expr: Box::new(first),
2084 semi_token,
2085 len: Box::new(len),
2086 }))
2087 } else {
2088 Err(content.error("expected `,` or `;`"))
2089 }
2090 }
2091
2092 #[cfg(feature = "full")]
2093 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2094 impl Parse for ExprArray {
2095 fn parse(input: ParseStream) -> Result<Self> {
2096 let content;
2097 let bracket_token = match crate::__private::parse_brackets(&input) {
crate::__private::Ok(brackets) => {
content = brackets.content;
_ = content;
brackets.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}bracketed!(content in input);
2098 let mut elems = Punctuated::new();
2099
2100 while !content.is_empty() {
2101 let first: Expr = content.parse()?;
2102 elems.push_value(first);
2103 if content.is_empty() {
2104 break;
2105 }
2106 let punct = content.parse()?;
2107 elems.push_punct(punct);
2108 }
2109
2110 Ok(ExprArray {
2111 attrs: Vec::new(),
2112 bracket_token,
2113 elems,
2114 })
2115 }
2116 }
2117
2118 #[cfg(feature = "full")]
2119 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2120 impl Parse for ExprRepeat {
2121 fn parse(input: ParseStream) -> Result<Self> {
2122 let content;
2123 Ok(ExprRepeat {
2124 bracket_token: match crate::__private::parse_brackets(&input) {
crate::__private::Ok(brackets) => {
content = brackets.content;
_ = content;
brackets.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}bracketed!(content in input),
2125 attrs: Vec::new(),
2126 expr: content.parse()?,
2127 semi_token: content.parse()?,
2128 len: content.parse()?,
2129 })
2130 }
2131 }
2132
2133 #[cfg(feature = "full")]
2134 fn continue_parsing_early(mut expr: &Expr) -> bool {
2135 while let Expr::Group(group) = expr {
2136 expr = &group.expr;
2137 }
2138 match expr {
2139 Expr::If(_)
2140 | Expr::While(_)
2141 | Expr::ForLoop(_)
2142 | Expr::Loop(_)
2143 | Expr::Match(_)
2144 | Expr::TryBlock(_)
2145 | Expr::Unsafe(_)
2146 | Expr::Const(_)
2147 | Expr::Block(_) => false,
2148 _ => true,
2149 }
2150 }
2151
2152 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2153 impl Parse for ExprLit {
2154 fn parse(input: ParseStream) -> Result<Self> {
2155 Ok(ExprLit {
2156 attrs: Vec::new(),
2157 lit: input.parse()?,
2158 })
2159 }
2160 }
2161
2162 fn expr_group(
2163 input: ParseStream,
2164 #[cfg(feature = "full")] allow_struct: AllowStruct,
2165 ) -> Result<Expr> {
2166 let group = crate::group::parse_group(input)?;
2167 let mut inner: Expr = group.content.parse()?;
2168
2169 match inner {
2170 Expr::Path(mut expr) if expr.attrs.is_empty() => {
2171 let grouped_len = expr.path.segments.len();
2172 Path::parse_rest(input, &mut expr.path, true)?;
2173 match rest_of_path_or_macro_or_struct(
2174 expr.qself,
2175 expr.path,
2176 input,
2177 #[cfg(feature = "full")]
2178 allow_struct,
2179 )? {
2180 Expr::Path(expr) if expr.path.segments.len() == grouped_len => {
2181 inner = Expr::Path(expr);
2182 }
2183 extended => return Ok(extended),
2184 }
2185 }
2186 _ => {}
2187 }
2188
2189 Ok(Expr::Group(ExprGroup {
2190 attrs: Vec::new(),
2191 group_token: group.token,
2192 expr: Box::new(inner),
2193 }))
2194 }
2195
2196 #[cfg(feature = "full")]
2197 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2198 impl Parse for ExprParen {
2199 fn parse(input: ParseStream) -> Result<Self> {
2200 let content;
2201 Ok(ExprParen {
2202 attrs: Vec::new(),
2203 paren_token: match crate::__private::parse_parens(&input) {
crate::__private::Ok(parens) => {
content = parens.content;
_ = content;
parens.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in input),
2204 expr: content.parse()?,
2205 })
2206 }
2207 }
2208
2209 #[cfg(feature = "full")]
2210 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2211 impl Parse for ExprLet {
2212 fn parse(input: ParseStream) -> Result<Self> {
2213 let allow_struct = AllowStruct(true);
2214 expr_let(input, allow_struct)
2215 }
2216 }
2217
2218 #[cfg(feature = "full")]
2219 fn expr_let(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprLet> {
2220 Ok(ExprLet {
2221 attrs: Vec::new(),
2222 let_token: input.parse()?,
2223 pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
2224 eq_token: input.parse()?,
2225 expr: Box::new({
2226 let lhs = unary_expr(input, allow_struct)?;
2227 parse_expr(input, lhs, allow_struct, Precedence::Compare)?
2228 }),
2229 })
2230 }
2231
2232 #[cfg(feature = "full")]
2233 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2234 impl Parse for ExprIf {
2235 fn parse(input: ParseStream) -> Result<Self> {
2236 let attrs = input.call(Attribute::parse_outer)?;
2237
2238 let mut clauses = Vec::new();
2239 let mut expr;
2240 loop {
2241 let if_token: crate::token::IfToken![if] = input.parse()?;
2242 let cond = input.call(Expr::parse_without_eager_brace)?;
2243 let then_branch: Block = input.parse()?;
2244
2245 expr = ExprIf {
2246 attrs: Vec::new(),
2247 if_token,
2248 cond: Box::new(cond),
2249 then_branch,
2250 else_branch: None,
2251 };
2252
2253 if !input.peek(crate::token::ElseToken![else]) {
2254 break;
2255 }
2256
2257 let else_token: crate::token::ElseToken![else] = input.parse()?;
2258 let lookahead = input.lookahead1();
2259 if lookahead.peek(crate::token::IfToken![if]) {
2260 expr.else_branch = Some((else_token, Box::new(Expr::PLACEHOLDER)));
2261 clauses.push(expr);
2262 } else if lookahead.peek(token::Brace) {
2263 expr.else_branch = Some((
2264 else_token,
2265 Box::new(Expr::Block(ExprBlock {
2266 attrs: Vec::new(),
2267 label: None,
2268 block: input.parse()?,
2269 })),
2270 ));
2271 break;
2272 } else {
2273 return Err(lookahead.error());
2274 }
2275 }
2276
2277 while let Some(mut prev) = clauses.pop() {
2278 *prev.else_branch.as_mut().unwrap().1 = Expr::If(expr);
2279 expr = prev;
2280 }
2281 expr.attrs = attrs;
2282 Ok(expr)
2283 }
2284 }
2285
2286 #[cfg(feature = "full")]
2287 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2288 impl Parse for ExprInfer {
2289 fn parse(input: ParseStream) -> Result<Self> {
2290 Ok(ExprInfer {
2291 attrs: input.call(Attribute::parse_outer)?,
2292 underscore_token: input.parse()?,
2293 })
2294 }
2295 }
2296
2297 #[cfg(feature = "full")]
2298 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2299 impl Parse for ExprForLoop {
2300 fn parse(input: ParseStream) -> Result<Self> {
2301 let mut attrs = input.call(Attribute::parse_outer)?;
2302 let label: Option<Label> = input.parse()?;
2303 let for_token: crate::token::ForToken![for] = input.parse()?;
2304
2305 let pat = Pat::parse_multi_with_leading_vert(input)?;
2306
2307 let in_token: crate::token::InToken![in] = input.parse()?;
2308 let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
2309
2310 let content;
2311 let brace_token = match crate::__private::parse_braces(&input) {
crate::__private::Ok(braces) => {
content = braces.content;
_ = content;
braces.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2312 attr::parsing::parse_inner(&content, &mut attrs)?;
2313 let stmts = content.call(Block::parse_within)?;
2314
2315 Ok(ExprForLoop {
2316 attrs,
2317 label,
2318 for_token,
2319 pat: Box::new(pat),
2320 in_token,
2321 expr: Box::new(expr),
2322 body: Block { brace_token, stmts },
2323 })
2324 }
2325 }
2326
2327 #[cfg(feature = "full")]
2328 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2329 impl Parse for ExprLoop {
2330 fn parse(input: ParseStream) -> Result<Self> {
2331 let mut attrs = input.call(Attribute::parse_outer)?;
2332 let label: Option<Label> = input.parse()?;
2333 let loop_token: crate::token::LoopToken![loop] = input.parse()?;
2334
2335 let content;
2336 let brace_token = match crate::__private::parse_braces(&input) {
crate::__private::Ok(braces) => {
content = braces.content;
_ = content;
braces.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2337 attr::parsing::parse_inner(&content, &mut attrs)?;
2338 let stmts = content.call(Block::parse_within)?;
2339
2340 Ok(ExprLoop {
2341 attrs,
2342 label,
2343 loop_token,
2344 body: Block { brace_token, stmts },
2345 })
2346 }
2347 }
2348
2349 #[cfg(feature = "full")]
2350 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2351 impl Parse for ExprMatch {
2352 fn parse(input: ParseStream) -> Result<Self> {
2353 let mut attrs = input.call(Attribute::parse_outer)?;
2354 let match_token: crate::token::MatchToken![match] = input.parse()?;
2355 let expr = Expr::parse_without_eager_brace(input)?;
2356
2357 let content;
2358 let brace_token = match crate::__private::parse_braces(&input) {
crate::__private::Ok(braces) => {
content = braces.content;
_ = content;
braces.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2359 attr::parsing::parse_inner(&content, &mut attrs)?;
2360
2361 let arms = Arm::parse_multiple(&content)?;
2362
2363 Ok(ExprMatch {
2364 attrs,
2365 match_token,
2366 expr: Box::new(expr),
2367 brace_token,
2368 arms,
2369 })
2370 }
2371 }
2372
2373 macro_rules! impl_by_parsing_expr {
2374 (
2375 $(
2376 $expr_type:ty, $variant:ident, $msg:expr,
2377 )*
2378 ) => {
2379 $(
2380 #[cfg(all(feature = "full", feature = "printing"))]
2381 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2382 impl Parse for $expr_type {
2383 fn parse(input: ParseStream) -> Result<Self> {
2384 let mut expr: Expr = input.parse()?;
2385 loop {
2386 match expr {
2387 Expr::$variant(inner) => return Ok(inner),
2388 Expr::Group(next) => expr = *next.expr,
2389 _ => return Err(Error::new_spanned(expr, $msg)),
2390 }
2391 }
2392 }
2393 }
2394 )*
2395 };
2396 }
2397
2398 impl Parse for ExprTuple {
fn parse(input: ParseStream) -> Result<Self> {
let mut expr: Expr = input.parse()?;
loop {
match expr {
Expr::Tuple(inner) => return Ok(inner),
Expr::Group(next) => expr = *next.expr,
_ =>
return Err(Error::new_spanned(expr,
"expected tuple expression")),
}
}
}
}impl_by_parsing_expr! {
2399 ExprAssign, Assign, "expected assignment expression",
2400 ExprAwait, Await, "expected await expression",
2401 ExprBinary, Binary, "expected binary operation",
2402 ExprCall, Call, "expected function call expression",
2403 ExprCast, Cast, "expected cast expression",
2404 ExprField, Field, "expected struct field access",
2405 ExprIndex, Index, "expected indexing expression",
2406 ExprMethodCall, MethodCall, "expected method call expression",
2407 ExprRange, Range, "expected range expression",
2408 ExprTry, Try, "expected try expression",
2409 ExprTuple, Tuple, "expected tuple expression",
2410 }
2411
2412 #[cfg(feature = "full")]
2413 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2414 impl Parse for ExprUnary {
2415 fn parse(input: ParseStream) -> Result<Self> {
2416 let attrs = Vec::new();
2417 let allow_struct = AllowStruct(true);
2418 expr_unary(input, attrs, allow_struct)
2419 }
2420 }
2421
2422 #[cfg(feature = "full")]
2423 fn expr_unary(
2424 input: ParseStream,
2425 attrs: Vec<Attribute>,
2426 allow_struct: AllowStruct,
2427 ) -> Result<ExprUnary> {
2428 Ok(ExprUnary {
2429 attrs,
2430 op: input.parse()?,
2431 expr: Box::new(unary_expr(input, allow_struct)?),
2432 })
2433 }
2434
2435 #[cfg(feature = "full")]
2436 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2437 impl Parse for ExprClosure {
2438 fn parse(input: ParseStream) -> Result<Self> {
2439 let allow_struct = AllowStruct(true);
2440 expr_closure(input, allow_struct)
2441 }
2442 }
2443
2444 #[cfg(feature = "full")]
2445 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2446 impl Parse for ExprRawAddr {
2447 fn parse(input: ParseStream) -> Result<Self> {
2448 let allow_struct = AllowStruct(true);
2449 Ok(ExprRawAddr {
2450 attrs: Vec::new(),
2451 and_token: input.parse()?,
2452 raw: input.parse()?,
2453 mutability: input.parse()?,
2454 expr: Box::new(unary_expr(input, allow_struct)?),
2455 })
2456 }
2457 }
2458
2459 #[cfg(feature = "full")]
2460 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2461 impl Parse for ExprReference {
2462 fn parse(input: ParseStream) -> Result<Self> {
2463 let allow_struct = AllowStruct(true);
2464 Ok(ExprReference {
2465 attrs: Vec::new(),
2466 and_token: input.parse()?,
2467 mutability: input.parse()?,
2468 expr: Box::new(unary_expr(input, allow_struct)?),
2469 })
2470 }
2471 }
2472
2473 #[cfg(feature = "full")]
2474 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2475 impl Parse for ExprBreak {
2476 fn parse(input: ParseStream) -> Result<Self> {
2477 let allow_struct = AllowStruct(true);
2478 expr_break(input, allow_struct)
2479 }
2480 }
2481
2482 #[cfg(feature = "full")]
2483 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2484 impl Parse for ExprReturn {
2485 fn parse(input: ParseStream) -> Result<Self> {
2486 Ok(ExprReturn {
2487 attrs: Vec::new(),
2488 return_token: input.parse()?,
2489 expr: {
2490 if Expr::peek(input) {
2491 Some(input.parse()?)
2492 } else {
2493 None
2494 }
2495 },
2496 })
2497 }
2498 }
2499
2500 #[cfg(feature = "full")]
2501 fn expr_become(input: ParseStream) -> Result<Expr> {
2502 let begin = input.fork();
2503 input.parse::<crate::token::BecomeToken![become]>()?;
2504 input.parse::<Expr>()?;
2505 Ok(Expr::Verbatim(verbatim::between(&begin, input)))
2506 }
2507
2508 #[cfg(feature = "full")]
2509 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2510 impl Parse for ExprTryBlock {
2511 fn parse(input: ParseStream) -> Result<Self> {
2512 Ok(ExprTryBlock {
2513 attrs: Vec::new(),
2514 try_token: input.parse()?,
2515 block: input.parse()?,
2516 })
2517 }
2518 }
2519
2520 #[cfg(feature = "full")]
2521 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2522 impl Parse for ExprYield {
2523 fn parse(input: ParseStream) -> Result<Self> {
2524 Ok(ExprYield {
2525 attrs: Vec::new(),
2526 yield_token: input.parse()?,
2527 expr: {
2528 if Expr::peek(input) {
2529 Some(input.parse()?)
2530 } else {
2531 None
2532 }
2533 },
2534 })
2535 }
2536 }
2537
2538 #[cfg(feature = "full")]
2539 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2540 let lifetimes: Option<BoundLifetimes> = input.parse()?;
2541 let constness: Option<crate::token::ConstToken![const]> = input.parse()?;
2542 let movability: Option<crate::token::StaticToken![static]> = input.parse()?;
2543 let asyncness: Option<crate::token::AsyncToken![async]> = input.parse()?;
2544 let capture: Option<crate::token::MoveToken![move]> = input.parse()?;
2545 let or1_token: crate::token::OrToken![|] = input.parse()?;
2546
2547 let mut inputs = Punctuated::new();
2548 loop {
2549 if input.peek(crate::token::OrToken![|]) {
2550 break;
2551 }
2552 let value = closure_arg(input)?;
2553 inputs.push_value(value);
2554 if input.peek(crate::token::OrToken![|]) {
2555 break;
2556 }
2557 let punct: crate::token::CommaToken![,] = input.parse()?;
2558 inputs.push_punct(punct);
2559 }
2560
2561 let or2_token: crate::token::OrToken![|] = input.parse()?;
2562
2563 let (output, body) = if input.peek(crate::token::RArrowToken![->]) {
2564 let arrow_token: crate::token::RArrowToken![->] = input.parse()?;
2565 let ty: Type = input.parse()?;
2566 let body: Block = input.parse()?;
2567 let output = ReturnType::Type(arrow_token, Box::new(ty));
2568 let block = Expr::Block(ExprBlock {
2569 attrs: Vec::new(),
2570 label: None,
2571 block: body,
2572 });
2573 (output, block)
2574 } else {
2575 let body = ambiguous_expr(input, allow_struct)?;
2576 (ReturnType::Default, body)
2577 };
2578
2579 Ok(ExprClosure {
2580 attrs: Vec::new(),
2581 lifetimes,
2582 constness,
2583 movability,
2584 asyncness,
2585 capture,
2586 or1_token,
2587 inputs,
2588 or2_token,
2589 output,
2590 body: Box::new(body),
2591 })
2592 }
2593
2594 #[cfg(feature = "full")]
2595 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2596 impl Parse for ExprAsync {
2597 fn parse(input: ParseStream) -> Result<Self> {
2598 Ok(ExprAsync {
2599 attrs: Vec::new(),
2600 async_token: input.parse()?,
2601 capture: input.parse()?,
2602 block: input.parse()?,
2603 })
2604 }
2605 }
2606
2607 #[cfg(feature = "full")]
2608 fn closure_arg(input: ParseStream) -> Result<Pat> {
2609 let attrs = input.call(Attribute::parse_outer)?;
2610 let mut pat = Pat::parse_single(input)?;
2611
2612 if input.peek(crate::token::ColonToken![:]) {
2613 Ok(Pat::Type(PatType {
2614 attrs,
2615 pat: Box::new(pat),
2616 colon_token: input.parse()?,
2617 ty: input.parse()?,
2618 }))
2619 } else {
2620 match &mut pat {
2621 Pat::Const(pat) => pat.attrs = attrs,
2622 Pat::Ident(pat) => pat.attrs = attrs,
2623 Pat::Lit(pat) => pat.attrs = attrs,
2624 Pat::Macro(pat) => pat.attrs = attrs,
2625 Pat::Or(pat) => pat.attrs = attrs,
2626 Pat::Paren(pat) => pat.attrs = attrs,
2627 Pat::Path(pat) => pat.attrs = attrs,
2628 Pat::Range(pat) => pat.attrs = attrs,
2629 Pat::Reference(pat) => pat.attrs = attrs,
2630 Pat::Rest(pat) => pat.attrs = attrs,
2631 Pat::Slice(pat) => pat.attrs = attrs,
2632 Pat::Struct(pat) => pat.attrs = attrs,
2633 Pat::Tuple(pat) => pat.attrs = attrs,
2634 Pat::TupleStruct(pat) => pat.attrs = attrs,
2635 Pat::Type(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
2636 Pat::Verbatim(_) => {}
2637 Pat::Wild(pat) => pat.attrs = attrs,
2638 }
2639 Ok(pat)
2640 }
2641 }
2642
2643 #[cfg(feature = "full")]
2644 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2645 impl Parse for ExprWhile {
2646 fn parse(input: ParseStream) -> Result<Self> {
2647 let mut attrs = input.call(Attribute::parse_outer)?;
2648 let label: Option<Label> = input.parse()?;
2649 let while_token: crate::token::WhileToken![while] = input.parse()?;
2650 let cond = Expr::parse_without_eager_brace(input)?;
2651
2652 let content;
2653 let brace_token = match crate::__private::parse_braces(&input) {
crate::__private::Ok(braces) => {
content = braces.content;
_ = content;
braces.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2654 attr::parsing::parse_inner(&content, &mut attrs)?;
2655 let stmts = content.call(Block::parse_within)?;
2656
2657 Ok(ExprWhile {
2658 attrs,
2659 label,
2660 while_token,
2661 cond: Box::new(cond),
2662 body: Block { brace_token, stmts },
2663 })
2664 }
2665 }
2666
2667 #[cfg(feature = "full")]
2668 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2669 impl Parse for ExprConst {
2670 fn parse(input: ParseStream) -> Result<Self> {
2671 let const_token: crate::token::ConstToken![const] = input.parse()?;
2672
2673 let content;
2674 let brace_token = match crate::__private::parse_braces(&input) {
crate::__private::Ok(braces) => {
content = braces.content;
_ = content;
braces.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2675 let inner_attrs = content.call(Attribute::parse_inner)?;
2676 let stmts = content.call(Block::parse_within)?;
2677
2678 Ok(ExprConst {
2679 attrs: inner_attrs,
2680 const_token,
2681 block: Block { brace_token, stmts },
2682 })
2683 }
2684 }
2685
2686 #[cfg(feature = "full")]
2687 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2688 impl Parse for Label {
2689 fn parse(input: ParseStream) -> Result<Self> {
2690 Ok(Label {
2691 name: input.parse()?,
2692 colon_token: input.parse()?,
2693 })
2694 }
2695 }
2696
2697 #[cfg(feature = "full")]
2698 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2699 impl Parse for Option<Label> {
2700 fn parse(input: ParseStream) -> Result<Self> {
2701 if input.peek(Lifetime) {
2702 input.parse().map(Some)
2703 } else {
2704 Ok(None)
2705 }
2706 }
2707 }
2708
2709 #[cfg(feature = "full")]
2710 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2711 impl Parse for ExprContinue {
2712 fn parse(input: ParseStream) -> Result<Self> {
2713 Ok(ExprContinue {
2714 attrs: Vec::new(),
2715 continue_token: input.parse()?,
2716 label: input.parse()?,
2717 })
2718 }
2719 }
2720
2721 #[cfg(feature = "full")]
2722 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2723 let break_token: crate::token::BreakToken![break] = input.parse()?;
2724
2725 let ahead = input.fork();
2726 let label: Option<Lifetime> = ahead.parse()?;
2727 if label.is_some() && ahead.peek(crate::token::ColonToken![:]) {
2728 let _: Expr = input.parse()?;
2731 let start_span = label.unwrap().apostrophe;
2732 let end_span = input.cursor().prev_span();
2733 return Err(crate::error::new2(
2734 start_span,
2735 end_span,
2736 "parentheses required",
2737 ));
2738 }
2739
2740 input.advance_to(&ahead);
2741 let expr = if Expr::peek(input) && (allow_struct.0 || !input.peek(token::Brace)) {
2742 Some(input.parse()?)
2743 } else {
2744 None
2745 };
2746
2747 Ok(ExprBreak {
2748 attrs: Vec::new(),
2749 break_token,
2750 label,
2751 expr,
2752 })
2753 }
2754
2755 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2756 impl Parse for FieldValue {
2757 fn parse(input: ParseStream) -> Result<Self> {
2758 let attrs = input.call(Attribute::parse_outer)?;
2759 let member: Member = input.parse()?;
2760 let (colon_token, value) = if input.peek(crate::token::ColonToken![:]) || !member.is_named() {
2761 let colon_token: crate::token::ColonToken![:] = input.parse()?;
2762 let value: Expr = input.parse()?;
2763 (Some(colon_token), value)
2764 } else if let Member::Named(ident) = &member {
2765 let value = Expr::Path(ExprPath {
2766 attrs: Vec::new(),
2767 qself: None,
2768 path: Path::from(ident.clone()),
2769 });
2770 (None, value)
2771 } else {
2772 ::core::panicking::panic("internal error: entered unreachable code")unreachable!()
2773 };
2774
2775 Ok(FieldValue {
2776 attrs,
2777 member,
2778 colon_token,
2779 expr: value,
2780 })
2781 }
2782 }
2783
2784 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2785 impl Parse for ExprStruct {
2786 fn parse(input: ParseStream) -> Result<Self> {
2787 let expr_style = true;
2788 let (qself, path) = path::parsing::qpath(input, expr_style)?;
2789 expr_struct_helper(input, qself, path)
2790 }
2791 }
2792
2793 fn expr_struct_helper(
2794 input: ParseStream,
2795 qself: Option<QSelf>,
2796 path: Path,
2797 ) -> Result<ExprStruct> {
2798 let content;
2799 let brace_token = match crate::__private::parse_braces(&input) {
crate::__private::Ok(braces) => {
content = braces.content;
_ = content;
braces.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2800
2801 let mut fields = Punctuated::new();
2802 while !content.is_empty() {
2803 if content.peek(crate::token::DotDotToken![..]) {
2804 return Ok(ExprStruct {
2805 attrs: Vec::new(),
2806 qself,
2807 path,
2808 brace_token,
2809 fields,
2810 dot2_token: Some(content.parse()?),
2811 rest: if content.is_empty() {
2812 None
2813 } else {
2814 Some(Box::new(content.parse()?))
2815 },
2816 });
2817 }
2818
2819 fields.push(content.parse()?);
2820 if content.is_empty() {
2821 break;
2822 }
2823 let punct: crate::token::CommaToken![,] = content.parse()?;
2824 fields.push_punct(punct);
2825 }
2826
2827 Ok(ExprStruct {
2828 attrs: Vec::new(),
2829 qself,
2830 path,
2831 brace_token,
2832 fields,
2833 dot2_token: None,
2834 rest: None,
2835 })
2836 }
2837
2838 #[cfg(feature = "full")]
2839 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2840 impl Parse for ExprUnsafe {
2841 fn parse(input: ParseStream) -> Result<Self> {
2842 let unsafe_token: crate::token::UnsafeToken![unsafe] = input.parse()?;
2843
2844 let content;
2845 let brace_token = match crate::__private::parse_braces(&input) {
crate::__private::Ok(braces) => {
content = braces.content;
_ = content;
braces.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2846 let inner_attrs = content.call(Attribute::parse_inner)?;
2847 let stmts = content.call(Block::parse_within)?;
2848
2849 Ok(ExprUnsafe {
2850 attrs: inner_attrs,
2851 unsafe_token,
2852 block: Block { brace_token, stmts },
2853 })
2854 }
2855 }
2856
2857 #[cfg(feature = "full")]
2858 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2859 impl Parse for ExprBlock {
2860 fn parse(input: ParseStream) -> Result<Self> {
2861 let mut attrs = input.call(Attribute::parse_outer)?;
2862 let label: Option<Label> = input.parse()?;
2863
2864 let content;
2865 let brace_token = match crate::__private::parse_braces(&input) {
crate::__private::Ok(braces) => {
content = braces.content;
_ = content;
braces.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2866 attr::parsing::parse_inner(&content, &mut attrs)?;
2867 let stmts = content.call(Block::parse_within)?;
2868
2869 Ok(ExprBlock {
2870 attrs,
2871 label,
2872 block: Block { brace_token, stmts },
2873 })
2874 }
2875 }
2876
2877 #[cfg(feature = "full")]
2878 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2879 let limits: RangeLimits = input.parse()?;
2880 let end = parse_range_end(input, &limits, allow_struct)?;
2881 Ok(ExprRange {
2882 attrs: Vec::new(),
2883 start: None,
2884 limits,
2885 end,
2886 })
2887 }
2888
2889 #[cfg(feature = "full")]
2890 fn parse_range_end(
2891 input: ParseStream,
2892 limits: &RangeLimits,
2893 allow_struct: AllowStruct,
2894 ) -> Result<Option<Box<Expr>>> {
2895 if #[allow(non_exhaustive_omitted_patterns)] match limits {
RangeLimits::HalfOpen(_) => true,
_ => false,
}matches!(limits, RangeLimits::HalfOpen(_))
2896 && (input.is_empty()
2897 || input.peek(crate::token::CommaToken![,])
2898 || input.peek(crate::token::SemiToken![;])
2899 || input.peek(crate::token::DotToken![.]) && !input.peek(crate::token::DotDotToken![..])
2900 || input.peek(crate::token::QuestionToken![?])
2901 || input.peek(crate::token::FatArrowToken![=>])
2902 || !allow_struct.0 && input.peek(token::Brace)
2903 || input.peek(crate::token::EqToken![=])
2904 || input.peek(crate::token::PlusToken![+])
2905 || input.peek(crate::token::SlashToken![/])
2906 || input.peek(crate::token::PercentToken![%])
2907 || input.peek(crate::token::CaretToken![^])
2908 || input.peek(crate::token::GtToken![>])
2909 || input.peek(crate::token::LeToken![<=])
2910 || input.peek(crate::token::NeToken![!=])
2911 || input.peek(crate::token::MinusEqToken![-=])
2912 || input.peek(crate::token::StarEqToken![*=])
2913 || input.peek(crate::token::AndEqToken![&=])
2914 || input.peek(crate::token::OrEqToken![|=])
2915 || input.peek(crate::token::ShlEqToken![<<=])
2916 || input.peek(crate::token::AsToken![as]))
2917 {
2918 Ok(None)
2919 } else {
2920 let end = parse_binop_rhs(input, allow_struct, Precedence::Range)?;
2921 Ok(Some(end))
2922 }
2923 }
2924
2925 #[cfg(feature = "full")]
2926 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2927 impl Parse for RangeLimits {
2928 fn parse(input: ParseStream) -> Result<Self> {
2929 let lookahead = input.lookahead1();
2930 let dot_dot = lookahead.peek(crate::token::DotDotToken![..]);
2931 let dot_dot_eq = dot_dot && lookahead.peek(crate::token::DotDotEqToken![..=]);
2932 let dot_dot_dot = dot_dot && input.peek(crate::token::DotDotDotToken![...]);
2933 if dot_dot_eq {
2934 input.parse().map(RangeLimits::Closed)
2935 } else if dot_dot && !dot_dot_dot {
2936 input.parse().map(RangeLimits::HalfOpen)
2937 } else {
2938 Err(lookahead.error())
2939 }
2940 }
2941 }
2942
2943 #[cfg(feature = "full")]
2944 impl RangeLimits {
2945 pub(crate) fn parse_obsolete(input: ParseStream) -> Result<Self> {
2946 let lookahead = input.lookahead1();
2947 let dot_dot = lookahead.peek(crate::token::DotDotToken![..]);
2948 let dot_dot_eq = dot_dot && lookahead.peek(crate::token::DotDotEqToken![..=]);
2949 let dot_dot_dot = dot_dot && input.peek(crate::token::DotDotDotToken![...]);
2950 if dot_dot_eq {
2951 input.parse().map(RangeLimits::Closed)
2952 } else if dot_dot_dot {
2953 let dot3: crate::token::DotDotDotToken![...] = input.parse()?;
2954 Ok(RangeLimits::Closed(crate::token::DotDotEqToken))
2955 } else if dot_dot {
2956 input.parse().map(RangeLimits::HalfOpen)
2957 } else {
2958 Err(lookahead.error())
2959 }
2960 }
2961 }
2962
2963 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2964 impl Parse for ExprPath {
2965 fn parse(input: ParseStream) -> Result<Self> {
2966 #[cfg(not(feature = "full"))]
2967 let attrs = Vec::new();
2968 #[cfg(feature = "full")]
2969 let attrs = input.call(Attribute::parse_outer)?;
2970
2971 let expr_style = true;
2972 let (qself, path) = path::parsing::qpath(input, expr_style)?;
2973
2974 Ok(ExprPath { attrs, qself, path })
2975 }
2976 }
2977
2978 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2979 impl Parse for Member {
2980 fn parse(input: ParseStream) -> Result<Self> {
2981 if input.peek(Ident) {
2982 input.parse().map(Member::Named)
2983 } else if input.peek(LitInt) {
2984 input.parse().map(Member::Unnamed)
2985 } else {
2986 Err(input.error("expected identifier or integer"))
2987 }
2988 }
2989 }
2990
2991 #[cfg(feature = "full")]
2992 impl Arm {
2993 pub(crate) fn parse_multiple(input: ParseStream) -> Result<Vec<Self>> {
2994 let mut arms = Vec::new();
2995 while !input.is_empty() {
2996 arms.push(input.call(Arm::parse)?);
2997 }
2998 Ok(arms)
2999 }
3000 }
3001
3002 #[cfg(feature = "full")]
3003 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3004 impl Parse for Arm {
3005 fn parse(input: ParseStream) -> Result<Arm> {
3006 let requires_comma;
3007 Ok(Arm {
3008 attrs: input.call(Attribute::parse_outer)?,
3009 pat: Pat::parse_multi_with_leading_vert(input)?,
3010 guard: {
3011 if input.peek(crate::token::IfToken![if]) {
3012 let if_token: crate::token::IfToken![if] = input.parse()?;
3013 let guard: Expr = input.parse()?;
3014 Some((if_token, Box::new(guard)))
3015 } else {
3016 None
3017 }
3018 },
3019 fat_arrow_token: input.parse()?,
3020 body: {
3021 let body = Expr::parse_with_earlier_boundary_rule(input)?;
3022 requires_comma = classify::requires_comma_to_be_match_arm(&body);
3023 Box::new(body)
3024 },
3025 comma: {
3026 if requires_comma && !input.is_empty() {
3027 Some(input.parse()?)
3028 } else {
3029 input.parse()?
3030 }
3031 },
3032 })
3033 }
3034 }
3035
3036 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3037 impl Parse for Index {
3038 fn parse(input: ParseStream) -> Result<Self> {
3039 let lit: LitInt = input.parse()?;
3040 if lit.suffix().is_empty() {
3041 Ok(Index {
3042 index: lit
3043 .base10_digits()
3044 .parse()
3045 .map_err(|err| Error::new(lit.span(), err))?,
3046 span: lit.span(),
3047 })
3048 } else {
3049 Err(Error::new(lit.span(), "expected unsuffixed integer"))
3050 }
3051 }
3052 }
3053
3054 fn multi_index(e: &mut Expr, dot_token: &mut crate::token::DotToken![.], float: LitFloat) -> Result<bool> {
3055 let float_token = float.token();
3056 let float_span = float_token.span();
3057 let mut float_repr = float_token.to_string();
3058 let trailing_dot = float_repr.ends_with('.');
3059 if trailing_dot {
3060 float_repr.truncate(float_repr.len() - 1);
3061 }
3062
3063 let mut offset = 0;
3064 for part in float_repr.split('.') {
3065 let mut index: Index =
3066 crate::parse_str(part).map_err(|err| Error::new(float_span, err))?;
3067 let part_end = offset + part.len();
3068 index.span = float_token.subspan(offset..part_end).unwrap_or(float_span);
3069
3070 let base = mem::replace(e, Expr::PLACEHOLDER);
3071 *e = Expr::Field(ExprField {
3072 attrs: Vec::new(),
3073 base: Box::new(base),
3074 dot_token: crate::token::DotToken,
3075 member: Member::Unnamed(index),
3076 });
3077
3078 let dot_span = float_token
3079 .subspan(part_end..part_end + 1)
3080 .unwrap_or(float_span);
3081 *dot_token = crate::token::DotToken;
3082 offset = part_end + 1;
3083 }
3084
3085 Ok(!trailing_dot)
3086 }
3087
3088 #[cfg(feature = "full")]
3089 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3090 impl Parse for PointerMutability {
3091 fn parse(input: ParseStream) -> Result<Self> {
3092 let lookahead = input.lookahead1();
3093 if lookahead.peek(crate::token::ConstToken![const]) {
3094 Ok(PointerMutability::Const(input.parse()?))
3095 } else if lookahead.peek(crate::token::MutToken![mut]) {
3096 Ok(PointerMutability::Mut(input.parse()?))
3097 } else {
3098 Err(lookahead.error())
3099 }
3100 }
3101 }
3102
3103 fn check_cast(input: ParseStream) -> Result<()> {
3104 let kind = if input.peek(crate::token::DotToken![.]) && !input.peek(crate::token::DotDotToken![..]) {
3105 if input.peek2(crate::token::AwaitToken![await]) {
3106 "`.await`"
3107 } else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(crate::token::PathSepToken![::])) {
3108 "a method call"
3109 } else {
3110 "a field access"
3111 }
3112 } else if input.peek(crate::token::QuestionToken![?]) {
3113 "`?`"
3114 } else if input.peek(token::Bracket) {
3115 "indexing"
3116 } else if input.peek(token::Paren) {
3117 "a function call"
3118 } else {
3119 return Ok(());
3120 };
3121 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("casts cannot be followed by {0}",
kind))
})format!("casts cannot be followed by {}", kind);
3122 Err(input.error(msg))
3123 }
3124}
3125
3126#[cfg(feature = "printing")]
3127pub(crate) mod printing {
3128 use crate::attr::Attribute;
3129 #[cfg(feature = "full")]
3130 use crate::attr::FilterAttrs;
3131 #[cfg(feature = "full")]
3132 use crate::classify;
3133 #[cfg(feature = "full")]
3134 use crate::expr::{
3135 Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
3136 ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
3137 ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
3138 ExprWhile, ExprYield, Label, PointerMutability, RangeLimits,
3139 };
3140 use crate::expr::{
3141 Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
3142 ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
3143 FieldValue, Index, Member,
3144 };
3145 use crate::fixup::FixupContext;
3146 use crate::op::BinOp;
3147 use crate::path;
3148 use crate::path::printing::PathStyle;
3149 use crate::precedence::Precedence;
3150 use crate::token;
3151 #[cfg(feature = "full")]
3152 use crate::ty::ReturnType;
3153 use proc_macro2::{Literal, Span, TokenStream};
3154 use quote::{ToTokens, TokenStreamExt as _};
3155
3156 #[cfg(feature = "full")]
3157 pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3158 tokens.append_all(attrs.outer());
3159 }
3160
3161 #[cfg(feature = "full")]
3162 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3163 tokens.append_all(attrs.inner());
3164 }
3165
3166 #[cfg(not(feature = "full"))]
3167 pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3168
3169 pub(crate) fn print_subexpression(
3170 expr: &Expr,
3171 needs_group: bool,
3172 tokens: &mut TokenStream,
3173 mut fixup: FixupContext,
3174 ) {
3175 if needs_group {
3176 fixup = FixupContext::NONE;
3188 }
3189
3190 let do_print_expr = |tokens: &mut TokenStream| print_expr(expr, tokens, fixup);
3191
3192 if needs_group {
3193 token::Paren::default().surround(tokens, do_print_expr);
3194 } else {
3195 do_print_expr(tokens);
3196 }
3197 }
3198
3199 pub(crate) fn print_expr(expr: &Expr, tokens: &mut TokenStream, mut fixup: FixupContext) {
3200 #[cfg(feature = "full")]
3201 let needs_group = fixup.parenthesize(expr);
3202 #[cfg(not(feature = "full"))]
3203 let needs_group = false;
3204
3205 if needs_group {
3206 fixup = FixupContext::NONE;
3207 }
3208
3209 let do_print_expr = |tokens: &mut TokenStream| match expr {
3210 #[cfg(feature = "full")]
3211 Expr::Array(e) => e.to_tokens(tokens),
3212 #[cfg(feature = "full")]
3213 Expr::Assign(e) => print_expr_assign(e, tokens, fixup),
3214 #[cfg(feature = "full")]
3215 Expr::Async(e) => e.to_tokens(tokens),
3216 #[cfg(feature = "full")]
3217 Expr::Await(e) => print_expr_await(e, tokens, fixup),
3218 Expr::Binary(e) => print_expr_binary(e, tokens, fixup),
3219 #[cfg(feature = "full")]
3220 Expr::Block(e) => e.to_tokens(tokens),
3221 #[cfg(feature = "full")]
3222 Expr::Break(e) => print_expr_break(e, tokens, fixup),
3223 Expr::Call(e) => print_expr_call(e, tokens, fixup),
3224 Expr::Cast(e) => print_expr_cast(e, tokens, fixup),
3225 #[cfg(feature = "full")]
3226 Expr::Closure(e) => print_expr_closure(e, tokens, fixup),
3227 #[cfg(feature = "full")]
3228 Expr::Const(e) => e.to_tokens(tokens),
3229 #[cfg(feature = "full")]
3230 Expr::Continue(e) => e.to_tokens(tokens),
3231 Expr::Field(e) => print_expr_field(e, tokens, fixup),
3232 #[cfg(feature = "full")]
3233 Expr::ForLoop(e) => e.to_tokens(tokens),
3234 Expr::Group(e) => e.to_tokens(tokens),
3235 #[cfg(feature = "full")]
3236 Expr::If(e) => e.to_tokens(tokens),
3237 Expr::Index(e) => print_expr_index(e, tokens, fixup),
3238 #[cfg(feature = "full")]
3239 Expr::Infer(e) => e.to_tokens(tokens),
3240 #[cfg(feature = "full")]
3241 Expr::Let(e) => print_expr_let(e, tokens, fixup),
3242 Expr::Lit(e) => e.to_tokens(tokens),
3243 #[cfg(feature = "full")]
3244 Expr::Loop(e) => e.to_tokens(tokens),
3245 Expr::Macro(e) => e.to_tokens(tokens),
3246 #[cfg(feature = "full")]
3247 Expr::Match(e) => e.to_tokens(tokens),
3248 Expr::MethodCall(e) => print_expr_method_call(e, tokens, fixup),
3249 Expr::Paren(e) => e.to_tokens(tokens),
3250 Expr::Path(e) => e.to_tokens(tokens),
3251 #[cfg(feature = "full")]
3252 Expr::Range(e) => print_expr_range(e, tokens, fixup),
3253 #[cfg(feature = "full")]
3254 Expr::RawAddr(e) => print_expr_raw_addr(e, tokens, fixup),
3255 Expr::Reference(e) => print_expr_reference(e, tokens, fixup),
3256 #[cfg(feature = "full")]
3257 Expr::Repeat(e) => e.to_tokens(tokens),
3258 #[cfg(feature = "full")]
3259 Expr::Return(e) => print_expr_return(e, tokens, fixup),
3260 Expr::Struct(e) => e.to_tokens(tokens),
3261 #[cfg(feature = "full")]
3262 Expr::Try(e) => print_expr_try(e, tokens, fixup),
3263 #[cfg(feature = "full")]
3264 Expr::TryBlock(e) => e.to_tokens(tokens),
3265 Expr::Tuple(e) => e.to_tokens(tokens),
3266 Expr::Unary(e) => print_expr_unary(e, tokens, fixup),
3267 #[cfg(feature = "full")]
3268 Expr::Unsafe(e) => e.to_tokens(tokens),
3269 Expr::Verbatim(e) => e.to_tokens(tokens),
3270 #[cfg(feature = "full")]
3271 Expr::While(e) => e.to_tokens(tokens),
3272 #[cfg(feature = "full")]
3273 Expr::Yield(e) => print_expr_yield(e, tokens, fixup),
3274
3275 #[cfg(not(feature = "full"))]
3276 _ => unreachable!(),
3277 };
3278
3279 if needs_group {
3280 token::Paren::default().surround(tokens, do_print_expr);
3281 } else {
3282 do_print_expr(tokens);
3283 }
3284 }
3285
3286 #[cfg(feature = "full")]
3287 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3288 impl ToTokens for ExprArray {
3289 fn to_tokens(&self, tokens: &mut TokenStream) {
3290 outer_attrs_to_tokens(&self.attrs, tokens);
3291 self.bracket_token.surround(tokens, |tokens| {
3292 self.elems.to_tokens(tokens);
3293 });
3294 }
3295 }
3296
3297 #[cfg(feature = "full")]
3298 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3299 impl ToTokens for ExprAssign {
3300 fn to_tokens(&self, tokens: &mut TokenStream) {
3301 print_expr_assign(self, tokens, FixupContext::NONE);
3302 }
3303 }
3304
3305 #[cfg(feature = "full")]
3306 fn print_expr_assign(e: &ExprAssign, tokens: &mut TokenStream, mut fixup: FixupContext) {
3307 outer_attrs_to_tokens(&e.attrs, tokens);
3308
3309 let needs_group = !e.attrs.is_empty();
3310 if needs_group {
3311 fixup = FixupContext::NONE;
3312 }
3313
3314 let do_print_expr = |tokens: &mut TokenStream| {
3315 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3316 &e.left,
3317 false,
3318 false,
3319 Precedence::Assign,
3320 );
3321 print_subexpression(&e.left, left_prec <= Precedence::Range, tokens, left_fixup);
3322 e.eq_token.to_tokens(tokens);
3323 print_expr(
3324 &e.right,
3325 tokens,
3326 fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign),
3327 );
3328 };
3329
3330 if needs_group {
3331 token::Paren::default().surround(tokens, do_print_expr);
3332 } else {
3333 do_print_expr(tokens);
3334 }
3335 }
3336
3337 #[cfg(feature = "full")]
3338 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3339 impl ToTokens for ExprAsync {
3340 fn to_tokens(&self, tokens: &mut TokenStream) {
3341 outer_attrs_to_tokens(&self.attrs, tokens);
3342 self.async_token.to_tokens(tokens);
3343 self.capture.to_tokens(tokens);
3344 self.block.to_tokens(tokens);
3345 }
3346 }
3347
3348 #[cfg(feature = "full")]
3349 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3350 impl ToTokens for ExprAwait {
3351 fn to_tokens(&self, tokens: &mut TokenStream) {
3352 print_expr_await(self, tokens, FixupContext::NONE);
3353 }
3354 }
3355
3356 #[cfg(feature = "full")]
3357 fn print_expr_await(e: &ExprAwait, tokens: &mut TokenStream, fixup: FixupContext) {
3358 outer_attrs_to_tokens(&e.attrs, tokens);
3359 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3360 print_subexpression(
3361 &e.base,
3362 left_prec < Precedence::Unambiguous,
3363 tokens,
3364 left_fixup,
3365 );
3366 e.dot_token.to_tokens(tokens);
3367 e.await_token.to_tokens(tokens);
3368 }
3369
3370 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3371 impl ToTokens for ExprBinary {
3372 fn to_tokens(&self, tokens: &mut TokenStream) {
3373 print_expr_binary(self, tokens, FixupContext::NONE);
3374 }
3375 }
3376
3377 fn print_expr_binary(e: &ExprBinary, tokens: &mut TokenStream, mut fixup: FixupContext) {
3378 outer_attrs_to_tokens(&e.attrs, tokens);
3379
3380 let needs_group = !e.attrs.is_empty();
3381 if needs_group {
3382 fixup = FixupContext::NONE;
3383 }
3384
3385 let do_print_expr = |tokens: &mut TokenStream| {
3386 let binop_prec = Precedence::of_binop(&e.op);
3387 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3388 &e.left,
3389 #[cfg(feature = "full")]
3390 match &e.op {
3391 BinOp::Sub(_)
3392 | BinOp::Mul(_)
3393 | BinOp::And(_)
3394 | BinOp::Or(_)
3395 | BinOp::BitAnd(_)
3396 | BinOp::BitOr(_)
3397 | BinOp::Shl(_)
3398 | BinOp::Lt(_) => true,
3399 _ => false,
3400 },
3401 match &e.op {
3402 BinOp::Shl(_) | BinOp::Lt(_) => true,
3403 _ => false,
3404 },
3405 #[cfg(feature = "full")]
3406 binop_prec,
3407 );
3408 let left_needs_group = match binop_prec {
3409 Precedence::Assign => left_prec <= Precedence::Range,
3410 Precedence::Compare => left_prec <= binop_prec,
3411 _ => left_prec < binop_prec,
3412 };
3413
3414 let right_fixup = fixup.rightmost_subexpression_fixup(
3415 #[cfg(feature = "full")]
3416 false,
3417 #[cfg(feature = "full")]
3418 false,
3419 #[cfg(feature = "full")]
3420 binop_prec,
3421 );
3422 let right_needs_group = binop_prec != Precedence::Assign
3423 && right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
3424
3425 print_subexpression(&e.left, left_needs_group, tokens, left_fixup);
3426 e.op.to_tokens(tokens);
3427 print_subexpression(&e.right, right_needs_group, tokens, right_fixup);
3428 };
3429
3430 if needs_group {
3431 token::Paren::default().surround(tokens, do_print_expr);
3432 } else {
3433 do_print_expr(tokens);
3434 }
3435 }
3436
3437 #[cfg(feature = "full")]
3438 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3439 impl ToTokens for ExprBlock {
3440 fn to_tokens(&self, tokens: &mut TokenStream) {
3441 outer_attrs_to_tokens(&self.attrs, tokens);
3442 self.label.to_tokens(tokens);
3443 self.block.brace_token.surround(tokens, |tokens| {
3444 inner_attrs_to_tokens(&self.attrs, tokens);
3445 tokens.append_all(&self.block.stmts);
3446 });
3447 }
3448 }
3449
3450 #[cfg(feature = "full")]
3451 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3452 impl ToTokens for ExprBreak {
3453 fn to_tokens(&self, tokens: &mut TokenStream) {
3454 print_expr_break(self, tokens, FixupContext::NONE);
3455 }
3456 }
3457
3458 #[cfg(feature = "full")]
3459 fn print_expr_break(e: &ExprBreak, tokens: &mut TokenStream, fixup: FixupContext) {
3460 outer_attrs_to_tokens(&e.attrs, tokens);
3461 e.break_token.to_tokens(tokens);
3462 e.label.to_tokens(tokens);
3463 if let Some(value) = &e.expr {
3464 print_subexpression(
3465 value,
3466 e.label.is_none() && classify::expr_leading_label(value),
3469 tokens,
3470 fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump),
3471 );
3472 }
3473 }
3474
3475 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3476 impl ToTokens for ExprCall {
3477 fn to_tokens(&self, tokens: &mut TokenStream) {
3478 print_expr_call(self, tokens, FixupContext::NONE);
3479 }
3480 }
3481
3482 fn print_expr_call(e: &ExprCall, tokens: &mut TokenStream, fixup: FixupContext) {
3483 outer_attrs_to_tokens(&e.attrs, tokens);
3484
3485 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3486 &e.func,
3487 #[cfg(feature = "full")]
3488 true,
3489 false,
3490 #[cfg(feature = "full")]
3491 Precedence::Unambiguous,
3492 );
3493 let needs_group = if let Expr::Field(func) = &*e.func {
3494 func.member.is_named()
3495 } else {
3496 left_prec < Precedence::Unambiguous
3497 };
3498 print_subexpression(&e.func, needs_group, tokens, left_fixup);
3499
3500 e.paren_token.surround(tokens, |tokens| {
3501 e.args.to_tokens(tokens);
3502 });
3503 }
3504
3505 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3506 impl ToTokens for ExprCast {
3507 fn to_tokens(&self, tokens: &mut TokenStream) {
3508 print_expr_cast(self, tokens, FixupContext::NONE);
3509 }
3510 }
3511
3512 fn print_expr_cast(e: &ExprCast, tokens: &mut TokenStream, mut fixup: FixupContext) {
3513 outer_attrs_to_tokens(&e.attrs, tokens);
3514
3515 let needs_group = !e.attrs.is_empty();
3516 if needs_group {
3517 fixup = FixupContext::NONE;
3518 }
3519
3520 let do_print_expr = |tokens: &mut TokenStream| {
3521 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3522 &e.expr,
3523 #[cfg(feature = "full")]
3524 false,
3525 false,
3526 #[cfg(feature = "full")]
3527 Precedence::Cast,
3528 );
3529 print_subexpression(&e.expr, left_prec < Precedence::Cast, tokens, left_fixup);
3530 e.as_token.to_tokens(tokens);
3531 e.ty.to_tokens(tokens);
3532 };
3533
3534 if needs_group {
3535 token::Paren::default().surround(tokens, do_print_expr);
3536 } else {
3537 do_print_expr(tokens);
3538 }
3539 }
3540
3541 #[cfg(feature = "full")]
3542 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3543 impl ToTokens for ExprClosure {
3544 fn to_tokens(&self, tokens: &mut TokenStream) {
3545 print_expr_closure(self, tokens, FixupContext::NONE);
3546 }
3547 }
3548
3549 #[cfg(feature = "full")]
3550 fn print_expr_closure(e: &ExprClosure, tokens: &mut TokenStream, fixup: FixupContext) {
3551 outer_attrs_to_tokens(&e.attrs, tokens);
3552 e.lifetimes.to_tokens(tokens);
3553 e.constness.to_tokens(tokens);
3554 e.movability.to_tokens(tokens);
3555 e.asyncness.to_tokens(tokens);
3556 e.capture.to_tokens(tokens);
3557 e.or1_token.to_tokens(tokens);
3558 e.inputs.to_tokens(tokens);
3559 e.or2_token.to_tokens(tokens);
3560 e.output.to_tokens(tokens);
3561 if #[allow(non_exhaustive_omitted_patterns)] match e.output {
ReturnType::Default => true,
_ => false,
}matches!(e.output, ReturnType::Default)
3562 || #[allow(non_exhaustive_omitted_patterns)] match &*e.body {
Expr::Block(body) if body.attrs.is_empty() && body.label.is_none() =>
true,
_ => false,
}matches!(&*e.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
3563 {
3564 print_expr(
3565 &e.body,
3566 tokens,
3567 fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
3568 );
3569 } else {
3570 token::Brace::default().surround(tokens, |tokens| {
3571 print_expr(&e.body, tokens, FixupContext::new_stmt());
3572 });
3573 }
3574 }
3575
3576 #[cfg(feature = "full")]
3577 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3578 impl ToTokens for ExprConst {
3579 fn to_tokens(&self, tokens: &mut TokenStream) {
3580 outer_attrs_to_tokens(&self.attrs, tokens);
3581 self.const_token.to_tokens(tokens);
3582 self.block.brace_token.surround(tokens, |tokens| {
3583 inner_attrs_to_tokens(&self.attrs, tokens);
3584 tokens.append_all(&self.block.stmts);
3585 });
3586 }
3587 }
3588
3589 #[cfg(feature = "full")]
3590 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3591 impl ToTokens for ExprContinue {
3592 fn to_tokens(&self, tokens: &mut TokenStream) {
3593 outer_attrs_to_tokens(&self.attrs, tokens);
3594 self.continue_token.to_tokens(tokens);
3595 self.label.to_tokens(tokens);
3596 }
3597 }
3598
3599 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3600 impl ToTokens for ExprField {
3601 fn to_tokens(&self, tokens: &mut TokenStream) {
3602 print_expr_field(self, tokens, FixupContext::NONE);
3603 }
3604 }
3605
3606 fn print_expr_field(e: &ExprField, tokens: &mut TokenStream, fixup: FixupContext) {
3607 outer_attrs_to_tokens(&e.attrs, tokens);
3608 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3609 print_subexpression(
3610 &e.base,
3611 left_prec < Precedence::Unambiguous,
3612 tokens,
3613 left_fixup,
3614 );
3615 e.dot_token.to_tokens(tokens);
3616 e.member.to_tokens(tokens);
3617 }
3618
3619 #[cfg(feature = "full")]
3620 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3621 impl ToTokens for ExprForLoop {
3622 fn to_tokens(&self, tokens: &mut TokenStream) {
3623 outer_attrs_to_tokens(&self.attrs, tokens);
3624 self.label.to_tokens(tokens);
3625 self.for_token.to_tokens(tokens);
3626 self.pat.to_tokens(tokens);
3627 self.in_token.to_tokens(tokens);
3628 print_expr(&self.expr, tokens, FixupContext::new_condition());
3629 self.body.brace_token.surround(tokens, |tokens| {
3630 inner_attrs_to_tokens(&self.attrs, tokens);
3631 tokens.append_all(&self.body.stmts);
3632 });
3633 }
3634 }
3635
3636 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3637 impl ToTokens for ExprGroup {
3638 fn to_tokens(&self, tokens: &mut TokenStream) {
3639 outer_attrs_to_tokens(&self.attrs, tokens);
3640 self.group_token.surround(tokens, |tokens| {
3641 self.expr.to_tokens(tokens);
3642 });
3643 }
3644 }
3645
3646 #[cfg(feature = "full")]
3647 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3648 impl ToTokens for ExprIf {
3649 fn to_tokens(&self, tokens: &mut TokenStream) {
3650 outer_attrs_to_tokens(&self.attrs, tokens);
3651
3652 let mut expr = self;
3653 loop {
3654 expr.if_token.to_tokens(tokens);
3655 print_expr(&expr.cond, tokens, FixupContext::new_condition());
3656 expr.then_branch.to_tokens(tokens);
3657
3658 let (else_token, else_) = match &expr.else_branch {
3659 Some(else_branch) => else_branch,
3660 None => break,
3661 };
3662
3663 else_token.to_tokens(tokens);
3664 match &**else_ {
3665 Expr::If(next) => {
3666 expr = next;
3667 }
3668 Expr::Block(last) => {
3669 last.to_tokens(tokens);
3670 break;
3671 }
3672 other => {
3675 token::Brace::default().surround(tokens, |tokens| {
3676 print_expr(other, tokens, FixupContext::new_stmt());
3677 });
3678 break;
3679 }
3680 }
3681 }
3682 }
3683 }
3684
3685 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3686 impl ToTokens for ExprIndex {
3687 fn to_tokens(&self, tokens: &mut TokenStream) {
3688 print_expr_index(self, tokens, FixupContext::NONE);
3689 }
3690 }
3691
3692 fn print_expr_index(e: &ExprIndex, tokens: &mut TokenStream, fixup: FixupContext) {
3693 outer_attrs_to_tokens(&e.attrs, tokens);
3694 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3695 &e.expr,
3696 #[cfg(feature = "full")]
3697 true,
3698 false,
3699 #[cfg(feature = "full")]
3700 Precedence::Unambiguous,
3701 );
3702 print_subexpression(
3703 &e.expr,
3704 left_prec < Precedence::Unambiguous,
3705 tokens,
3706 left_fixup,
3707 );
3708 e.bracket_token.surround(tokens, |tokens| {
3709 e.index.to_tokens(tokens);
3710 });
3711 }
3712
3713 #[cfg(feature = "full")]
3714 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3715 impl ToTokens for ExprInfer {
3716 fn to_tokens(&self, tokens: &mut TokenStream) {
3717 outer_attrs_to_tokens(&self.attrs, tokens);
3718 self.underscore_token.to_tokens(tokens);
3719 }
3720 }
3721
3722 #[cfg(feature = "full")]
3723 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3724 impl ToTokens for ExprLet {
3725 fn to_tokens(&self, tokens: &mut TokenStream) {
3726 print_expr_let(self, tokens, FixupContext::NONE);
3727 }
3728 }
3729
3730 #[cfg(feature = "full")]
3731 fn print_expr_let(e: &ExprLet, tokens: &mut TokenStream, fixup: FixupContext) {
3732 outer_attrs_to_tokens(&e.attrs, tokens);
3733 e.let_token.to_tokens(tokens);
3734 e.pat.to_tokens(tokens);
3735 e.eq_token.to_tokens(tokens);
3736 let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Let);
3737 print_subexpression(&e.expr, right_prec < Precedence::Let, tokens, right_fixup);
3738 }
3739
3740 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3741 impl ToTokens for ExprLit {
3742 fn to_tokens(&self, tokens: &mut TokenStream) {
3743 outer_attrs_to_tokens(&self.attrs, tokens);
3744 self.lit.to_tokens(tokens);
3745 }
3746 }
3747
3748 #[cfg(feature = "full")]
3749 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3750 impl ToTokens for ExprLoop {
3751 fn to_tokens(&self, tokens: &mut TokenStream) {
3752 outer_attrs_to_tokens(&self.attrs, tokens);
3753 self.label.to_tokens(tokens);
3754 self.loop_token.to_tokens(tokens);
3755 self.body.brace_token.surround(tokens, |tokens| {
3756 inner_attrs_to_tokens(&self.attrs, tokens);
3757 tokens.append_all(&self.body.stmts);
3758 });
3759 }
3760 }
3761
3762 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3763 impl ToTokens for ExprMacro {
3764 fn to_tokens(&self, tokens: &mut TokenStream) {
3765 outer_attrs_to_tokens(&self.attrs, tokens);
3766 self.mac.to_tokens(tokens);
3767 }
3768 }
3769
3770 #[cfg(feature = "full")]
3771 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3772 impl ToTokens for ExprMatch {
3773 fn to_tokens(&self, tokens: &mut TokenStream) {
3774 outer_attrs_to_tokens(&self.attrs, tokens);
3775 self.match_token.to_tokens(tokens);
3776 print_expr(&self.expr, tokens, FixupContext::new_condition());
3777 self.brace_token.surround(tokens, |tokens| {
3778 inner_attrs_to_tokens(&self.attrs, tokens);
3779 for (i, arm) in self.arms.iter().enumerate() {
3780 arm.to_tokens(tokens);
3781 let is_last = i == self.arms.len() - 1;
3784 if !is_last
3785 && classify::requires_comma_to_be_match_arm(&arm.body)
3786 && arm.comma.is_none()
3787 {
3788 <crate::token::CommaToken![,]>::default().to_tokens(tokens);
3789 }
3790 }
3791 });
3792 }
3793 }
3794
3795 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3796 impl ToTokens for ExprMethodCall {
3797 fn to_tokens(&self, tokens: &mut TokenStream) {
3798 print_expr_method_call(self, tokens, FixupContext::NONE);
3799 }
3800 }
3801
3802 fn print_expr_method_call(e: &ExprMethodCall, tokens: &mut TokenStream, fixup: FixupContext) {
3803 outer_attrs_to_tokens(&e.attrs, tokens);
3804 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.receiver);
3805 print_subexpression(
3806 &e.receiver,
3807 left_prec < Precedence::Unambiguous,
3808 tokens,
3809 left_fixup,
3810 );
3811 e.dot_token.to_tokens(tokens);
3812 e.method.to_tokens(tokens);
3813 if let Some(turbofish) = &e.turbofish {
3814 path::printing::print_angle_bracketed_generic_arguments(
3815 tokens,
3816 turbofish,
3817 PathStyle::Expr,
3818 );
3819 }
3820 e.paren_token.surround(tokens, |tokens| {
3821 e.args.to_tokens(tokens);
3822 });
3823 }
3824
3825 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3826 impl ToTokens for ExprParen {
3827 fn to_tokens(&self, tokens: &mut TokenStream) {
3828 outer_attrs_to_tokens(&self.attrs, tokens);
3829 self.paren_token.surround(tokens, |tokens| {
3830 self.expr.to_tokens(tokens);
3831 });
3832 }
3833 }
3834
3835 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3836 impl ToTokens for ExprPath {
3837 fn to_tokens(&self, tokens: &mut TokenStream) {
3838 outer_attrs_to_tokens(&self.attrs, tokens);
3839 path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3840 }
3841 }
3842
3843 #[cfg(feature = "full")]
3844 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3845 impl ToTokens for ExprRange {
3846 fn to_tokens(&self, tokens: &mut TokenStream) {
3847 print_expr_range(self, tokens, FixupContext::NONE);
3848 }
3849 }
3850
3851 #[cfg(feature = "full")]
3852 fn print_expr_range(e: &ExprRange, tokens: &mut TokenStream, mut fixup: FixupContext) {
3853 outer_attrs_to_tokens(&e.attrs, tokens);
3854
3855 let needs_group = !e.attrs.is_empty();
3856 if needs_group {
3857 fixup = FixupContext::NONE;
3858 }
3859
3860 let do_print_expr = |tokens: &mut TokenStream| {
3861 if let Some(start) = &e.start {
3862 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3863 start,
3864 true,
3865 false,
3866 Precedence::Range,
3867 );
3868 print_subexpression(start, left_prec <= Precedence::Range, tokens, left_fixup);
3869 }
3870 e.limits.to_tokens(tokens);
3871 if let Some(end) = &e.end {
3872 let right_fixup =
3873 fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
3874 let right_prec = right_fixup.rightmost_subexpression_precedence(end);
3875 print_subexpression(end, right_prec <= Precedence::Range, tokens, right_fixup);
3876 }
3877 };
3878
3879 if needs_group {
3880 token::Paren::default().surround(tokens, do_print_expr);
3881 } else {
3882 do_print_expr(tokens);
3883 }
3884 }
3885
3886 #[cfg(feature = "full")]
3887 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3888 impl ToTokens for ExprRawAddr {
3889 fn to_tokens(&self, tokens: &mut TokenStream) {
3890 print_expr_raw_addr(self, tokens, FixupContext::NONE);
3891 }
3892 }
3893
3894 #[cfg(feature = "full")]
3895 fn print_expr_raw_addr(e: &ExprRawAddr, tokens: &mut TokenStream, fixup: FixupContext) {
3896 outer_attrs_to_tokens(&e.attrs, tokens);
3897 e.and_token.to_tokens(tokens);
3898 e.raw.to_tokens(tokens);
3899 e.mutability.to_tokens(tokens);
3900 let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Prefix);
3901 print_subexpression(
3902 &e.expr,
3903 right_prec < Precedence::Prefix,
3904 tokens,
3905 right_fixup,
3906 );
3907 }
3908
3909 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3910 impl ToTokens for ExprReference {
3911 fn to_tokens(&self, tokens: &mut TokenStream) {
3912 print_expr_reference(self, tokens, FixupContext::NONE);
3913 }
3914 }
3915
3916 fn print_expr_reference(e: &ExprReference, tokens: &mut TokenStream, fixup: FixupContext) {
3917 outer_attrs_to_tokens(&e.attrs, tokens);
3918 e.and_token.to_tokens(tokens);
3919 e.mutability.to_tokens(tokens);
3920 let (right_prec, right_fixup) = fixup.rightmost_subexpression(
3921 &e.expr,
3922 #[cfg(feature = "full")]
3923 Precedence::Prefix,
3924 );
3925 print_subexpression(
3926 &e.expr,
3927 right_prec < Precedence::Prefix,
3928 tokens,
3929 right_fixup,
3930 );
3931 }
3932
3933 #[cfg(feature = "full")]
3934 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3935 impl ToTokens for ExprRepeat {
3936 fn to_tokens(&self, tokens: &mut TokenStream) {
3937 outer_attrs_to_tokens(&self.attrs, tokens);
3938 self.bracket_token.surround(tokens, |tokens| {
3939 self.expr.to_tokens(tokens);
3940 self.semi_token.to_tokens(tokens);
3941 self.len.to_tokens(tokens);
3942 });
3943 }
3944 }
3945
3946 #[cfg(feature = "full")]
3947 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3948 impl ToTokens for ExprReturn {
3949 fn to_tokens(&self, tokens: &mut TokenStream) {
3950 print_expr_return(self, tokens, FixupContext::NONE);
3951 }
3952 }
3953
3954 #[cfg(feature = "full")]
3955 fn print_expr_return(e: &ExprReturn, tokens: &mut TokenStream, fixup: FixupContext) {
3956 outer_attrs_to_tokens(&e.attrs, tokens);
3957 e.return_token.to_tokens(tokens);
3958 if let Some(expr) = &e.expr {
3959 print_expr(
3960 expr,
3961 tokens,
3962 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
3963 );
3964 }
3965 }
3966
3967 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3968 impl ToTokens for ExprStruct {
3969 fn to_tokens(&self, tokens: &mut TokenStream) {
3970 outer_attrs_to_tokens(&self.attrs, tokens);
3971 path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3972 self.brace_token.surround(tokens, |tokens| {
3973 self.fields.to_tokens(tokens);
3974 if let Some(dot2_token) = &self.dot2_token {
3975 dot2_token.to_tokens(tokens);
3976 } else if self.rest.is_some() {
3977 crate::token::DotDotToken).to_tokens(tokens);
3978 }
3979 self.rest.to_tokens(tokens);
3980 });
3981 }
3982 }
3983
3984 #[cfg(feature = "full")]
3985 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3986 impl ToTokens for ExprTry {
3987 fn to_tokens(&self, tokens: &mut TokenStream) {
3988 print_expr_try(self, tokens, FixupContext::NONE);
3989 }
3990 }
3991
3992 #[cfg(feature = "full")]
3993 fn print_expr_try(e: &ExprTry, tokens: &mut TokenStream, fixup: FixupContext) {
3994 outer_attrs_to_tokens(&e.attrs, tokens);
3995 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.expr);
3996 print_subexpression(
3997 &e.expr,
3998 left_prec < Precedence::Unambiguous,
3999 tokens,
4000 left_fixup,
4001 );
4002 e.question_token.to_tokens(tokens);
4003 }
4004
4005 #[cfg(feature = "full")]
4006 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4007 impl ToTokens for ExprTryBlock {
4008 fn to_tokens(&self, tokens: &mut TokenStream) {
4009 outer_attrs_to_tokens(&self.attrs, tokens);
4010 self.try_token.to_tokens(tokens);
4011 self.block.to_tokens(tokens);
4012 }
4013 }
4014
4015 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4016 impl ToTokens for ExprTuple {
4017 fn to_tokens(&self, tokens: &mut TokenStream) {
4018 outer_attrs_to_tokens(&self.attrs, tokens);
4019 self.paren_token.surround(tokens, |tokens| {
4020 self.elems.to_tokens(tokens);
4021 if self.elems.len() == 1 && !self.elems.trailing_punct() {
4024 <crate::token::CommaToken![,]>::default().to_tokens(tokens);
4025 }
4026 });
4027 }
4028 }
4029
4030 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4031 impl ToTokens for ExprUnary {
4032 fn to_tokens(&self, tokens: &mut TokenStream) {
4033 print_expr_unary(self, tokens, FixupContext::NONE);
4034 }
4035 }
4036
4037 fn print_expr_unary(e: &ExprUnary, tokens: &mut TokenStream, fixup: FixupContext) {
4038 outer_attrs_to_tokens(&e.attrs, tokens);
4039 e.op.to_tokens(tokens);
4040 let (right_prec, right_fixup) = fixup.rightmost_subexpression(
4041 &e.expr,
4042 #[cfg(feature = "full")]
4043 Precedence::Prefix,
4044 );
4045 print_subexpression(
4046 &e.expr,
4047 right_prec < Precedence::Prefix,
4048 tokens,
4049 right_fixup,
4050 );
4051 }
4052
4053 #[cfg(feature = "full")]
4054 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4055 impl ToTokens for ExprUnsafe {
4056 fn to_tokens(&self, tokens: &mut TokenStream) {
4057 outer_attrs_to_tokens(&self.attrs, tokens);
4058 self.unsafe_token.to_tokens(tokens);
4059 self.block.brace_token.surround(tokens, |tokens| {
4060 inner_attrs_to_tokens(&self.attrs, tokens);
4061 tokens.append_all(&self.block.stmts);
4062 });
4063 }
4064 }
4065
4066 #[cfg(feature = "full")]
4067 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4068 impl ToTokens for ExprWhile {
4069 fn to_tokens(&self, tokens: &mut TokenStream) {
4070 outer_attrs_to_tokens(&self.attrs, tokens);
4071 self.label.to_tokens(tokens);
4072 self.while_token.to_tokens(tokens);
4073 print_expr(&self.cond, tokens, FixupContext::new_condition());
4074 self.body.brace_token.surround(tokens, |tokens| {
4075 inner_attrs_to_tokens(&self.attrs, tokens);
4076 tokens.append_all(&self.body.stmts);
4077 });
4078 }
4079 }
4080
4081 #[cfg(feature = "full")]
4082 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4083 impl ToTokens for ExprYield {
4084 fn to_tokens(&self, tokens: &mut TokenStream) {
4085 print_expr_yield(self, tokens, FixupContext::NONE);
4086 }
4087 }
4088
4089 #[cfg(feature = "full")]
4090 fn print_expr_yield(e: &ExprYield, tokens: &mut TokenStream, fixup: FixupContext) {
4091 outer_attrs_to_tokens(&e.attrs, tokens);
4092 e.yield_token.to_tokens(tokens);
4093 if let Some(expr) = &e.expr {
4094 print_expr(
4095 expr,
4096 tokens,
4097 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
4098 );
4099 }
4100 }
4101
4102 #[cfg(feature = "full")]
4103 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4104 impl ToTokens for Arm {
4105 fn to_tokens(&self, tokens: &mut TokenStream) {
4106 tokens.append_all(&self.attrs);
4107 self.pat.to_tokens(tokens);
4108 if let Some((if_token, guard)) = &self.guard {
4109 if_token.to_tokens(tokens);
4110 guard.to_tokens(tokens);
4111 }
4112 self.fat_arrow_token.to_tokens(tokens);
4113 print_expr(&self.body, tokens, FixupContext::new_match_arm());
4114 self.comma.to_tokens(tokens);
4115 }
4116 }
4117
4118 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4119 impl ToTokens for FieldValue {
4120 fn to_tokens(&self, tokens: &mut TokenStream) {
4121 outer_attrs_to_tokens(&self.attrs, tokens);
4122 self.member.to_tokens(tokens);
4123 if let Some(colon_token) = &self.colon_token {
4124 colon_token.to_tokens(tokens);
4125 self.expr.to_tokens(tokens);
4126 }
4127 }
4128 }
4129
4130 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4131 impl ToTokens for Index {
4132 fn to_tokens(&self, tokens: &mut TokenStream) {
4133 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
4134 lit.set_span(self.span);
4135 tokens.append(lit);
4136 }
4137 }
4138
4139 #[cfg(feature = "full")]
4140 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4141 impl ToTokens for Label {
4142 fn to_tokens(&self, tokens: &mut TokenStream) {
4143 self.name.to_tokens(tokens);
4144 self.colon_token.to_tokens(tokens);
4145 }
4146 }
4147
4148 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4149 impl ToTokens for Member {
4150 fn to_tokens(&self, tokens: &mut TokenStream) {
4151 match self {
4152 Member::Named(ident) => ident.to_tokens(tokens),
4153 Member::Unnamed(index) => index.to_tokens(tokens),
4154 }
4155 }
4156 }
4157
4158 #[cfg(feature = "full")]
4159 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4160 impl ToTokens for RangeLimits {
4161 fn to_tokens(&self, tokens: &mut TokenStream) {
4162 match self {
4163 RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
4164 RangeLimits::Closed(t) => t.to_tokens(tokens),
4165 }
4166 }
4167 }
4168
4169 #[cfg(feature = "full")]
4170 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4171 impl ToTokens for PointerMutability {
4172 fn to_tokens(&self, tokens: &mut TokenStream) {
4173 match self {
4174 PointerMutability::Const(const_token) => const_token.to_tokens(tokens),
4175 PointerMutability::Mut(mut_token) => mut_token.to_tokens(tokens),
4176 }
4177 }
4178 }
4179}