Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/syn/expr.rs
38271 views
1
// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3
use crate::attr::Attribute;
4
#[cfg(all(feature = "parsing", feature = "full"))]
5
use crate::error::Result;
6
#[cfg(feature = "parsing")]
7
use crate::ext::IdentExt as _;
8
#[cfg(feature = "full")]
9
use crate::generics::BoundLifetimes;
10
use crate::ident::Ident;
11
#[cfg(any(feature = "parsing", feature = "full"))]
12
use crate::lifetime::Lifetime;
13
use crate::lit::Lit;
14
use crate::mac::Macro;
15
use crate::op::{BinOp, UnOp};
16
#[cfg(feature = "parsing")]
17
use crate::parse::ParseStream;
18
#[cfg(feature = "full")]
19
use crate::pat::Pat;
20
use crate::path::{AngleBracketedGenericArguments, Path, QSelf};
21
use crate::punctuated::Punctuated;
22
#[cfg(feature = "full")]
23
use crate::stmt::Block;
24
use crate::token;
25
#[cfg(feature = "full")]
26
use crate::ty::ReturnType;
27
use crate::ty::Type;
28
use proc_macro2::{Span, TokenStream};
29
#[cfg(feature = "printing")]
30
use quote::IdentFragment;
31
#[cfg(feature = "printing")]
32
use std::fmt::{self, Display};
33
use std::hash::{Hash, Hasher};
34
#[cfg(all(feature = "parsing", feature = "full"))]
35
use std::mem;
36
37
ast_enum_of_structs! {
38
/// A Rust expression.
39
///
40
/// *This type is available only if Syn is built with the `"derive"` or `"full"`
41
/// feature, but most of the variants are not available unless "full" is enabled.*
42
///
43
/// # Syntax tree enums
44
///
45
/// This type is a syntax tree enum. In Syn this and other syntax tree enums
46
/// are designed to be traversed using the following rebinding idiom.
47
///
48
/// ```
49
/// # use syn::Expr;
50
/// #
51
/// # fn example(expr: Expr) {
52
/// # const IGNORE: &str = stringify! {
53
/// let expr: Expr = /* ... */;
54
/// # };
55
/// match expr {
56
/// Expr::MethodCall(expr) => {
57
/// /* ... */
58
/// }
59
/// Expr::Cast(expr) => {
60
/// /* ... */
61
/// }
62
/// Expr::If(expr) => {
63
/// /* ... */
64
/// }
65
///
66
/// /* ... */
67
/// # _ => {}
68
/// # }
69
/// # }
70
/// ```
71
///
72
/// We begin with a variable `expr` of type `Expr` that has no fields
73
/// (because it is an enum), and by matching on it and rebinding a variable
74
/// with the same name `expr` we effectively imbue our variable with all of
75
/// the data fields provided by the variant that it turned out to be. So for
76
/// example above if we ended up in the `MethodCall` case then we get to use
77
/// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
78
/// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
79
///
80
/// This approach avoids repeating the variant names twice on every line.
81
///
82
/// ```
83
/// # use syn::{Expr, ExprMethodCall};
84
/// #
85
/// # fn example(expr: Expr) {
86
/// // Repetitive; recommend not doing this.
87
/// match expr {
88
/// Expr::MethodCall(ExprMethodCall { method, args, .. }) => {
89
/// # }
90
/// # _ => {}
91
/// # }
92
/// # }
93
/// ```
94
///
95
/// In general, the name to which a syntax tree enum variant is bound should
96
/// be a suitable name for the complete syntax tree enum type.
97
///
98
/// ```
99
/// # use syn::{Expr, ExprField};
100
/// #
101
/// # fn example(discriminant: ExprField) {
102
/// // Binding is called `base` which is the name I would use if I were
103
/// // assigning `*discriminant.base` without an `if let`.
104
/// if let Expr::Tuple(base) = *discriminant.base {
105
/// # }
106
/// # }
107
/// ```
108
///
109
/// A sign that you may not be choosing the right variable names is if you
110
/// see names getting repeated in your code, like accessing
111
/// `receiver.receiver` or `pat.pat` or `cond.cond`.
112
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
113
#[non_exhaustive]
114
pub enum Expr {
115
/// A slice literal expression: `[a, b, c, d]`.
116
Array(ExprArray),
117
118
/// An assignment expression: `a = compute()`.
119
Assign(ExprAssign),
120
121
/// An async block: `async { ... }`.
122
Async(ExprAsync),
123
124
/// An await expression: `fut.await`.
125
Await(ExprAwait),
126
127
/// A binary operation: `a + b`, `a += b`.
128
Binary(ExprBinary),
129
130
/// A blocked scope: `{ ... }`.
131
Block(ExprBlock),
132
133
/// A `break`, with an optional label to break and an optional
134
/// expression.
135
Break(ExprBreak),
136
137
/// A function call expression: `invoke(a, b)`.
138
Call(ExprCall),
139
140
/// A cast expression: `foo as f64`.
141
Cast(ExprCast),
142
143
/// A closure expression: `|a, b| a + b`.
144
Closure(ExprClosure),
145
146
/// A const block: `const { ... }`.
147
Const(ExprConst),
148
149
/// A `continue`, with an optional label.
150
Continue(ExprContinue),
151
152
/// Access of a named struct field (`obj.k`) or unnamed tuple struct
153
/// field (`obj.0`).
154
Field(ExprField),
155
156
/// A for loop: `for pat in expr { ... }`.
157
ForLoop(ExprForLoop),
158
159
/// An expression contained within invisible delimiters.
160
///
161
/// This variant is important for faithfully representing the precedence
162
/// of expressions and is related to `None`-delimited spans in a
163
/// `TokenStream`.
164
Group(ExprGroup),
165
166
/// An `if` expression with an optional `else` block: `if expr { ... }
167
/// else { ... }`.
168
///
169
/// The `else` branch expression may only be an `If` or `Block`
170
/// expression, not any of the other types of expression.
171
If(ExprIf),
172
173
/// A square bracketed indexing expression: `vector[2]`.
174
Index(ExprIndex),
175
176
/// The inferred value of a const generic argument, denoted `_`.
177
Infer(ExprInfer),
178
179
/// A `let` guard: `let Some(x) = opt`.
180
Let(ExprLet),
181
182
/// A literal in place of an expression: `1`, `"foo"`.
183
Lit(ExprLit),
184
185
/// Conditionless loop: `loop { ... }`.
186
Loop(ExprLoop),
187
188
/// A macro invocation expression: `format!("{}", q)`.
189
Macro(ExprMacro),
190
191
/// A `match` expression: `match n { Some(n) => {}, None => {} }`.
192
Match(ExprMatch),
193
194
/// A method call expression: `x.foo::<T>(a, b)`.
195
MethodCall(ExprMethodCall),
196
197
/// A parenthesized expression: `(a + b)`.
198
Paren(ExprParen),
199
200
/// A path like `std::mem::replace` possibly containing generic
201
/// parameters and a qualified self-type.
202
///
203
/// A plain identifier like `x` is a path of length 1.
204
Path(ExprPath),
205
206
/// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
207
Range(ExprRange),
208
209
/// Address-of operation: `&raw const place` or `&raw mut place`.
210
RawAddr(ExprRawAddr),
211
212
/// A referencing operation: `&a` or `&mut a`.
213
Reference(ExprReference),
214
215
/// An array literal constructed from one repeated element: `[0u8; N]`.
216
Repeat(ExprRepeat),
217
218
/// A `return`, with an optional value to be returned.
219
Return(ExprReturn),
220
221
/// A struct literal expression: `Point { x: 1, y: 1 }`.
222
///
223
/// The `rest` provides the value of the remaining fields as in `S { a:
224
/// 1, b: 1, ..rest }`.
225
Struct(ExprStruct),
226
227
/// A try-expression: `expr?`.
228
Try(ExprTry),
229
230
/// A try block: `try { ... }`.
231
TryBlock(ExprTryBlock),
232
233
/// A tuple expression: `(a, b, c, d)`.
234
Tuple(ExprTuple),
235
236
/// A unary operation: `!x`, `*x`.
237
Unary(ExprUnary),
238
239
/// An unsafe block: `unsafe { ... }`.
240
Unsafe(ExprUnsafe),
241
242
/// Tokens in expression position not interpreted by Syn.
243
Verbatim(TokenStream),
244
245
/// A while loop: `while expr { ... }`.
246
While(ExprWhile),
247
248
/// A yield expression: `yield expr`.
249
Yield(ExprYield),
250
251
// For testing exhaustiveness in downstream code, use the following idiom:
252
//
253
// match expr {
254
// #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
255
//
256
// Expr::Array(expr) => {...}
257
// Expr::Assign(expr) => {...}
258
// ...
259
// Expr::Yield(expr) => {...}
260
//
261
// _ => { /* some sane fallback */ }
262
// }
263
//
264
// This way we fail your tests but don't break your library when adding
265
// a variant. You will be notified by a test failure when a variant is
266
// added, so that you can add code to handle it, but your library will
267
// continue to compile and work for downstream users in the interim.
268
}
269
}
270
271
ast_struct! {
272
/// A slice literal expression: `[a, b, c, d]`.
273
#[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
ast_struct! {
282
/// An assignment expression: `a = compute()`.
283
#[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
ast_struct! {
293
/// An async block: `async { ... }`.
294
#[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
ast_struct! {
304
/// An await expression: `fut.await`.
305
#[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
ast_struct! {
315
/// A binary operation: `a + b`, `a += b`.
316
#[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
ast_struct! {
326
/// A blocked scope: `{ ... }`.
327
#[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
ast_struct! {
336
/// A `break`, with an optional label to break and an optional
337
/// expression.
338
#[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
ast_struct! {
348
/// A function call expression: `invoke(a, b)`.
349
#[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
ast_struct! {
359
/// A cast expression: `foo as f64`.
360
#[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
ast_struct! {
370
/// A closure expression: `|a, b| a + b`.
371
#[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
ast_struct! {
388
/// A const block: `const { ... }`.
389
#[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
ast_struct! {
398
/// A `continue`, with an optional label.
399
#[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
ast_struct! {
408
/// Access of a named struct field (`obj.k`) or unnamed tuple struct
409
/// field (`obj.0`).
410
#[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
ast_struct! {
420
/// A for loop: `for pat in expr { ... }`.
421
#[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
ast_struct! {
434
/// An expression contained within invisible delimiters.
435
///
436
/// This variant is important for faithfully representing the precedence
437
/// of expressions and is related to `None`-delimited spans in a
438
/// `TokenStream`.
439
#[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
ast_struct! {
448
/// An `if` expression with an optional `else` block: `if expr { ... }
449
/// else { ... }`.
450
///
451
/// The `else` branch expression may only be an `If` or `Block`
452
/// expression, not any of the other types of expression.
453
#[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
ast_struct! {
464
/// A square bracketed indexing expression: `vector[2]`.
465
#[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
ast_struct! {
475
/// The inferred value of a const generic argument, denoted `_`.
476
#[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
ast_struct! {
484
/// A `let` guard: `let Some(x) = opt`.
485
#[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
ast_struct! {
496
/// A literal in place of an expression: `1`, `"foo"`.
497
#[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
ast_struct! {
505
/// Conditionless loop: `loop { ... }`.
506
#[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
ast_struct! {
516
/// A macro invocation expression: `format!("{}", q)`.
517
#[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
ast_struct! {
525
/// A `match` expression: `match n { Some(n) => {}, None => {} }`.
526
#[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
ast_struct! {
537
/// A method call expression: `x.foo::<T>(a, b)`.
538
#[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
ast_struct! {
551
/// A parenthesized expression: `(a + b)`.
552
#[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
ast_struct! {
561
/// A path like `std::mem::replace` possibly containing generic
562
/// parameters and a qualified self-type.
563
///
564
/// A plain identifier like `x` is a path of length 1.
565
#[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
ast_struct! {
574
/// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
575
#[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
ast_struct! {
585
/// Address-of operation: `&raw const place` or `&raw mut place`.
586
#[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
ast_struct! {
597
/// A referencing operation: `&a` or `&mut a`.
598
#[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
ast_struct! {
608
/// An array literal constructed from one repeated element: `[0u8; N]`.
609
#[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
ast_struct! {
620
/// A `return`, with an optional value to be returned.
621
#[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
ast_struct! {
630
/// A struct literal expression: `Point { x: 1, y: 1 }`.
631
///
632
/// The `rest` provides the value of the remaining fields as in `S { a:
633
/// 1, b: 1, ..rest }`.
634
#[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
ast_struct! {
647
/// A try-expression: `expr?`.
648
#[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
ast_struct! {
657
/// A try block: `try { ... }`.
658
#[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
ast_struct! {
667
/// A tuple expression: `(a, b, c, d)`.
668
#[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
ast_struct! {
677
/// A unary operation: `!x`, `*x`.
678
#[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
ast_struct! {
687
/// An unsafe block: `unsafe { ... }`.
688
#[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
ast_struct! {
697
/// A while loop: `while expr { ... }`.
698
#[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
ast_struct! {
709
/// A yield expression: `yield expr`.
710
#[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
718
impl Expr {
719
/// An unspecified invalid expression.
720
///
721
/// ```
722
/// use quote::ToTokens;
723
/// use std::mem;
724
/// use syn::{parse_quote, Expr};
725
///
726
/// fn unparenthesize(e: &mut Expr) {
727
/// while let Expr::Paren(paren) = e {
728
/// *e = mem::replace(&mut *paren.expr, Expr::PLACEHOLDER);
729
/// }
730
/// }
731
///
732
/// fn main() {
733
/// let mut e: Expr = parse_quote! { ((1 + 1)) };
734
/// unparenthesize(&mut e);
735
/// assert_eq!("1 + 1", e.to_token_stream().to_string());
736
/// }
737
/// ```
738
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
/// An alternative to the primary `Expr::parse` parser (from the [`Parse`]
748
/// trait) for ambiguous syntactic positions in which a trailing brace
749
/// should not be taken as part of the expression.
750
///
751
/// [`Parse`]: crate::parse::Parse
752
///
753
/// Rust grammar has an ambiguity where braces sometimes turn a path
754
/// expression into a struct initialization and sometimes do not. In the
755
/// following code, the expression `S {}` is one expression. Presumably
756
/// there is an empty struct `struct S {}` defined somewhere which it is
757
/// instantiating.
758
///
759
/// ```
760
/// # struct S;
761
/// # impl std::ops::Deref for S {
762
/// # type Target = bool;
763
/// # fn deref(&self) -> &Self::Target {
764
/// # &true
765
/// # }
766
/// # }
767
/// let _ = *S {};
768
///
769
/// // parsed by rustc as: `*(S {})`
770
/// ```
771
///
772
/// We would want to parse the above using `Expr::parse` after the `=`
773
/// token.
774
///
775
/// But in the following, `S {}` is *not* a struct init expression.
776
///
777
/// ```
778
/// # const S: &bool = &true;
779
/// if *S {} {}
780
///
781
/// // parsed by rustc as:
782
/// //
783
/// // if (*S) {
784
/// // /* empty block */
785
/// // }
786
/// // {
787
/// // /* another empty block */
788
/// // }
789
/// ```
790
///
791
/// For that reason we would want to parse if-conditions using
792
/// `Expr::parse_without_eager_brace` after the `if` token. Same for similar
793
/// syntactic positions such as the condition expr after a `while` token or
794
/// the expr at the top of a `match`.
795
///
796
/// The Rust grammar's choices around which way this ambiguity is resolved
797
/// at various syntactic positions is fairly arbitrary. Really either parse
798
/// behavior could work in most positions, and language designers just
799
/// decide each case based on which is more likely to be what the programmer
800
/// had in mind most of the time.
801
///
802
/// ```
803
/// # struct S;
804
/// # fn doc() -> S {
805
/// if return S {} {}
806
/// # unreachable!()
807
/// # }
808
///
809
/// // parsed by rustc as:
810
/// //
811
/// // if (return (S {})) {
812
/// // }
813
/// //
814
/// // but could equally well have been this other arbitrary choice:
815
/// //
816
/// // if (return S) {
817
/// // }
818
/// // {}
819
/// ```
820
///
821
/// Note the grammar ambiguity on trailing braces is distinct from
822
/// precedence and is not captured by assigning a precedence level to the
823
/// braced struct init expr in relation to other operators. This can be
824
/// illustrated by `return 0..S {}` vs `match 0..S {}`. The former parses as
825
/// `return (0..(S {}))` implying tighter precedence for struct init than
826
/// `..`, while the latter parses as `match (0..S) {}` implying tighter
827
/// precedence for `..` than struct init, a contradiction.
828
#[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
/// An alternative to the primary `Expr::parse` parser (from the [`Parse`]
835
/// trait) for syntactic positions in which expression boundaries are placed
836
/// more eagerly than done by the typical expression grammar. This includes
837
/// expressions at the head of a statement or in the right-hand side of a
838
/// `match` arm.
839
///
840
/// [`Parse`]: crate::parse::Parse
841
///
842
/// Compare the following cases:
843
///
844
/// 1.
845
/// ```
846
/// # let result = ();
847
/// # let guard = false;
848
/// # let cond = true;
849
/// # let f = true;
850
/// # let g = f;
851
/// #
852
/// let _ = match result {
853
/// () if guard => if cond { f } else { g }
854
/// () => false,
855
/// };
856
/// ```
857
///
858
/// 2.
859
/// ```
860
/// # let cond = true;
861
/// # let f = ();
862
/// # let g = f;
863
/// #
864
/// let _ = || {
865
/// if cond { f } else { g }
866
/// ()
867
/// };
868
/// ```
869
///
870
/// 3.
871
/// ```
872
/// # let cond = true;
873
/// # let f = || ();
874
/// # let g = f;
875
/// #
876
/// let _ = [if cond { f } else { g } ()];
877
/// ```
878
///
879
/// The same sequence of tokens `if cond { f } else { g } ()` appears in
880
/// expression position 3 times. The first two syntactic positions use eager
881
/// placement of expression boundaries, and parse as `Expr::If`, with the
882
/// adjacent `()` becoming `Pat::Tuple` or `Expr::Tuple`. In contrast, the
883
/// third case uses standard expression boundaries and parses as
884
/// `Expr::Call`.
885
///
886
/// As with [`parse_without_eager_brace`], this ambiguity in the Rust
887
/// grammar is independent of precedence.
888
///
889
/// [`parse_without_eager_brace`]: Self::parse_without_eager_brace
890
#[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
/// Returns whether the next token in the parse stream is one that might
897
/// possibly form the beginning of an expr.
898
///
899
/// This classification is a load-bearing part of the grammar of some Rust
900
/// expressions, notably `return` and `break`. For example `return < …` will
901
/// never parse `<` as a binary operator regardless of what comes after,
902
/// because `<` is a legal starting token for an expression and so it's
903
/// required to be continued as a return value, such as `return <Struct as
904
/// Trait>::CONST`. Meanwhile `return > …` treats the `>` as a binary
905
/// operator because it cannot be a starting token for any Rust expression.
906
#[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(Token![as]) // value name or keyword
910
|| input.peek(token::Paren) // tuple
911
|| input.peek(token::Bracket) // array
912
|| input.peek(token::Brace) // block
913
|| input.peek(Lit) // literal
914
|| input.peek(Token![!]) && !input.peek(Token![!=]) // operator not
915
|| input.peek(Token![-]) && !input.peek(Token![-=]) && !input.peek(Token![->]) // unary minus
916
|| input.peek(Token![*]) && !input.peek(Token![*=]) // dereference
917
|| input.peek(Token![|]) && !input.peek(Token![|=]) // closure
918
|| input.peek(Token![&]) && !input.peek(Token![&=]) // reference
919
|| input.peek(Token![..]) // range
920
|| input.peek(Token![<]) && !input.peek(Token![<=]) && !input.peek(Token![<<=]) // associated path
921
|| input.peek(Token![::]) // absolute path
922
|| input.peek(Lifetime) // labeled loop
923
|| input.peek(Token![#]) // expression attributes
924
}
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
ast_enum! {
974
/// A struct or tuple struct field accessed in a struct literal or field
975
/// expression.
976
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
977
pub enum Member {
978
/// A named field like `self.x`.
979
Named(Ident),
980
/// An unnamed field like `self.0`.
981
Unnamed(Index),
982
}
983
}
984
985
impl From<Ident> for Member {
986
fn from(ident: Ident) -> Member {
987
Member::Named(ident)
988
}
989
}
990
991
impl From<Index> for Member {
992
fn from(index: Index) -> Member {
993
Member::Unnamed(index)
994
}
995
}
996
997
impl From<usize> for Member {
998
fn from(index: usize) -> Member {
999
Member::Unnamed(Index::from(index))
1000
}
1001
}
1002
1003
impl Eq for Member {}
1004
1005
impl 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
1015
impl 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")]
1025
impl 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"))]
1042
impl 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
ast_struct! {
1052
/// The index of an unnamed tuple struct field.
1053
#[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
1060
impl From<usize> for Index {
1061
fn from(index: usize) -> Index {
1062
assert!(index < u32::MAX as usize);
1063
Index {
1064
index: index as u32,
1065
span: Span::call_site(),
1066
}
1067
}
1068
}
1069
1070
impl Eq for Index {}
1071
1072
impl PartialEq for Index {
1073
fn eq(&self, other: &Self) -> bool {
1074
self.index == other.index
1075
}
1076
}
1077
1078
impl Hash for Index {
1079
fn hash<H: Hasher>(&self, state: &mut H) {
1080
self.index.hash(state);
1081
}
1082
}
1083
1084
#[cfg(feature = "printing")]
1085
impl 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
ast_struct! {
1096
/// A field-value pair in a struct literal.
1097
#[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
/// The colon in `Struct { x: x }`. If written in shorthand like
1103
/// `Struct { x }`, there is no colon.
1104
pub colon_token: Option<Token![:]>,
1105
1106
pub expr: Expr,
1107
}
1108
}
1109
1110
#[cfg(feature = "full")]
1111
ast_struct! {
1112
/// A lifetime labeling a `for`, `while`, or `loop`.
1113
#[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
ast_struct! {
1122
/// One arm of a `match` expression: `0..=10 => { return true; }`.
1123
///
1124
/// As in:
1125
///
1126
/// ```
1127
/// # fn f() -> bool {
1128
/// # let n = 0;
1129
/// match n {
1130
/// 0..=10 => {
1131
/// return true;
1132
/// }
1133
/// // ...
1134
/// # _ => {}
1135
/// }
1136
/// # false
1137
/// # }
1138
/// ```
1139
#[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
ast_enum! {
1152
/// Limit types of a range, inclusive or exclusive.
1153
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1154
pub enum RangeLimits {
1155
/// Inclusive at the beginning, exclusive at the end.
1156
HalfOpen(Token![..]),
1157
/// Inclusive at the beginning and end.
1158
Closed(Token![..=]),
1159
}
1160
}
1161
1162
#[cfg(feature = "full")]
1163
ast_enum! {
1164
/// Mutability of a raw pointer (`*const T`, `*mut T`), in which non-mutable
1165
/// isn't the implicit default.
1166
#[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")]
1174
pub(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
#[cfg(feature = "full")]
1218
use proc_macro2::{Span, TokenStream};
1219
use std::mem;
1220
1221
// When we're parsing expressions which occur before blocks, like in an if
1222
// statement's condition, we cannot parse a struct literal.
1223
//
1224
// Struct literals are ambiguous in certain positions
1225
// https://github.com/rust-lang/rfcs/pull/92
1226
#[cfg(feature = "full")]
1227
pub(super) struct AllowStruct(pub bool);
1228
1229
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1230
impl Parse for Expr {
1231
fn parse(input: ParseStream) -> Result<Self> {
1232
ambiguous_expr(
1233
input,
1234
#[cfg(feature = "full")]
1235
AllowStruct(true),
1236
)
1237
}
1238
}
1239
1240
#[cfg(feature = "full")]
1241
pub(super) fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
1242
let mut attrs = input.call(expr_attrs)?;
1243
let mut expr = if input.peek(token::Group) {
1244
let allow_struct = AllowStruct(true);
1245
let atom = expr_group(input, allow_struct)?;
1246
if continue_parsing_early(&atom) {
1247
trailer_helper(input, atom)?
1248
} else {
1249
atom
1250
}
1251
} else if input.peek(Token![if]) {
1252
Expr::If(input.parse()?)
1253
} else if input.peek(Token![while]) {
1254
Expr::While(input.parse()?)
1255
} else if input.peek(Token![for])
1256
&& !generics::parsing::choose_generics_over_qpath_after_keyword(input)
1257
{
1258
Expr::ForLoop(input.parse()?)
1259
} else if input.peek(Token![loop]) {
1260
Expr::Loop(input.parse()?)
1261
} else if input.peek(Token![match]) {
1262
Expr::Match(input.parse()?)
1263
} else if input.peek(Token![try]) && input.peek2(token::Brace) {
1264
Expr::TryBlock(input.parse()?)
1265
} else if input.peek(Token![unsafe]) {
1266
Expr::Unsafe(input.parse()?)
1267
} else if input.peek(Token![const]) && input.peek2(token::Brace) {
1268
Expr::Const(input.parse()?)
1269
} else if input.peek(token::Brace) {
1270
Expr::Block(input.parse()?)
1271
} else if input.peek(Lifetime) {
1272
atom_labeled(input)?
1273
} else {
1274
let allow_struct = AllowStruct(true);
1275
unary_expr(input, allow_struct)?
1276
};
1277
1278
if continue_parsing_early(&expr) {
1279
attrs.extend(expr.replace_attrs(Vec::new()));
1280
expr.replace_attrs(attrs);
1281
1282
let allow_struct = AllowStruct(true);
1283
return parse_expr(input, expr, allow_struct, Precedence::MIN);
1284
}
1285
1286
if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) {
1287
expr = trailer_helper(input, expr)?;
1288
1289
attrs.extend(expr.replace_attrs(Vec::new()));
1290
expr.replace_attrs(attrs);
1291
1292
let allow_struct = AllowStruct(true);
1293
return parse_expr(input, expr, allow_struct, Precedence::MIN);
1294
}
1295
1296
attrs.extend(expr.replace_attrs(Vec::new()));
1297
expr.replace_attrs(attrs);
1298
Ok(expr)
1299
}
1300
1301
#[cfg(feature = "full")]
1302
impl Copy for AllowStruct {}
1303
1304
#[cfg(feature = "full")]
1305
impl Clone for AllowStruct {
1306
fn clone(&self) -> Self {
1307
*self
1308
}
1309
}
1310
1311
#[cfg(feature = "full")]
1312
fn parse_expr(
1313
input: ParseStream,
1314
mut lhs: Expr,
1315
allow_struct: AllowStruct,
1316
base: Precedence,
1317
) -> Result<Expr> {
1318
loop {
1319
let ahead = input.fork();
1320
if let Expr::Range(_) = lhs {
1321
// A range cannot be the left-hand side of another binary operator.
1322
break;
1323
} else if let Ok(op) = ahead.parse::<BinOp>() {
1324
let precedence = Precedence::of_binop(&op);
1325
if precedence < base {
1326
break;
1327
}
1328
if precedence == Precedence::Assign {
1329
if let Expr::Range(_) = lhs {
1330
break;
1331
}
1332
}
1333
if precedence == Precedence::Compare {
1334
if let Expr::Binary(lhs) = &lhs {
1335
if Precedence::of_binop(&lhs.op) == Precedence::Compare {
1336
return Err(input.error("comparison operators cannot be chained"));
1337
}
1338
}
1339
}
1340
input.advance_to(&ahead);
1341
let right = parse_binop_rhs(input, allow_struct, precedence)?;
1342
lhs = Expr::Binary(ExprBinary {
1343
attrs: Vec::new(),
1344
left: Box::new(lhs),
1345
op,
1346
right,
1347
});
1348
} else if Precedence::Assign >= base
1349
&& input.peek(Token![=])
1350
&& !input.peek(Token![=>])
1351
&& match lhs {
1352
Expr::Range(_) => false,
1353
_ => true,
1354
}
1355
{
1356
let eq_token: Token![=] = input.parse()?;
1357
let right = parse_binop_rhs(input, allow_struct, Precedence::Assign)?;
1358
lhs = Expr::Assign(ExprAssign {
1359
attrs: Vec::new(),
1360
left: Box::new(lhs),
1361
eq_token,
1362
right,
1363
});
1364
} else if Precedence::Range >= base && input.peek(Token![..]) {
1365
let limits: RangeLimits = input.parse()?;
1366
let end = parse_range_end(input, &limits, allow_struct)?;
1367
lhs = Expr::Range(ExprRange {
1368
attrs: Vec::new(),
1369
start: Some(Box::new(lhs)),
1370
limits,
1371
end,
1372
});
1373
} else if Precedence::Cast >= base && input.peek(Token![as]) {
1374
let as_token: Token![as] = input.parse()?;
1375
let allow_plus = false;
1376
let allow_group_generic = false;
1377
let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1378
check_cast(input)?;
1379
lhs = Expr::Cast(ExprCast {
1380
attrs: Vec::new(),
1381
expr: Box::new(lhs),
1382
as_token,
1383
ty: Box::new(ty),
1384
});
1385
} else {
1386
break;
1387
}
1388
}
1389
Ok(lhs)
1390
}
1391
1392
#[cfg(not(feature = "full"))]
1393
fn parse_expr(input: ParseStream, mut lhs: Expr, base: Precedence) -> Result<Expr> {
1394
loop {
1395
let ahead = input.fork();
1396
if let Ok(op) = ahead.parse::<BinOp>() {
1397
let precedence = Precedence::of_binop(&op);
1398
if precedence < base {
1399
break;
1400
}
1401
if precedence == Precedence::Compare {
1402
if let Expr::Binary(lhs) = &lhs {
1403
if Precedence::of_binop(&lhs.op) == Precedence::Compare {
1404
return Err(input.error("comparison operators cannot be chained"));
1405
}
1406
}
1407
}
1408
input.advance_to(&ahead);
1409
let right = parse_binop_rhs(input, precedence)?;
1410
lhs = Expr::Binary(ExprBinary {
1411
attrs: Vec::new(),
1412
left: Box::new(lhs),
1413
op,
1414
right,
1415
});
1416
} else if Precedence::Cast >= base && input.peek(Token![as]) {
1417
let as_token: Token![as] = input.parse()?;
1418
let allow_plus = false;
1419
let allow_group_generic = false;
1420
let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1421
check_cast(input)?;
1422
lhs = Expr::Cast(ExprCast {
1423
attrs: Vec::new(),
1424
expr: Box::new(lhs),
1425
as_token,
1426
ty: Box::new(ty),
1427
});
1428
} else {
1429
break;
1430
}
1431
}
1432
Ok(lhs)
1433
}
1434
1435
fn parse_binop_rhs(
1436
input: ParseStream,
1437
#[cfg(feature = "full")] allow_struct: AllowStruct,
1438
precedence: Precedence,
1439
) -> Result<Box<Expr>> {
1440
let mut rhs = unary_expr(
1441
input,
1442
#[cfg(feature = "full")]
1443
allow_struct,
1444
)?;
1445
loop {
1446
let next = peek_precedence(input);
1447
if next > precedence || next == precedence && precedence == Precedence::Assign {
1448
let cursor = input.cursor();
1449
rhs = parse_expr(
1450
input,
1451
rhs,
1452
#[cfg(feature = "full")]
1453
allow_struct,
1454
next,
1455
)?;
1456
if cursor == input.cursor() {
1457
// Bespoke grammar restrictions separate from precedence can
1458
// cause parsing to not advance, such as `..a` being
1459
// disallowed in the left-hand side of binary operators,
1460
// even ones that have lower precedence than `..`.
1461
break;
1462
}
1463
} else {
1464
break;
1465
}
1466
}
1467
Ok(Box::new(rhs))
1468
}
1469
1470
fn peek_precedence(input: ParseStream) -> Precedence {
1471
if let Ok(op) = input.fork().parse() {
1472
Precedence::of_binop(&op)
1473
} else if input.peek(Token![=]) && !input.peek(Token![=>]) {
1474
Precedence::Assign
1475
} else if input.peek(Token![..]) {
1476
Precedence::Range
1477
} else if input.peek(Token![as]) {
1478
Precedence::Cast
1479
} else {
1480
Precedence::MIN
1481
}
1482
}
1483
1484
// Parse an arbitrary expression.
1485
pub(super) fn ambiguous_expr(
1486
input: ParseStream,
1487
#[cfg(feature = "full")] allow_struct: AllowStruct,
1488
) -> Result<Expr> {
1489
let lhs = unary_expr(
1490
input,
1491
#[cfg(feature = "full")]
1492
allow_struct,
1493
)?;
1494
parse_expr(
1495
input,
1496
lhs,
1497
#[cfg(feature = "full")]
1498
allow_struct,
1499
Precedence::MIN,
1500
)
1501
}
1502
1503
#[cfg(feature = "full")]
1504
fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> {
1505
let mut attrs = Vec::new();
1506
while !input.peek(token::Group) && input.peek(Token![#]) {
1507
attrs.push(input.call(attr::parsing::single_parse_outer)?);
1508
}
1509
Ok(attrs)
1510
}
1511
1512
// <UnOp> <trailer>
1513
// & <trailer>
1514
// &mut <trailer>
1515
// box <trailer>
1516
#[cfg(feature = "full")]
1517
fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1518
let begin = input.fork();
1519
let attrs = input.call(expr_attrs)?;
1520
if input.peek(token::Group) {
1521
return trailer_expr(begin, attrs, input, allow_struct);
1522
}
1523
1524
if input.peek(Token![&]) {
1525
let and_token: Token![&] = input.parse()?;
1526
let raw: Option<Token![raw]> = if input.peek(Token![raw])
1527
&& (input.peek2(Token![mut]) || input.peek2(Token![const]))
1528
{
1529
Some(input.parse()?)
1530
} else {
1531
None
1532
};
1533
let mutability: Option<Token![mut]> = input.parse()?;
1534
let const_token: Option<Token![const]> = if raw.is_some() && mutability.is_none() {
1535
Some(input.parse()?)
1536
} else {
1537
None
1538
};
1539
let expr = Box::new(unary_expr(input, allow_struct)?);
1540
if let Some(raw) = raw {
1541
Ok(Expr::RawAddr(ExprRawAddr {
1542
attrs,
1543
and_token,
1544
raw,
1545
mutability: match mutability {
1546
Some(mut_token) => PointerMutability::Mut(mut_token),
1547
None => PointerMutability::Const(const_token.unwrap()),
1548
},
1549
expr,
1550
}))
1551
} else {
1552
Ok(Expr::Reference(ExprReference {
1553
attrs,
1554
and_token,
1555
mutability,
1556
expr,
1557
}))
1558
}
1559
} else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1560
expr_unary(input, attrs, allow_struct).map(Expr::Unary)
1561
} else {
1562
trailer_expr(begin, attrs, input, allow_struct)
1563
}
1564
}
1565
1566
#[cfg(not(feature = "full"))]
1567
fn unary_expr(input: ParseStream) -> Result<Expr> {
1568
if input.peek(Token![&]) {
1569
Ok(Expr::Reference(ExprReference {
1570
attrs: Vec::new(),
1571
and_token: input.parse()?,
1572
mutability: input.parse()?,
1573
expr: Box::new(unary_expr(input)?),
1574
}))
1575
} else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1576
Ok(Expr::Unary(ExprUnary {
1577
attrs: Vec::new(),
1578
op: input.parse()?,
1579
expr: Box::new(unary_expr(input)?),
1580
}))
1581
} else {
1582
trailer_expr(input)
1583
}
1584
}
1585
1586
// <atom> (..<args>) ...
1587
// <atom> . <ident> (..<args>) ...
1588
// <atom> . <ident> ...
1589
// <atom> . <lit> ...
1590
// <atom> [ <expr> ] ...
1591
// <atom> ? ...
1592
#[cfg(feature = "full")]
1593
fn trailer_expr(
1594
begin: ParseBuffer,
1595
mut attrs: Vec<Attribute>,
1596
input: ParseStream,
1597
allow_struct: AllowStruct,
1598
) -> Result<Expr> {
1599
let atom = atom_expr(input, allow_struct)?;
1600
let mut e = trailer_helper(input, atom)?;
1601
1602
if let Expr::Verbatim(tokens) = &mut e {
1603
*tokens = verbatim::between(&begin, input);
1604
} else if !attrs.is_empty() {
1605
if let Expr::Range(range) = e {
1606
let spans: &[Span] = match &range.limits {
1607
RangeLimits::HalfOpen(limits) => &limits.spans,
1608
RangeLimits::Closed(limits) => &limits.spans,
1609
};
1610
return Err(crate::error::new2(
1611
spans[0],
1612
*spans.last().unwrap(),
1613
"attributes are not allowed on range expressions starting with `..`",
1614
));
1615
}
1616
let inner_attrs = e.replace_attrs(Vec::new());
1617
attrs.extend(inner_attrs);
1618
e.replace_attrs(attrs);
1619
}
1620
1621
Ok(e)
1622
}
1623
1624
#[cfg(feature = "full")]
1625
fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
1626
loop {
1627
if input.peek(token::Paren) {
1628
let content;
1629
e = Expr::Call(ExprCall {
1630
attrs: Vec::new(),
1631
func: Box::new(e),
1632
paren_token: parenthesized!(content in input),
1633
args: content.parse_terminated(Expr::parse, Token![,])?,
1634
});
1635
} else if input.peek(Token![.])
1636
&& !input.peek(Token![..])
1637
&& match e {
1638
Expr::Range(_) => false,
1639
_ => true,
1640
}
1641
{
1642
let mut dot_token: Token![.] = input.parse()?;
1643
1644
let float_token: Option<LitFloat> = input.parse()?;
1645
if let Some(float_token) = float_token {
1646
if multi_index(&mut e, &mut dot_token, float_token)? {
1647
continue;
1648
}
1649
}
1650
1651
let await_token: Option<Token![await]> = input.parse()?;
1652
if let Some(await_token) = await_token {
1653
e = Expr::Await(ExprAwait {
1654
attrs: Vec::new(),
1655
base: Box::new(e),
1656
dot_token,
1657
await_token,
1658
});
1659
continue;
1660
}
1661
1662
let member: Member = input.parse()?;
1663
let turbofish = if member.is_named() && input.peek(Token![::]) {
1664
Some(AngleBracketedGenericArguments::parse_turbofish(input)?)
1665
} else {
1666
None
1667
};
1668
1669
if turbofish.is_some() || input.peek(token::Paren) {
1670
if let Member::Named(method) = member {
1671
let content;
1672
e = Expr::MethodCall(ExprMethodCall {
1673
attrs: Vec::new(),
1674
receiver: Box::new(e),
1675
dot_token,
1676
method,
1677
turbofish,
1678
paren_token: parenthesized!(content in input),
1679
args: content.parse_terminated(Expr::parse, Token![,])?,
1680
});
1681
continue;
1682
}
1683
}
1684
1685
e = Expr::Field(ExprField {
1686
attrs: Vec::new(),
1687
base: Box::new(e),
1688
dot_token,
1689
member,
1690
});
1691
} else if input.peek(token::Bracket) {
1692
let content;
1693
e = Expr::Index(ExprIndex {
1694
attrs: Vec::new(),
1695
expr: Box::new(e),
1696
bracket_token: bracketed!(content in input),
1697
index: content.parse()?,
1698
});
1699
} else if input.peek(Token![?])
1700
&& match e {
1701
Expr::Range(_) => false,
1702
_ => true,
1703
}
1704
{
1705
e = Expr::Try(ExprTry {
1706
attrs: Vec::new(),
1707
expr: Box::new(e),
1708
question_token: input.parse()?,
1709
});
1710
} else {
1711
break;
1712
}
1713
}
1714
Ok(e)
1715
}
1716
1717
#[cfg(not(feature = "full"))]
1718
fn trailer_expr(input: ParseStream) -> Result<Expr> {
1719
let mut e = atom_expr(input)?;
1720
1721
loop {
1722
if input.peek(token::Paren) {
1723
let content;
1724
e = Expr::Call(ExprCall {
1725
attrs: Vec::new(),
1726
func: Box::new(e),
1727
paren_token: parenthesized!(content in input),
1728
args: content.parse_terminated(Expr::parse, Token![,])?,
1729
});
1730
} else if input.peek(Token![.])
1731
&& !input.peek(Token![..])
1732
&& !input.peek2(Token![await])
1733
{
1734
let mut dot_token: Token![.] = input.parse()?;
1735
1736
let float_token: Option<LitFloat> = input.parse()?;
1737
if let Some(float_token) = float_token {
1738
if multi_index(&mut e, &mut dot_token, float_token)? {
1739
continue;
1740
}
1741
}
1742
1743
let member: Member = input.parse()?;
1744
let turbofish = if member.is_named() && input.peek(Token![::]) {
1745
let colon2_token: Token![::] = input.parse()?;
1746
let turbofish =
1747
AngleBracketedGenericArguments::do_parse(Some(colon2_token), input)?;
1748
Some(turbofish)
1749
} else {
1750
None
1751
};
1752
1753
if turbofish.is_some() || input.peek(token::Paren) {
1754
if let Member::Named(method) = member {
1755
let content;
1756
e = Expr::MethodCall(ExprMethodCall {
1757
attrs: Vec::new(),
1758
receiver: Box::new(e),
1759
dot_token,
1760
method,
1761
turbofish,
1762
paren_token: parenthesized!(content in input),
1763
args: content.parse_terminated(Expr::parse, Token![,])?,
1764
});
1765
continue;
1766
}
1767
}
1768
1769
e = Expr::Field(ExprField {
1770
attrs: Vec::new(),
1771
base: Box::new(e),
1772
dot_token,
1773
member,
1774
});
1775
} else if input.peek(token::Bracket) {
1776
let content;
1777
e = Expr::Index(ExprIndex {
1778
attrs: Vec::new(),
1779
expr: Box::new(e),
1780
bracket_token: bracketed!(content in input),
1781
index: content.parse()?,
1782
});
1783
} else {
1784
break;
1785
}
1786
}
1787
1788
Ok(e)
1789
}
1790
1791
// Parse all atomic expressions which don't have to worry about precedence
1792
// interactions, as they are fully contained.
1793
#[cfg(feature = "full")]
1794
fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1795
if input.peek(token::Group) {
1796
expr_group(input, allow_struct)
1797
} else if input.peek(Lit) {
1798
input.parse().map(Expr::Lit)
1799
} else if input.peek(Token![async])
1800
&& (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1801
{
1802
input.parse().map(Expr::Async)
1803
} else if input.peek(Token![try]) && input.peek2(token::Brace) {
1804
input.parse().map(Expr::TryBlock)
1805
} else if input.peek(Token![|])
1806
|| input.peek(Token![move])
1807
|| input.peek(Token![for])
1808
&& generics::parsing::choose_generics_over_qpath_after_keyword(input)
1809
|| input.peek(Token![const]) && !input.peek2(token::Brace)
1810
|| input.peek(Token![static])
1811
|| input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1812
{
1813
expr_closure(input, allow_struct).map(Expr::Closure)
1814
} else if token::parsing::peek_keyword(input.cursor(), "builtin") && input.peek2(Token![#])
1815
{
1816
expr_builtin(input)
1817
} else if input.peek(Ident)
1818
|| input.peek(Token![::])
1819
|| input.peek(Token![<])
1820
|| input.peek(Token![self])
1821
|| input.peek(Token![Self])
1822
|| input.peek(Token![super])
1823
|| input.peek(Token![crate])
1824
|| input.peek(Token![try]) && (input.peek2(Token![!]) || input.peek2(Token![::]))
1825
{
1826
path_or_macro_or_struct(input, allow_struct)
1827
} else if input.peek(token::Paren) {
1828
paren_or_tuple(input)
1829
} else if input.peek(Token![break]) {
1830
expr_break(input, allow_struct).map(Expr::Break)
1831
} else if input.peek(Token![continue]) {
1832
input.parse().map(Expr::Continue)
1833
} else if input.peek(Token![return]) {
1834
input.parse().map(Expr::Return)
1835
} else if input.peek(Token![become]) {
1836
expr_become(input)
1837
} else if input.peek(token::Bracket) {
1838
array_or_repeat(input)
1839
} else if input.peek(Token![let]) {
1840
expr_let(input, allow_struct).map(Expr::Let)
1841
} else if input.peek(Token![if]) {
1842
input.parse().map(Expr::If)
1843
} else if input.peek(Token![while]) {
1844
input.parse().map(Expr::While)
1845
} else if input.peek(Token![for]) {
1846
input.parse().map(Expr::ForLoop)
1847
} else if input.peek(Token![loop]) {
1848
input.parse().map(Expr::Loop)
1849
} else if input.peek(Token![match]) {
1850
input.parse().map(Expr::Match)
1851
} else if input.peek(Token![yield]) {
1852
input.parse().map(Expr::Yield)
1853
} else if input.peek(Token![unsafe]) {
1854
input.parse().map(Expr::Unsafe)
1855
} else if input.peek(Token![const]) {
1856
input.parse().map(Expr::Const)
1857
} else if input.peek(token::Brace) {
1858
input.parse().map(Expr::Block)
1859
} else if input.peek(Token![..]) {
1860
expr_range(input, allow_struct).map(Expr::Range)
1861
} else if input.peek(Token![_]) {
1862
input.parse().map(Expr::Infer)
1863
} else if input.peek(Lifetime) {
1864
atom_labeled(input)
1865
} else {
1866
Err(input.error("expected an expression"))
1867
}
1868
}
1869
1870
#[cfg(feature = "full")]
1871
fn atom_labeled(input: ParseStream) -> Result<Expr> {
1872
let the_label: Label = input.parse()?;
1873
let mut expr = if input.peek(Token![while]) {
1874
Expr::While(input.parse()?)
1875
} else if input.peek(Token![for]) {
1876
Expr::ForLoop(input.parse()?)
1877
} else if input.peek(Token![loop]) {
1878
Expr::Loop(input.parse()?)
1879
} else if input.peek(token::Brace) {
1880
Expr::Block(input.parse()?)
1881
} else {
1882
return Err(input.error("expected loop or block expression"));
1883
};
1884
match &mut expr {
1885
Expr::While(ExprWhile { label, .. })
1886
| Expr::ForLoop(ExprForLoop { label, .. })
1887
| Expr::Loop(ExprLoop { label, .. })
1888
| Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
1889
_ => unreachable!(),
1890
}
1891
Ok(expr)
1892
}
1893
1894
#[cfg(not(feature = "full"))]
1895
fn atom_expr(input: ParseStream) -> Result<Expr> {
1896
if input.peek(token::Group) {
1897
expr_group(input)
1898
} else if input.peek(Lit) {
1899
input.parse().map(Expr::Lit)
1900
} else if input.peek(token::Paren) {
1901
paren_or_tuple(input)
1902
} else if input.peek(Ident)
1903
|| input.peek(Token![::])
1904
|| input.peek(Token![<])
1905
|| input.peek(Token![self])
1906
|| input.peek(Token![Self])
1907
|| input.peek(Token![super])
1908
|| input.peek(Token![crate])
1909
{
1910
path_or_macro_or_struct(input)
1911
} else if input.is_empty() {
1912
Err(input.error("expected an expression"))
1913
} else {
1914
if input.peek(token::Brace) {
1915
let scan = input.fork();
1916
let content;
1917
braced!(content in scan);
1918
if content.parse::<Expr>().is_ok() && content.is_empty() {
1919
let expr_block = verbatim::between(input, &scan);
1920
input.advance_to(&scan);
1921
return Ok(Expr::Verbatim(expr_block));
1922
}
1923
}
1924
Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1925
}
1926
}
1927
1928
#[cfg(feature = "full")]
1929
fn expr_builtin(input: ParseStream) -> Result<Expr> {
1930
let begin = input.fork();
1931
1932
token::parsing::keyword(input, "builtin")?;
1933
input.parse::<Token![#]>()?;
1934
input.parse::<Ident>()?;
1935
1936
let args;
1937
parenthesized!(args in input);
1938
args.parse::<TokenStream>()?;
1939
1940
Ok(Expr::Verbatim(verbatim::between(&begin, input)))
1941
}
1942
1943
fn path_or_macro_or_struct(
1944
input: ParseStream,
1945
#[cfg(feature = "full")] allow_struct: AllowStruct,
1946
) -> Result<Expr> {
1947
let expr_style = true;
1948
let (qself, path) = path::parsing::qpath(input, expr_style)?;
1949
rest_of_path_or_macro_or_struct(
1950
qself,
1951
path,
1952
input,
1953
#[cfg(feature = "full")]
1954
allow_struct,
1955
)
1956
}
1957
1958
fn rest_of_path_or_macro_or_struct(
1959
qself: Option<QSelf>,
1960
path: Path,
1961
input: ParseStream,
1962
#[cfg(feature = "full")] allow_struct: AllowStruct,
1963
) -> Result<Expr> {
1964
if qself.is_none()
1965
&& input.peek(Token![!])
1966
&& !input.peek(Token![!=])
1967
&& path.is_mod_style()
1968
{
1969
let bang_token: Token![!] = input.parse()?;
1970
let (delimiter, tokens) = mac::parse_delimiter(input)?;
1971
return Ok(Expr::Macro(ExprMacro {
1972
attrs: Vec::new(),
1973
mac: Macro {
1974
path,
1975
bang_token,
1976
delimiter,
1977
tokens,
1978
},
1979
}));
1980
}
1981
1982
#[cfg(not(feature = "full"))]
1983
let allow_struct = (true,);
1984
if allow_struct.0 && input.peek(token::Brace) {
1985
return expr_struct_helper(input, qself, path).map(Expr::Struct);
1986
}
1987
1988
Ok(Expr::Path(ExprPath {
1989
attrs: Vec::new(),
1990
qself,
1991
path,
1992
}))
1993
}
1994
1995
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1996
impl Parse for ExprMacro {
1997
fn parse(input: ParseStream) -> Result<Self> {
1998
Ok(ExprMacro {
1999
attrs: Vec::new(),
2000
mac: input.parse()?,
2001
})
2002
}
2003
}
2004
2005
fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
2006
let content;
2007
let paren_token = parenthesized!(content in input);
2008
if content.is_empty() {
2009
return Ok(Expr::Tuple(ExprTuple {
2010
attrs: Vec::new(),
2011
paren_token,
2012
elems: Punctuated::new(),
2013
}));
2014
}
2015
2016
let first: Expr = content.parse()?;
2017
if content.is_empty() {
2018
return Ok(Expr::Paren(ExprParen {
2019
attrs: Vec::new(),
2020
paren_token,
2021
expr: Box::new(first),
2022
}));
2023
}
2024
2025
let mut elems = Punctuated::new();
2026
elems.push_value(first);
2027
while !content.is_empty() {
2028
let punct = content.parse()?;
2029
elems.push_punct(punct);
2030
if content.is_empty() {
2031
break;
2032
}
2033
let value = content.parse()?;
2034
elems.push_value(value);
2035
}
2036
Ok(Expr::Tuple(ExprTuple {
2037
attrs: Vec::new(),
2038
paren_token,
2039
elems,
2040
}))
2041
}
2042
2043
#[cfg(feature = "full")]
2044
fn array_or_repeat(input: ParseStream) -> Result<Expr> {
2045
let content;
2046
let bracket_token = bracketed!(content in input);
2047
if content.is_empty() {
2048
return Ok(Expr::Array(ExprArray {
2049
attrs: Vec::new(),
2050
bracket_token,
2051
elems: Punctuated::new(),
2052
}));
2053
}
2054
2055
let first: Expr = content.parse()?;
2056
if content.is_empty() || content.peek(Token![,]) {
2057
let mut elems = Punctuated::new();
2058
elems.push_value(first);
2059
while !content.is_empty() {
2060
let punct = content.parse()?;
2061
elems.push_punct(punct);
2062
if content.is_empty() {
2063
break;
2064
}
2065
let value = content.parse()?;
2066
elems.push_value(value);
2067
}
2068
Ok(Expr::Array(ExprArray {
2069
attrs: Vec::new(),
2070
bracket_token,
2071
elems,
2072
}))
2073
} else if content.peek(Token![;]) {
2074
let semi_token: Token![;] = content.parse()?;
2075
let len: Expr = content.parse()?;
2076
Ok(Expr::Repeat(ExprRepeat {
2077
attrs: Vec::new(),
2078
bracket_token,
2079
expr: Box::new(first),
2080
semi_token,
2081
len: Box::new(len),
2082
}))
2083
} else {
2084
Err(content.error("expected `,` or `;`"))
2085
}
2086
}
2087
2088
#[cfg(feature = "full")]
2089
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2090
impl Parse for ExprArray {
2091
fn parse(input: ParseStream) -> Result<Self> {
2092
let content;
2093
let bracket_token = bracketed!(content in input);
2094
let mut elems = Punctuated::new();
2095
2096
while !content.is_empty() {
2097
let first: Expr = content.parse()?;
2098
elems.push_value(first);
2099
if content.is_empty() {
2100
break;
2101
}
2102
let punct = content.parse()?;
2103
elems.push_punct(punct);
2104
}
2105
2106
Ok(ExprArray {
2107
attrs: Vec::new(),
2108
bracket_token,
2109
elems,
2110
})
2111
}
2112
}
2113
2114
#[cfg(feature = "full")]
2115
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2116
impl Parse for ExprRepeat {
2117
fn parse(input: ParseStream) -> Result<Self> {
2118
let content;
2119
Ok(ExprRepeat {
2120
bracket_token: bracketed!(content in input),
2121
attrs: Vec::new(),
2122
expr: content.parse()?,
2123
semi_token: content.parse()?,
2124
len: content.parse()?,
2125
})
2126
}
2127
}
2128
2129
#[cfg(feature = "full")]
2130
fn continue_parsing_early(mut expr: &Expr) -> bool {
2131
while let Expr::Group(group) = expr {
2132
expr = &group.expr;
2133
}
2134
match expr {
2135
Expr::If(_)
2136
| Expr::While(_)
2137
| Expr::ForLoop(_)
2138
| Expr::Loop(_)
2139
| Expr::Match(_)
2140
| Expr::TryBlock(_)
2141
| Expr::Unsafe(_)
2142
| Expr::Const(_)
2143
| Expr::Block(_) => false,
2144
_ => true,
2145
}
2146
}
2147
2148
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2149
impl Parse for ExprLit {
2150
fn parse(input: ParseStream) -> Result<Self> {
2151
Ok(ExprLit {
2152
attrs: Vec::new(),
2153
lit: input.parse()?,
2154
})
2155
}
2156
}
2157
2158
fn expr_group(
2159
input: ParseStream,
2160
#[cfg(feature = "full")] allow_struct: AllowStruct,
2161
) -> Result<Expr> {
2162
let group = crate::group::parse_group(input)?;
2163
let mut inner: Expr = group.content.parse()?;
2164
2165
match inner {
2166
Expr::Path(mut expr) if expr.attrs.is_empty() => {
2167
let grouped_len = expr.path.segments.len();
2168
Path::parse_rest(input, &mut expr.path, true)?;
2169
match rest_of_path_or_macro_or_struct(
2170
expr.qself,
2171
expr.path,
2172
input,
2173
#[cfg(feature = "full")]
2174
allow_struct,
2175
)? {
2176
Expr::Path(expr) if expr.path.segments.len() == grouped_len => {
2177
inner = Expr::Path(expr);
2178
}
2179
extended => return Ok(extended),
2180
}
2181
}
2182
_ => {}
2183
}
2184
2185
Ok(Expr::Group(ExprGroup {
2186
attrs: Vec::new(),
2187
group_token: group.token,
2188
expr: Box::new(inner),
2189
}))
2190
}
2191
2192
#[cfg(feature = "full")]
2193
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2194
impl Parse for ExprParen {
2195
fn parse(input: ParseStream) -> Result<Self> {
2196
let content;
2197
Ok(ExprParen {
2198
attrs: Vec::new(),
2199
paren_token: parenthesized!(content in input),
2200
expr: content.parse()?,
2201
})
2202
}
2203
}
2204
2205
#[cfg(feature = "full")]
2206
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2207
impl Parse for ExprLet {
2208
fn parse(input: ParseStream) -> Result<Self> {
2209
let allow_struct = AllowStruct(true);
2210
expr_let(input, allow_struct)
2211
}
2212
}
2213
2214
#[cfg(feature = "full")]
2215
fn expr_let(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprLet> {
2216
Ok(ExprLet {
2217
attrs: Vec::new(),
2218
let_token: input.parse()?,
2219
pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
2220
eq_token: input.parse()?,
2221
expr: Box::new({
2222
let lhs = unary_expr(input, allow_struct)?;
2223
parse_expr(input, lhs, allow_struct, Precedence::Compare)?
2224
}),
2225
})
2226
}
2227
2228
#[cfg(feature = "full")]
2229
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2230
impl Parse for ExprIf {
2231
fn parse(input: ParseStream) -> Result<Self> {
2232
let attrs = input.call(Attribute::parse_outer)?;
2233
2234
let mut clauses = Vec::new();
2235
let mut expr;
2236
loop {
2237
let if_token: Token![if] = input.parse()?;
2238
let cond = input.call(Expr::parse_without_eager_brace)?;
2239
let then_branch: Block = input.parse()?;
2240
2241
expr = ExprIf {
2242
attrs: Vec::new(),
2243
if_token,
2244
cond: Box::new(cond),
2245
then_branch,
2246
else_branch: None,
2247
};
2248
2249
if !input.peek(Token![else]) {
2250
break;
2251
}
2252
2253
let else_token: Token![else] = input.parse()?;
2254
let lookahead = input.lookahead1();
2255
if lookahead.peek(Token![if]) {
2256
expr.else_branch = Some((else_token, Box::new(Expr::PLACEHOLDER)));
2257
clauses.push(expr);
2258
} else if lookahead.peek(token::Brace) {
2259
expr.else_branch = Some((
2260
else_token,
2261
Box::new(Expr::Block(ExprBlock {
2262
attrs: Vec::new(),
2263
label: None,
2264
block: input.parse()?,
2265
})),
2266
));
2267
break;
2268
} else {
2269
return Err(lookahead.error());
2270
}
2271
}
2272
2273
while let Some(mut prev) = clauses.pop() {
2274
*prev.else_branch.as_mut().unwrap().1 = Expr::If(expr);
2275
expr = prev;
2276
}
2277
expr.attrs = attrs;
2278
Ok(expr)
2279
}
2280
}
2281
2282
#[cfg(feature = "full")]
2283
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2284
impl Parse for ExprInfer {
2285
fn parse(input: ParseStream) -> Result<Self> {
2286
Ok(ExprInfer {
2287
attrs: input.call(Attribute::parse_outer)?,
2288
underscore_token: input.parse()?,
2289
})
2290
}
2291
}
2292
2293
#[cfg(feature = "full")]
2294
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2295
impl Parse for ExprForLoop {
2296
fn parse(input: ParseStream) -> Result<Self> {
2297
let mut attrs = input.call(Attribute::parse_outer)?;
2298
let label: Option<Label> = input.parse()?;
2299
let for_token: Token![for] = input.parse()?;
2300
2301
let pat = Pat::parse_multi_with_leading_vert(input)?;
2302
2303
let in_token: Token![in] = input.parse()?;
2304
let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
2305
2306
let content;
2307
let brace_token = braced!(content in input);
2308
attr::parsing::parse_inner(&content, &mut attrs)?;
2309
let stmts = content.call(Block::parse_within)?;
2310
2311
Ok(ExprForLoop {
2312
attrs,
2313
label,
2314
for_token,
2315
pat: Box::new(pat),
2316
in_token,
2317
expr: Box::new(expr),
2318
body: Block { brace_token, stmts },
2319
})
2320
}
2321
}
2322
2323
#[cfg(feature = "full")]
2324
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2325
impl Parse for ExprLoop {
2326
fn parse(input: ParseStream) -> Result<Self> {
2327
let mut attrs = input.call(Attribute::parse_outer)?;
2328
let label: Option<Label> = input.parse()?;
2329
let loop_token: Token![loop] = input.parse()?;
2330
2331
let content;
2332
let brace_token = braced!(content in input);
2333
attr::parsing::parse_inner(&content, &mut attrs)?;
2334
let stmts = content.call(Block::parse_within)?;
2335
2336
Ok(ExprLoop {
2337
attrs,
2338
label,
2339
loop_token,
2340
body: Block { brace_token, stmts },
2341
})
2342
}
2343
}
2344
2345
#[cfg(feature = "full")]
2346
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2347
impl Parse for ExprMatch {
2348
fn parse(input: ParseStream) -> Result<Self> {
2349
let mut attrs = input.call(Attribute::parse_outer)?;
2350
let match_token: Token![match] = input.parse()?;
2351
let expr = Expr::parse_without_eager_brace(input)?;
2352
2353
let content;
2354
let brace_token = braced!(content in input);
2355
attr::parsing::parse_inner(&content, &mut attrs)?;
2356
2357
let arms = Arm::parse_multiple(&content)?;
2358
2359
Ok(ExprMatch {
2360
attrs,
2361
match_token,
2362
expr: Box::new(expr),
2363
brace_token,
2364
arms,
2365
})
2366
}
2367
}
2368
2369
macro_rules! impl_by_parsing_expr {
2370
(
2371
$(
2372
$expr_type:ty, $variant:ident, $msg:expr,
2373
)*
2374
) => {
2375
$(
2376
#[cfg(all(feature = "full", feature = "printing"))]
2377
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2378
impl Parse for $expr_type {
2379
fn parse(input: ParseStream) -> Result<Self> {
2380
let mut expr: Expr = input.parse()?;
2381
loop {
2382
match expr {
2383
Expr::$variant(inner) => return Ok(inner),
2384
Expr::Group(next) => expr = *next.expr,
2385
_ => return Err(Error::new_spanned(expr, $msg)),
2386
}
2387
}
2388
}
2389
}
2390
)*
2391
};
2392
}
2393
2394
impl_by_parsing_expr! {
2395
ExprAssign, Assign, "expected assignment expression",
2396
ExprAwait, Await, "expected await expression",
2397
ExprBinary, Binary, "expected binary operation",
2398
ExprCall, Call, "expected function call expression",
2399
ExprCast, Cast, "expected cast expression",
2400
ExprField, Field, "expected struct field access",
2401
ExprIndex, Index, "expected indexing expression",
2402
ExprMethodCall, MethodCall, "expected method call expression",
2403
ExprRange, Range, "expected range expression",
2404
ExprTry, Try, "expected try expression",
2405
ExprTuple, Tuple, "expected tuple expression",
2406
}
2407
2408
#[cfg(feature = "full")]
2409
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2410
impl Parse for ExprUnary {
2411
fn parse(input: ParseStream) -> Result<Self> {
2412
let attrs = Vec::new();
2413
let allow_struct = AllowStruct(true);
2414
expr_unary(input, attrs, allow_struct)
2415
}
2416
}
2417
2418
#[cfg(feature = "full")]
2419
fn expr_unary(
2420
input: ParseStream,
2421
attrs: Vec<Attribute>,
2422
allow_struct: AllowStruct,
2423
) -> Result<ExprUnary> {
2424
Ok(ExprUnary {
2425
attrs,
2426
op: input.parse()?,
2427
expr: Box::new(unary_expr(input, allow_struct)?),
2428
})
2429
}
2430
2431
#[cfg(feature = "full")]
2432
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2433
impl Parse for ExprClosure {
2434
fn parse(input: ParseStream) -> Result<Self> {
2435
let allow_struct = AllowStruct(true);
2436
expr_closure(input, allow_struct)
2437
}
2438
}
2439
2440
#[cfg(feature = "full")]
2441
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2442
impl Parse for ExprRawAddr {
2443
fn parse(input: ParseStream) -> Result<Self> {
2444
let allow_struct = AllowStruct(true);
2445
Ok(ExprRawAddr {
2446
attrs: Vec::new(),
2447
and_token: input.parse()?,
2448
raw: input.parse()?,
2449
mutability: input.parse()?,
2450
expr: Box::new(unary_expr(input, allow_struct)?),
2451
})
2452
}
2453
}
2454
2455
#[cfg(feature = "full")]
2456
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2457
impl Parse for ExprReference {
2458
fn parse(input: ParseStream) -> Result<Self> {
2459
let allow_struct = AllowStruct(true);
2460
Ok(ExprReference {
2461
attrs: Vec::new(),
2462
and_token: input.parse()?,
2463
mutability: input.parse()?,
2464
expr: Box::new(unary_expr(input, allow_struct)?),
2465
})
2466
}
2467
}
2468
2469
#[cfg(feature = "full")]
2470
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2471
impl Parse for ExprBreak {
2472
fn parse(input: ParseStream) -> Result<Self> {
2473
let allow_struct = AllowStruct(true);
2474
expr_break(input, allow_struct)
2475
}
2476
}
2477
2478
#[cfg(feature = "full")]
2479
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2480
impl Parse for ExprReturn {
2481
fn parse(input: ParseStream) -> Result<Self> {
2482
Ok(ExprReturn {
2483
attrs: Vec::new(),
2484
return_token: input.parse()?,
2485
expr: {
2486
if Expr::peek(input) {
2487
Some(input.parse()?)
2488
} else {
2489
None
2490
}
2491
},
2492
})
2493
}
2494
}
2495
2496
#[cfg(feature = "full")]
2497
fn expr_become(input: ParseStream) -> Result<Expr> {
2498
let begin = input.fork();
2499
input.parse::<Token![become]>()?;
2500
input.parse::<Expr>()?;
2501
Ok(Expr::Verbatim(verbatim::between(&begin, input)))
2502
}
2503
2504
#[cfg(feature = "full")]
2505
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2506
impl Parse for ExprTryBlock {
2507
fn parse(input: ParseStream) -> Result<Self> {
2508
Ok(ExprTryBlock {
2509
attrs: Vec::new(),
2510
try_token: input.parse()?,
2511
block: input.parse()?,
2512
})
2513
}
2514
}
2515
2516
#[cfg(feature = "full")]
2517
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2518
impl Parse for ExprYield {
2519
fn parse(input: ParseStream) -> Result<Self> {
2520
Ok(ExprYield {
2521
attrs: Vec::new(),
2522
yield_token: input.parse()?,
2523
expr: {
2524
if Expr::peek(input) {
2525
Some(input.parse()?)
2526
} else {
2527
None
2528
}
2529
},
2530
})
2531
}
2532
}
2533
2534
#[cfg(feature = "full")]
2535
fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2536
let lifetimes: Option<BoundLifetimes> = input.parse()?;
2537
let constness: Option<Token![const]> = input.parse()?;
2538
let movability: Option<Token![static]> = input.parse()?;
2539
let asyncness: Option<Token![async]> = input.parse()?;
2540
let capture: Option<Token![move]> = input.parse()?;
2541
let or1_token: Token![|] = input.parse()?;
2542
2543
let mut inputs = Punctuated::new();
2544
loop {
2545
if input.peek(Token![|]) {
2546
break;
2547
}
2548
let value = closure_arg(input)?;
2549
inputs.push_value(value);
2550
if input.peek(Token![|]) {
2551
break;
2552
}
2553
let punct: Token![,] = input.parse()?;
2554
inputs.push_punct(punct);
2555
}
2556
2557
let or2_token: Token![|] = input.parse()?;
2558
2559
let (output, body) = if input.peek(Token![->]) {
2560
let arrow_token: Token![->] = input.parse()?;
2561
let ty: Type = input.parse()?;
2562
let body: Block = input.parse()?;
2563
let output = ReturnType::Type(arrow_token, Box::new(ty));
2564
let block = Expr::Block(ExprBlock {
2565
attrs: Vec::new(),
2566
label: None,
2567
block: body,
2568
});
2569
(output, block)
2570
} else {
2571
let body = ambiguous_expr(input, allow_struct)?;
2572
(ReturnType::Default, body)
2573
};
2574
2575
Ok(ExprClosure {
2576
attrs: Vec::new(),
2577
lifetimes,
2578
constness,
2579
movability,
2580
asyncness,
2581
capture,
2582
or1_token,
2583
inputs,
2584
or2_token,
2585
output,
2586
body: Box::new(body),
2587
})
2588
}
2589
2590
#[cfg(feature = "full")]
2591
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2592
impl Parse for ExprAsync {
2593
fn parse(input: ParseStream) -> Result<Self> {
2594
Ok(ExprAsync {
2595
attrs: Vec::new(),
2596
async_token: input.parse()?,
2597
capture: input.parse()?,
2598
block: input.parse()?,
2599
})
2600
}
2601
}
2602
2603
#[cfg(feature = "full")]
2604
fn closure_arg(input: ParseStream) -> Result<Pat> {
2605
let attrs = input.call(Attribute::parse_outer)?;
2606
let mut pat = Pat::parse_single(input)?;
2607
2608
if input.peek(Token![:]) {
2609
Ok(Pat::Type(PatType {
2610
attrs,
2611
pat: Box::new(pat),
2612
colon_token: input.parse()?,
2613
ty: input.parse()?,
2614
}))
2615
} else {
2616
match &mut pat {
2617
Pat::Const(pat) => pat.attrs = attrs,
2618
Pat::Ident(pat) => pat.attrs = attrs,
2619
Pat::Lit(pat) => pat.attrs = attrs,
2620
Pat::Macro(pat) => pat.attrs = attrs,
2621
Pat::Or(pat) => pat.attrs = attrs,
2622
Pat::Paren(pat) => pat.attrs = attrs,
2623
Pat::Path(pat) => pat.attrs = attrs,
2624
Pat::Range(pat) => pat.attrs = attrs,
2625
Pat::Reference(pat) => pat.attrs = attrs,
2626
Pat::Rest(pat) => pat.attrs = attrs,
2627
Pat::Slice(pat) => pat.attrs = attrs,
2628
Pat::Struct(pat) => pat.attrs = attrs,
2629
Pat::Tuple(pat) => pat.attrs = attrs,
2630
Pat::TupleStruct(pat) => pat.attrs = attrs,
2631
Pat::Type(_) => unreachable!(),
2632
Pat::Verbatim(_) => {}
2633
Pat::Wild(pat) => pat.attrs = attrs,
2634
}
2635
Ok(pat)
2636
}
2637
}
2638
2639
#[cfg(feature = "full")]
2640
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2641
impl Parse for ExprWhile {
2642
fn parse(input: ParseStream) -> Result<Self> {
2643
let mut attrs = input.call(Attribute::parse_outer)?;
2644
let label: Option<Label> = input.parse()?;
2645
let while_token: Token![while] = input.parse()?;
2646
let cond = Expr::parse_without_eager_brace(input)?;
2647
2648
let content;
2649
let brace_token = braced!(content in input);
2650
attr::parsing::parse_inner(&content, &mut attrs)?;
2651
let stmts = content.call(Block::parse_within)?;
2652
2653
Ok(ExprWhile {
2654
attrs,
2655
label,
2656
while_token,
2657
cond: Box::new(cond),
2658
body: Block { brace_token, stmts },
2659
})
2660
}
2661
}
2662
2663
#[cfg(feature = "full")]
2664
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2665
impl Parse for ExprConst {
2666
fn parse(input: ParseStream) -> Result<Self> {
2667
let const_token: Token![const] = input.parse()?;
2668
2669
let content;
2670
let brace_token = braced!(content in input);
2671
let inner_attrs = content.call(Attribute::parse_inner)?;
2672
let stmts = content.call(Block::parse_within)?;
2673
2674
Ok(ExprConst {
2675
attrs: inner_attrs,
2676
const_token,
2677
block: Block { brace_token, stmts },
2678
})
2679
}
2680
}
2681
2682
#[cfg(feature = "full")]
2683
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2684
impl Parse for Label {
2685
fn parse(input: ParseStream) -> Result<Self> {
2686
Ok(Label {
2687
name: input.parse()?,
2688
colon_token: input.parse()?,
2689
})
2690
}
2691
}
2692
2693
#[cfg(feature = "full")]
2694
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2695
impl Parse for Option<Label> {
2696
fn parse(input: ParseStream) -> Result<Self> {
2697
if input.peek(Lifetime) {
2698
input.parse().map(Some)
2699
} else {
2700
Ok(None)
2701
}
2702
}
2703
}
2704
2705
#[cfg(feature = "full")]
2706
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2707
impl Parse for ExprContinue {
2708
fn parse(input: ParseStream) -> Result<Self> {
2709
Ok(ExprContinue {
2710
attrs: Vec::new(),
2711
continue_token: input.parse()?,
2712
label: input.parse()?,
2713
})
2714
}
2715
}
2716
2717
#[cfg(feature = "full")]
2718
fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2719
let break_token: Token![break] = input.parse()?;
2720
2721
let ahead = input.fork();
2722
let label: Option<Lifetime> = ahead.parse()?;
2723
if label.is_some() && ahead.peek(Token![:]) {
2724
// Not allowed: `break 'label: loop {...}`
2725
// Parentheses are required. `break ('label: loop {...})`
2726
let _: Expr = input.parse()?;
2727
let start_span = label.unwrap().apostrophe;
2728
let end_span = input.cursor().prev_span();
2729
return Err(crate::error::new2(
2730
start_span,
2731
end_span,
2732
"parentheses required",
2733
));
2734
}
2735
2736
input.advance_to(&ahead);
2737
let expr = if Expr::peek(input) && (allow_struct.0 || !input.peek(token::Brace)) {
2738
Some(input.parse()?)
2739
} else {
2740
None
2741
};
2742
2743
Ok(ExprBreak {
2744
attrs: Vec::new(),
2745
break_token,
2746
label,
2747
expr,
2748
})
2749
}
2750
2751
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2752
impl Parse for FieldValue {
2753
fn parse(input: ParseStream) -> Result<Self> {
2754
let attrs = input.call(Attribute::parse_outer)?;
2755
let member: Member = input.parse()?;
2756
let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2757
let colon_token: Token![:] = input.parse()?;
2758
let value: Expr = input.parse()?;
2759
(Some(colon_token), value)
2760
} else if let Member::Named(ident) = &member {
2761
let value = Expr::Path(ExprPath {
2762
attrs: Vec::new(),
2763
qself: None,
2764
path: Path::from(ident.clone()),
2765
});
2766
(None, value)
2767
} else {
2768
unreachable!()
2769
};
2770
2771
Ok(FieldValue {
2772
attrs,
2773
member,
2774
colon_token,
2775
expr: value,
2776
})
2777
}
2778
}
2779
2780
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2781
impl Parse for ExprStruct {
2782
fn parse(input: ParseStream) -> Result<Self> {
2783
let expr_style = true;
2784
let (qself, path) = path::parsing::qpath(input, expr_style)?;
2785
expr_struct_helper(input, qself, path)
2786
}
2787
}
2788
2789
fn expr_struct_helper(
2790
input: ParseStream,
2791
qself: Option<QSelf>,
2792
path: Path,
2793
) -> Result<ExprStruct> {
2794
let content;
2795
let brace_token = braced!(content in input);
2796
2797
let mut fields = Punctuated::new();
2798
while !content.is_empty() {
2799
if content.peek(Token![..]) {
2800
return Ok(ExprStruct {
2801
attrs: Vec::new(),
2802
qself,
2803
path,
2804
brace_token,
2805
fields,
2806
dot2_token: Some(content.parse()?),
2807
rest: if content.is_empty() {
2808
None
2809
} else {
2810
Some(Box::new(content.parse()?))
2811
},
2812
});
2813
}
2814
2815
fields.push(content.parse()?);
2816
if content.is_empty() {
2817
break;
2818
}
2819
let punct: Token![,] = content.parse()?;
2820
fields.push_punct(punct);
2821
}
2822
2823
Ok(ExprStruct {
2824
attrs: Vec::new(),
2825
qself,
2826
path,
2827
brace_token,
2828
fields,
2829
dot2_token: None,
2830
rest: None,
2831
})
2832
}
2833
2834
#[cfg(feature = "full")]
2835
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2836
impl Parse for ExprUnsafe {
2837
fn parse(input: ParseStream) -> Result<Self> {
2838
let unsafe_token: Token![unsafe] = input.parse()?;
2839
2840
let content;
2841
let brace_token = braced!(content in input);
2842
let inner_attrs = content.call(Attribute::parse_inner)?;
2843
let stmts = content.call(Block::parse_within)?;
2844
2845
Ok(ExprUnsafe {
2846
attrs: inner_attrs,
2847
unsafe_token,
2848
block: Block { brace_token, stmts },
2849
})
2850
}
2851
}
2852
2853
#[cfg(feature = "full")]
2854
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2855
impl Parse for ExprBlock {
2856
fn parse(input: ParseStream) -> Result<Self> {
2857
let mut attrs = input.call(Attribute::parse_outer)?;
2858
let label: Option<Label> = input.parse()?;
2859
2860
let content;
2861
let brace_token = braced!(content in input);
2862
attr::parsing::parse_inner(&content, &mut attrs)?;
2863
let stmts = content.call(Block::parse_within)?;
2864
2865
Ok(ExprBlock {
2866
attrs,
2867
label,
2868
block: Block { brace_token, stmts },
2869
})
2870
}
2871
}
2872
2873
#[cfg(feature = "full")]
2874
fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2875
let limits: RangeLimits = input.parse()?;
2876
let end = parse_range_end(input, &limits, allow_struct)?;
2877
Ok(ExprRange {
2878
attrs: Vec::new(),
2879
start: None,
2880
limits,
2881
end,
2882
})
2883
}
2884
2885
#[cfg(feature = "full")]
2886
fn parse_range_end(
2887
input: ParseStream,
2888
limits: &RangeLimits,
2889
allow_struct: AllowStruct,
2890
) -> Result<Option<Box<Expr>>> {
2891
if matches!(limits, RangeLimits::HalfOpen(_))
2892
&& (input.is_empty()
2893
|| input.peek(Token![,])
2894
|| input.peek(Token![;])
2895
|| input.peek(Token![.]) && !input.peek(Token![..])
2896
|| input.peek(Token![?])
2897
|| input.peek(Token![=>])
2898
|| !allow_struct.0 && input.peek(token::Brace)
2899
|| input.peek(Token![=])
2900
|| input.peek(Token![+])
2901
|| input.peek(Token![/])
2902
|| input.peek(Token![%])
2903
|| input.peek(Token![^])
2904
|| input.peek(Token![>])
2905
|| input.peek(Token![<=])
2906
|| input.peek(Token![!=])
2907
|| input.peek(Token![-=])
2908
|| input.peek(Token![*=])
2909
|| input.peek(Token![&=])
2910
|| input.peek(Token![|=])
2911
|| input.peek(Token![<<=])
2912
|| input.peek(Token![as]))
2913
{
2914
Ok(None)
2915
} else {
2916
let end = parse_binop_rhs(input, allow_struct, Precedence::Range)?;
2917
Ok(Some(end))
2918
}
2919
}
2920
2921
#[cfg(feature = "full")]
2922
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2923
impl Parse for RangeLimits {
2924
fn parse(input: ParseStream) -> Result<Self> {
2925
let lookahead = input.lookahead1();
2926
let dot_dot = lookahead.peek(Token![..]);
2927
let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
2928
let dot_dot_dot = dot_dot && input.peek(Token![...]);
2929
if dot_dot_eq {
2930
input.parse().map(RangeLimits::Closed)
2931
} else if dot_dot && !dot_dot_dot {
2932
input.parse().map(RangeLimits::HalfOpen)
2933
} else {
2934
Err(lookahead.error())
2935
}
2936
}
2937
}
2938
2939
#[cfg(feature = "full")]
2940
impl RangeLimits {
2941
pub(crate) fn parse_obsolete(input: ParseStream) -> Result<Self> {
2942
let lookahead = input.lookahead1();
2943
let dot_dot = lookahead.peek(Token![..]);
2944
let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
2945
let dot_dot_dot = dot_dot && input.peek(Token![...]);
2946
if dot_dot_eq {
2947
input.parse().map(RangeLimits::Closed)
2948
} else if dot_dot_dot {
2949
let dot3: Token![...] = input.parse()?;
2950
Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2951
} else if dot_dot {
2952
input.parse().map(RangeLimits::HalfOpen)
2953
} else {
2954
Err(lookahead.error())
2955
}
2956
}
2957
}
2958
2959
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2960
impl Parse for ExprPath {
2961
fn parse(input: ParseStream) -> Result<Self> {
2962
#[cfg(not(feature = "full"))]
2963
let attrs = Vec::new();
2964
#[cfg(feature = "full")]
2965
let attrs = input.call(Attribute::parse_outer)?;
2966
2967
let expr_style = true;
2968
let (qself, path) = path::parsing::qpath(input, expr_style)?;
2969
2970
Ok(ExprPath { attrs, qself, path })
2971
}
2972
}
2973
2974
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2975
impl Parse for Member {
2976
fn parse(input: ParseStream) -> Result<Self> {
2977
if input.peek(Ident) {
2978
input.parse().map(Member::Named)
2979
} else if input.peek(LitInt) {
2980
input.parse().map(Member::Unnamed)
2981
} else {
2982
Err(input.error("expected identifier or integer"))
2983
}
2984
}
2985
}
2986
2987
#[cfg(feature = "full")]
2988
impl Arm {
2989
pub(crate) fn parse_multiple(input: ParseStream) -> Result<Vec<Self>> {
2990
let mut arms = Vec::new();
2991
while !input.is_empty() {
2992
arms.push(input.call(Arm::parse)?);
2993
}
2994
Ok(arms)
2995
}
2996
}
2997
2998
#[cfg(feature = "full")]
2999
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3000
impl Parse for Arm {
3001
fn parse(input: ParseStream) -> Result<Arm> {
3002
let requires_comma;
3003
Ok(Arm {
3004
attrs: input.call(Attribute::parse_outer)?,
3005
pat: Pat::parse_multi_with_leading_vert(input)?,
3006
guard: {
3007
if input.peek(Token![if]) {
3008
let if_token: Token![if] = input.parse()?;
3009
let guard: Expr = input.parse()?;
3010
Some((if_token, Box::new(guard)))
3011
} else {
3012
None
3013
}
3014
},
3015
fat_arrow_token: input.parse()?,
3016
body: {
3017
let body = Expr::parse_with_earlier_boundary_rule(input)?;
3018
requires_comma = classify::requires_comma_to_be_match_arm(&body);
3019
Box::new(body)
3020
},
3021
comma: {
3022
if requires_comma && !input.is_empty() {
3023
Some(input.parse()?)
3024
} else {
3025
input.parse()?
3026
}
3027
},
3028
})
3029
}
3030
}
3031
3032
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3033
impl Parse for Index {
3034
fn parse(input: ParseStream) -> Result<Self> {
3035
let lit: LitInt = input.parse()?;
3036
if lit.suffix().is_empty() {
3037
Ok(Index {
3038
index: lit
3039
.base10_digits()
3040
.parse()
3041
.map_err(|err| Error::new(lit.span(), err))?,
3042
span: lit.span(),
3043
})
3044
} else {
3045
Err(Error::new(lit.span(), "expected unsuffixed integer"))
3046
}
3047
}
3048
}
3049
3050
fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
3051
let float_token = float.token();
3052
let float_span = float_token.span();
3053
let mut float_repr = float_token.to_string();
3054
let trailing_dot = float_repr.ends_with('.');
3055
if trailing_dot {
3056
float_repr.truncate(float_repr.len() - 1);
3057
}
3058
3059
let mut offset = 0;
3060
for part in float_repr.split('.') {
3061
let mut index: Index =
3062
crate::parse_str(part).map_err(|err| Error::new(float_span, err))?;
3063
let part_end = offset + part.len();
3064
index.span = float_token.subspan(offset..part_end).unwrap_or(float_span);
3065
3066
let base = mem::replace(e, Expr::PLACEHOLDER);
3067
*e = Expr::Field(ExprField {
3068
attrs: Vec::new(),
3069
base: Box::new(base),
3070
dot_token: Token![.](dot_token.span),
3071
member: Member::Unnamed(index),
3072
});
3073
3074
let dot_span = float_token
3075
.subspan(part_end..part_end + 1)
3076
.unwrap_or(float_span);
3077
*dot_token = Token![.](dot_span);
3078
offset = part_end + 1;
3079
}
3080
3081
Ok(!trailing_dot)
3082
}
3083
3084
#[cfg(feature = "full")]
3085
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3086
impl Parse for PointerMutability {
3087
fn parse(input: ParseStream) -> Result<Self> {
3088
let lookahead = input.lookahead1();
3089
if lookahead.peek(Token![const]) {
3090
Ok(PointerMutability::Const(input.parse()?))
3091
} else if lookahead.peek(Token![mut]) {
3092
Ok(PointerMutability::Mut(input.parse()?))
3093
} else {
3094
Err(lookahead.error())
3095
}
3096
}
3097
}
3098
3099
fn check_cast(input: ParseStream) -> Result<()> {
3100
let kind = if input.peek(Token![.]) && !input.peek(Token![..]) {
3101
if input.peek2(Token![await]) {
3102
"`.await`"
3103
} else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(Token![::])) {
3104
"a method call"
3105
} else {
3106
"a field access"
3107
}
3108
} else if input.peek(Token![?]) {
3109
"`?`"
3110
} else if input.peek(token::Bracket) {
3111
"indexing"
3112
} else if input.peek(token::Paren) {
3113
"a function call"
3114
} else {
3115
return Ok(());
3116
};
3117
let msg = format!("casts cannot be followed by {}", kind);
3118
Err(input.error(msg))
3119
}
3120
}
3121
3122
#[cfg(feature = "printing")]
3123
pub(crate) mod printing {
3124
use crate::attr::Attribute;
3125
#[cfg(feature = "full")]
3126
use crate::attr::FilterAttrs;
3127
#[cfg(feature = "full")]
3128
use crate::classify;
3129
#[cfg(feature = "full")]
3130
use crate::expr::{
3131
Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
3132
ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
3133
ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
3134
ExprWhile, ExprYield, Label, PointerMutability, RangeLimits,
3135
};
3136
use crate::expr::{
3137
Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
3138
ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
3139
FieldValue, Index, Member,
3140
};
3141
use crate::fixup::FixupContext;
3142
use crate::op::BinOp;
3143
use crate::path;
3144
use crate::path::printing::PathStyle;
3145
use crate::precedence::Precedence;
3146
use crate::token;
3147
#[cfg(feature = "full")]
3148
use crate::ty::ReturnType;
3149
use proc_macro2::{Literal, Span, TokenStream};
3150
use quote::{ToTokens, TokenStreamExt};
3151
3152
#[cfg(feature = "full")]
3153
pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3154
tokens.append_all(attrs.outer());
3155
}
3156
3157
#[cfg(feature = "full")]
3158
fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3159
tokens.append_all(attrs.inner());
3160
}
3161
3162
#[cfg(not(feature = "full"))]
3163
pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3164
3165
pub(crate) fn print_subexpression(
3166
expr: &Expr,
3167
needs_group: bool,
3168
tokens: &mut TokenStream,
3169
mut fixup: FixupContext,
3170
) {
3171
if needs_group {
3172
// If we are surrounding the whole cond in parentheses, such as:
3173
//
3174
// if (return Struct {}) {}
3175
//
3176
// then there is no need for parenthesizing the individual struct
3177
// expressions within. On the other hand if the whole cond is not
3178
// parenthesized, then print_expr must parenthesize exterior struct
3179
// literals.
3180
//
3181
// if x == (Struct {}) {}
3182
//
3183
fixup = FixupContext::NONE;
3184
}
3185
3186
let do_print_expr = |tokens: &mut TokenStream| print_expr(expr, tokens, fixup);
3187
3188
if needs_group {
3189
token::Paren::default().surround(tokens, do_print_expr);
3190
} else {
3191
do_print_expr(tokens);
3192
}
3193
}
3194
3195
pub(crate) fn print_expr(expr: &Expr, tokens: &mut TokenStream, mut fixup: FixupContext) {
3196
#[cfg(feature = "full")]
3197
let needs_group = fixup.parenthesize(expr);
3198
#[cfg(not(feature = "full"))]
3199
let needs_group = false;
3200
3201
if needs_group {
3202
fixup = FixupContext::NONE;
3203
}
3204
3205
let do_print_expr = |tokens: &mut TokenStream| match expr {
3206
#[cfg(feature = "full")]
3207
Expr::Array(e) => e.to_tokens(tokens),
3208
#[cfg(feature = "full")]
3209
Expr::Assign(e) => print_expr_assign(e, tokens, fixup),
3210
#[cfg(feature = "full")]
3211
Expr::Async(e) => e.to_tokens(tokens),
3212
#[cfg(feature = "full")]
3213
Expr::Await(e) => print_expr_await(e, tokens, fixup),
3214
Expr::Binary(e) => print_expr_binary(e, tokens, fixup),
3215
#[cfg(feature = "full")]
3216
Expr::Block(e) => e.to_tokens(tokens),
3217
#[cfg(feature = "full")]
3218
Expr::Break(e) => print_expr_break(e, tokens, fixup),
3219
Expr::Call(e) => print_expr_call(e, tokens, fixup),
3220
Expr::Cast(e) => print_expr_cast(e, tokens, fixup),
3221
#[cfg(feature = "full")]
3222
Expr::Closure(e) => print_expr_closure(e, tokens, fixup),
3223
#[cfg(feature = "full")]
3224
Expr::Const(e) => e.to_tokens(tokens),
3225
#[cfg(feature = "full")]
3226
Expr::Continue(e) => e.to_tokens(tokens),
3227
Expr::Field(e) => print_expr_field(e, tokens, fixup),
3228
#[cfg(feature = "full")]
3229
Expr::ForLoop(e) => e.to_tokens(tokens),
3230
Expr::Group(e) => e.to_tokens(tokens),
3231
#[cfg(feature = "full")]
3232
Expr::If(e) => e.to_tokens(tokens),
3233
Expr::Index(e) => print_expr_index(e, tokens, fixup),
3234
#[cfg(feature = "full")]
3235
Expr::Infer(e) => e.to_tokens(tokens),
3236
#[cfg(feature = "full")]
3237
Expr::Let(e) => print_expr_let(e, tokens, fixup),
3238
Expr::Lit(e) => e.to_tokens(tokens),
3239
#[cfg(feature = "full")]
3240
Expr::Loop(e) => e.to_tokens(tokens),
3241
Expr::Macro(e) => e.to_tokens(tokens),
3242
#[cfg(feature = "full")]
3243
Expr::Match(e) => e.to_tokens(tokens),
3244
Expr::MethodCall(e) => print_expr_method_call(e, tokens, fixup),
3245
Expr::Paren(e) => e.to_tokens(tokens),
3246
Expr::Path(e) => e.to_tokens(tokens),
3247
#[cfg(feature = "full")]
3248
Expr::Range(e) => print_expr_range(e, tokens, fixup),
3249
#[cfg(feature = "full")]
3250
Expr::RawAddr(e) => print_expr_raw_addr(e, tokens, fixup),
3251
Expr::Reference(e) => print_expr_reference(e, tokens, fixup),
3252
#[cfg(feature = "full")]
3253
Expr::Repeat(e) => e.to_tokens(tokens),
3254
#[cfg(feature = "full")]
3255
Expr::Return(e) => print_expr_return(e, tokens, fixup),
3256
Expr::Struct(e) => e.to_tokens(tokens),
3257
#[cfg(feature = "full")]
3258
Expr::Try(e) => print_expr_try(e, tokens, fixup),
3259
#[cfg(feature = "full")]
3260
Expr::TryBlock(e) => e.to_tokens(tokens),
3261
Expr::Tuple(e) => e.to_tokens(tokens),
3262
Expr::Unary(e) => print_expr_unary(e, tokens, fixup),
3263
#[cfg(feature = "full")]
3264
Expr::Unsafe(e) => e.to_tokens(tokens),
3265
Expr::Verbatim(e) => e.to_tokens(tokens),
3266
#[cfg(feature = "full")]
3267
Expr::While(e) => e.to_tokens(tokens),
3268
#[cfg(feature = "full")]
3269
Expr::Yield(e) => print_expr_yield(e, tokens, fixup),
3270
3271
#[cfg(not(feature = "full"))]
3272
_ => unreachable!(),
3273
};
3274
3275
if needs_group {
3276
token::Paren::default().surround(tokens, do_print_expr);
3277
} else {
3278
do_print_expr(tokens);
3279
}
3280
}
3281
3282
#[cfg(feature = "full")]
3283
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3284
impl ToTokens for ExprArray {
3285
fn to_tokens(&self, tokens: &mut TokenStream) {
3286
outer_attrs_to_tokens(&self.attrs, tokens);
3287
self.bracket_token.surround(tokens, |tokens| {
3288
self.elems.to_tokens(tokens);
3289
});
3290
}
3291
}
3292
3293
#[cfg(feature = "full")]
3294
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3295
impl ToTokens for ExprAssign {
3296
fn to_tokens(&self, tokens: &mut TokenStream) {
3297
print_expr_assign(self, tokens, FixupContext::NONE);
3298
}
3299
}
3300
3301
#[cfg(feature = "full")]
3302
fn print_expr_assign(e: &ExprAssign, tokens: &mut TokenStream, mut fixup: FixupContext) {
3303
outer_attrs_to_tokens(&e.attrs, tokens);
3304
3305
let needs_group = !e.attrs.is_empty();
3306
if needs_group {
3307
fixup = FixupContext::NONE;
3308
}
3309
3310
let do_print_expr = |tokens: &mut TokenStream| {
3311
let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3312
&e.left,
3313
false,
3314
false,
3315
Precedence::Assign,
3316
);
3317
print_subexpression(&e.left, left_prec <= Precedence::Range, tokens, left_fixup);
3318
e.eq_token.to_tokens(tokens);
3319
print_expr(
3320
&e.right,
3321
tokens,
3322
fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign),
3323
);
3324
};
3325
3326
if needs_group {
3327
token::Paren::default().surround(tokens, do_print_expr);
3328
} else {
3329
do_print_expr(tokens);
3330
}
3331
}
3332
3333
#[cfg(feature = "full")]
3334
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3335
impl ToTokens for ExprAsync {
3336
fn to_tokens(&self, tokens: &mut TokenStream) {
3337
outer_attrs_to_tokens(&self.attrs, tokens);
3338
self.async_token.to_tokens(tokens);
3339
self.capture.to_tokens(tokens);
3340
self.block.to_tokens(tokens);
3341
}
3342
}
3343
3344
#[cfg(feature = "full")]
3345
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3346
impl ToTokens for ExprAwait {
3347
fn to_tokens(&self, tokens: &mut TokenStream) {
3348
print_expr_await(self, tokens, FixupContext::NONE);
3349
}
3350
}
3351
3352
#[cfg(feature = "full")]
3353
fn print_expr_await(e: &ExprAwait, tokens: &mut TokenStream, fixup: FixupContext) {
3354
outer_attrs_to_tokens(&e.attrs, tokens);
3355
let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3356
print_subexpression(
3357
&e.base,
3358
left_prec < Precedence::Unambiguous,
3359
tokens,
3360
left_fixup,
3361
);
3362
e.dot_token.to_tokens(tokens);
3363
e.await_token.to_tokens(tokens);
3364
}
3365
3366
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3367
impl ToTokens for ExprBinary {
3368
fn to_tokens(&self, tokens: &mut TokenStream) {
3369
print_expr_binary(self, tokens, FixupContext::NONE);
3370
}
3371
}
3372
3373
fn print_expr_binary(e: &ExprBinary, tokens: &mut TokenStream, mut fixup: FixupContext) {
3374
outer_attrs_to_tokens(&e.attrs, tokens);
3375
3376
let needs_group = !e.attrs.is_empty();
3377
if needs_group {
3378
fixup = FixupContext::NONE;
3379
}
3380
3381
let do_print_expr = |tokens: &mut TokenStream| {
3382
let binop_prec = Precedence::of_binop(&e.op);
3383
let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3384
&e.left,
3385
#[cfg(feature = "full")]
3386
match &e.op {
3387
BinOp::Sub(_)
3388
| BinOp::Mul(_)
3389
| BinOp::And(_)
3390
| BinOp::Or(_)
3391
| BinOp::BitAnd(_)
3392
| BinOp::BitOr(_)
3393
| BinOp::Shl(_)
3394
| BinOp::Lt(_) => true,
3395
_ => false,
3396
},
3397
match &e.op {
3398
BinOp::Shl(_) | BinOp::Lt(_) => true,
3399
_ => false,
3400
},
3401
#[cfg(feature = "full")]
3402
binop_prec,
3403
);
3404
let left_needs_group = match binop_prec {
3405
Precedence::Assign => left_prec <= Precedence::Range,
3406
Precedence::Compare => left_prec <= binop_prec,
3407
_ => left_prec < binop_prec,
3408
};
3409
3410
let right_fixup = fixup.rightmost_subexpression_fixup(
3411
#[cfg(feature = "full")]
3412
false,
3413
#[cfg(feature = "full")]
3414
false,
3415
#[cfg(feature = "full")]
3416
binop_prec,
3417
);
3418
let right_needs_group = binop_prec != Precedence::Assign
3419
&& right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
3420
3421
print_subexpression(&e.left, left_needs_group, tokens, left_fixup);
3422
e.op.to_tokens(tokens);
3423
print_subexpression(&e.right, right_needs_group, tokens, right_fixup);
3424
};
3425
3426
if needs_group {
3427
token::Paren::default().surround(tokens, do_print_expr);
3428
} else {
3429
do_print_expr(tokens);
3430
}
3431
}
3432
3433
#[cfg(feature = "full")]
3434
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3435
impl ToTokens for ExprBlock {
3436
fn to_tokens(&self, tokens: &mut TokenStream) {
3437
outer_attrs_to_tokens(&self.attrs, tokens);
3438
self.label.to_tokens(tokens);
3439
self.block.brace_token.surround(tokens, |tokens| {
3440
inner_attrs_to_tokens(&self.attrs, tokens);
3441
tokens.append_all(&self.block.stmts);
3442
});
3443
}
3444
}
3445
3446
#[cfg(feature = "full")]
3447
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3448
impl ToTokens for ExprBreak {
3449
fn to_tokens(&self, tokens: &mut TokenStream) {
3450
print_expr_break(self, tokens, FixupContext::NONE);
3451
}
3452
}
3453
3454
#[cfg(feature = "full")]
3455
fn print_expr_break(e: &ExprBreak, tokens: &mut TokenStream, fixup: FixupContext) {
3456
outer_attrs_to_tokens(&e.attrs, tokens);
3457
e.break_token.to_tokens(tokens);
3458
e.label.to_tokens(tokens);
3459
if let Some(value) = &e.expr {
3460
print_subexpression(
3461
value,
3462
// Parenthesize `break 'inner: loop { break 'inner 1 } + 1`
3463
// ^---------------------------------^
3464
e.label.is_none() && classify::expr_leading_label(value),
3465
tokens,
3466
fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump),
3467
);
3468
}
3469
}
3470
3471
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3472
impl ToTokens for ExprCall {
3473
fn to_tokens(&self, tokens: &mut TokenStream) {
3474
print_expr_call(self, tokens, FixupContext::NONE);
3475
}
3476
}
3477
3478
fn print_expr_call(e: &ExprCall, tokens: &mut TokenStream, fixup: FixupContext) {
3479
outer_attrs_to_tokens(&e.attrs, tokens);
3480
3481
let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3482
&e.func,
3483
#[cfg(feature = "full")]
3484
true,
3485
false,
3486
#[cfg(feature = "full")]
3487
Precedence::Unambiguous,
3488
);
3489
let needs_group = if let Expr::Field(func) = &*e.func {
3490
func.member.is_named()
3491
} else {
3492
left_prec < Precedence::Unambiguous
3493
};
3494
print_subexpression(&e.func, needs_group, tokens, left_fixup);
3495
3496
e.paren_token.surround(tokens, |tokens| {
3497
e.args.to_tokens(tokens);
3498
});
3499
}
3500
3501
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3502
impl ToTokens for ExprCast {
3503
fn to_tokens(&self, tokens: &mut TokenStream) {
3504
print_expr_cast(self, tokens, FixupContext::NONE);
3505
}
3506
}
3507
3508
fn print_expr_cast(e: &ExprCast, tokens: &mut TokenStream, mut fixup: FixupContext) {
3509
outer_attrs_to_tokens(&e.attrs, tokens);
3510
3511
let needs_group = !e.attrs.is_empty();
3512
if needs_group {
3513
fixup = FixupContext::NONE;
3514
}
3515
3516
let do_print_expr = |tokens: &mut TokenStream| {
3517
let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3518
&e.expr,
3519
#[cfg(feature = "full")]
3520
false,
3521
false,
3522
#[cfg(feature = "full")]
3523
Precedence::Cast,
3524
);
3525
print_subexpression(&e.expr, left_prec < Precedence::Cast, tokens, left_fixup);
3526
e.as_token.to_tokens(tokens);
3527
e.ty.to_tokens(tokens);
3528
};
3529
3530
if needs_group {
3531
token::Paren::default().surround(tokens, do_print_expr);
3532
} else {
3533
do_print_expr(tokens);
3534
}
3535
}
3536
3537
#[cfg(feature = "full")]
3538
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3539
impl ToTokens for ExprClosure {
3540
fn to_tokens(&self, tokens: &mut TokenStream) {
3541
print_expr_closure(self, tokens, FixupContext::NONE);
3542
}
3543
}
3544
3545
#[cfg(feature = "full")]
3546
fn print_expr_closure(e: &ExprClosure, tokens: &mut TokenStream, fixup: FixupContext) {
3547
outer_attrs_to_tokens(&e.attrs, tokens);
3548
e.lifetimes.to_tokens(tokens);
3549
e.constness.to_tokens(tokens);
3550
e.movability.to_tokens(tokens);
3551
e.asyncness.to_tokens(tokens);
3552
e.capture.to_tokens(tokens);
3553
e.or1_token.to_tokens(tokens);
3554
e.inputs.to_tokens(tokens);
3555
e.or2_token.to_tokens(tokens);
3556
e.output.to_tokens(tokens);
3557
if matches!(e.output, ReturnType::Default)
3558
|| matches!(&*e.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
3559
{
3560
print_expr(
3561
&e.body,
3562
tokens,
3563
fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
3564
);
3565
} else {
3566
token::Brace::default().surround(tokens, |tokens| {
3567
print_expr(&e.body, tokens, FixupContext::new_stmt());
3568
});
3569
}
3570
}
3571
3572
#[cfg(feature = "full")]
3573
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3574
impl ToTokens for ExprConst {
3575
fn to_tokens(&self, tokens: &mut TokenStream) {
3576
outer_attrs_to_tokens(&self.attrs, tokens);
3577
self.const_token.to_tokens(tokens);
3578
self.block.brace_token.surround(tokens, |tokens| {
3579
inner_attrs_to_tokens(&self.attrs, tokens);
3580
tokens.append_all(&self.block.stmts);
3581
});
3582
}
3583
}
3584
3585
#[cfg(feature = "full")]
3586
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3587
impl ToTokens for ExprContinue {
3588
fn to_tokens(&self, tokens: &mut TokenStream) {
3589
outer_attrs_to_tokens(&self.attrs, tokens);
3590
self.continue_token.to_tokens(tokens);
3591
self.label.to_tokens(tokens);
3592
}
3593
}
3594
3595
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3596
impl ToTokens for ExprField {
3597
fn to_tokens(&self, tokens: &mut TokenStream) {
3598
print_expr_field(self, tokens, FixupContext::NONE);
3599
}
3600
}
3601
3602
fn print_expr_field(e: &ExprField, tokens: &mut TokenStream, fixup: FixupContext) {
3603
outer_attrs_to_tokens(&e.attrs, tokens);
3604
let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3605
print_subexpression(
3606
&e.base,
3607
left_prec < Precedence::Unambiguous,
3608
tokens,
3609
left_fixup,
3610
);
3611
e.dot_token.to_tokens(tokens);
3612
e.member.to_tokens(tokens);
3613
}
3614
3615
#[cfg(feature = "full")]
3616
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3617
impl ToTokens for ExprForLoop {
3618
fn to_tokens(&self, tokens: &mut TokenStream) {
3619
outer_attrs_to_tokens(&self.attrs, tokens);
3620
self.label.to_tokens(tokens);
3621
self.for_token.to_tokens(tokens);
3622
self.pat.to_tokens(tokens);
3623
self.in_token.to_tokens(tokens);
3624
print_expr(&self.expr, tokens, FixupContext::new_condition());
3625
self.body.brace_token.surround(tokens, |tokens| {
3626
inner_attrs_to_tokens(&self.attrs, tokens);
3627
tokens.append_all(&self.body.stmts);
3628
});
3629
}
3630
}
3631
3632
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3633
impl ToTokens for ExprGroup {
3634
fn to_tokens(&self, tokens: &mut TokenStream) {
3635
outer_attrs_to_tokens(&self.attrs, tokens);
3636
self.group_token.surround(tokens, |tokens| {
3637
self.expr.to_tokens(tokens);
3638
});
3639
}
3640
}
3641
3642
#[cfg(feature = "full")]
3643
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3644
impl ToTokens for ExprIf {
3645
fn to_tokens(&self, tokens: &mut TokenStream) {
3646
outer_attrs_to_tokens(&self.attrs, tokens);
3647
3648
let mut expr = self;
3649
loop {
3650
expr.if_token.to_tokens(tokens);
3651
print_expr(&expr.cond, tokens, FixupContext::new_condition());
3652
expr.then_branch.to_tokens(tokens);
3653
3654
let (else_token, else_) = match &expr.else_branch {
3655
Some(else_branch) => else_branch,
3656
None => break,
3657
};
3658
3659
else_token.to_tokens(tokens);
3660
match &**else_ {
3661
Expr::If(next) => {
3662
expr = next;
3663
}
3664
Expr::Block(last) => {
3665
last.to_tokens(tokens);
3666
break;
3667
}
3668
// If this is not one of the valid expressions to exist in
3669
// an else clause, wrap it in a block.
3670
other => {
3671
token::Brace::default().surround(tokens, |tokens| {
3672
print_expr(other, tokens, FixupContext::new_stmt());
3673
});
3674
break;
3675
}
3676
}
3677
}
3678
}
3679
}
3680
3681
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3682
impl ToTokens for ExprIndex {
3683
fn to_tokens(&self, tokens: &mut TokenStream) {
3684
print_expr_index(self, tokens, FixupContext::NONE);
3685
}
3686
}
3687
3688
fn print_expr_index(e: &ExprIndex, tokens: &mut TokenStream, fixup: FixupContext) {
3689
outer_attrs_to_tokens(&e.attrs, tokens);
3690
let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3691
&e.expr,
3692
#[cfg(feature = "full")]
3693
true,
3694
false,
3695
#[cfg(feature = "full")]
3696
Precedence::Unambiguous,
3697
);
3698
print_subexpression(
3699
&e.expr,
3700
left_prec < Precedence::Unambiguous,
3701
tokens,
3702
left_fixup,
3703
);
3704
e.bracket_token.surround(tokens, |tokens| {
3705
e.index.to_tokens(tokens);
3706
});
3707
}
3708
3709
#[cfg(feature = "full")]
3710
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3711
impl ToTokens for ExprInfer {
3712
fn to_tokens(&self, tokens: &mut TokenStream) {
3713
outer_attrs_to_tokens(&self.attrs, tokens);
3714
self.underscore_token.to_tokens(tokens);
3715
}
3716
}
3717
3718
#[cfg(feature = "full")]
3719
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3720
impl ToTokens for ExprLet {
3721
fn to_tokens(&self, tokens: &mut TokenStream) {
3722
print_expr_let(self, tokens, FixupContext::NONE);
3723
}
3724
}
3725
3726
#[cfg(feature = "full")]
3727
fn print_expr_let(e: &ExprLet, tokens: &mut TokenStream, fixup: FixupContext) {
3728
outer_attrs_to_tokens(&e.attrs, tokens);
3729
e.let_token.to_tokens(tokens);
3730
e.pat.to_tokens(tokens);
3731
e.eq_token.to_tokens(tokens);
3732
let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Let);
3733
print_subexpression(&e.expr, right_prec < Precedence::Let, tokens, right_fixup);
3734
}
3735
3736
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3737
impl ToTokens for ExprLit {
3738
fn to_tokens(&self, tokens: &mut TokenStream) {
3739
outer_attrs_to_tokens(&self.attrs, tokens);
3740
self.lit.to_tokens(tokens);
3741
}
3742
}
3743
3744
#[cfg(feature = "full")]
3745
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3746
impl ToTokens for ExprLoop {
3747
fn to_tokens(&self, tokens: &mut TokenStream) {
3748
outer_attrs_to_tokens(&self.attrs, tokens);
3749
self.label.to_tokens(tokens);
3750
self.loop_token.to_tokens(tokens);
3751
self.body.brace_token.surround(tokens, |tokens| {
3752
inner_attrs_to_tokens(&self.attrs, tokens);
3753
tokens.append_all(&self.body.stmts);
3754
});
3755
}
3756
}
3757
3758
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3759
impl ToTokens for ExprMacro {
3760
fn to_tokens(&self, tokens: &mut TokenStream) {
3761
outer_attrs_to_tokens(&self.attrs, tokens);
3762
self.mac.to_tokens(tokens);
3763
}
3764
}
3765
3766
#[cfg(feature = "full")]
3767
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3768
impl ToTokens for ExprMatch {
3769
fn to_tokens(&self, tokens: &mut TokenStream) {
3770
outer_attrs_to_tokens(&self.attrs, tokens);
3771
self.match_token.to_tokens(tokens);
3772
print_expr(&self.expr, tokens, FixupContext::new_condition());
3773
self.brace_token.surround(tokens, |tokens| {
3774
inner_attrs_to_tokens(&self.attrs, tokens);
3775
for (i, arm) in self.arms.iter().enumerate() {
3776
arm.to_tokens(tokens);
3777
// Ensure that we have a comma after a non-block arm, except
3778
// for the last one.
3779
let is_last = i == self.arms.len() - 1;
3780
if !is_last
3781
&& classify::requires_comma_to_be_match_arm(&arm.body)
3782
&& arm.comma.is_none()
3783
{
3784
<Token![,]>::default().to_tokens(tokens);
3785
}
3786
}
3787
});
3788
}
3789
}
3790
3791
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3792
impl ToTokens for ExprMethodCall {
3793
fn to_tokens(&self, tokens: &mut TokenStream) {
3794
print_expr_method_call(self, tokens, FixupContext::NONE);
3795
}
3796
}
3797
3798
fn print_expr_method_call(e: &ExprMethodCall, tokens: &mut TokenStream, fixup: FixupContext) {
3799
outer_attrs_to_tokens(&e.attrs, tokens);
3800
let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.receiver);
3801
print_subexpression(
3802
&e.receiver,
3803
left_prec < Precedence::Unambiguous,
3804
tokens,
3805
left_fixup,
3806
);
3807
e.dot_token.to_tokens(tokens);
3808
e.method.to_tokens(tokens);
3809
if let Some(turbofish) = &e.turbofish {
3810
path::printing::print_angle_bracketed_generic_arguments(
3811
tokens,
3812
turbofish,
3813
PathStyle::Expr,
3814
);
3815
}
3816
e.paren_token.surround(tokens, |tokens| {
3817
e.args.to_tokens(tokens);
3818
});
3819
}
3820
3821
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3822
impl ToTokens for ExprParen {
3823
fn to_tokens(&self, tokens: &mut TokenStream) {
3824
outer_attrs_to_tokens(&self.attrs, tokens);
3825
self.paren_token.surround(tokens, |tokens| {
3826
self.expr.to_tokens(tokens);
3827
});
3828
}
3829
}
3830
3831
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3832
impl ToTokens for ExprPath {
3833
fn to_tokens(&self, tokens: &mut TokenStream) {
3834
outer_attrs_to_tokens(&self.attrs, tokens);
3835
path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3836
}
3837
}
3838
3839
#[cfg(feature = "full")]
3840
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3841
impl ToTokens for ExprRange {
3842
fn to_tokens(&self, tokens: &mut TokenStream) {
3843
print_expr_range(self, tokens, FixupContext::NONE);
3844
}
3845
}
3846
3847
#[cfg(feature = "full")]
3848
fn print_expr_range(e: &ExprRange, tokens: &mut TokenStream, mut fixup: FixupContext) {
3849
outer_attrs_to_tokens(&e.attrs, tokens);
3850
3851
let needs_group = !e.attrs.is_empty();
3852
if needs_group {
3853
fixup = FixupContext::NONE;
3854
}
3855
3856
let do_print_expr = |tokens: &mut TokenStream| {
3857
if let Some(start) = &e.start {
3858
let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3859
start,
3860
true,
3861
false,
3862
Precedence::Range,
3863
);
3864
print_subexpression(start, left_prec <= Precedence::Range, tokens, left_fixup);
3865
}
3866
e.limits.to_tokens(tokens);
3867
if let Some(end) = &e.end {
3868
let right_fixup =
3869
fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
3870
let right_prec = right_fixup.rightmost_subexpression_precedence(end);
3871
print_subexpression(end, right_prec <= Precedence::Range, tokens, right_fixup);
3872
}
3873
};
3874
3875
if needs_group {
3876
token::Paren::default().surround(tokens, do_print_expr);
3877
} else {
3878
do_print_expr(tokens);
3879
}
3880
}
3881
3882
#[cfg(feature = "full")]
3883
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3884
impl ToTokens for ExprRawAddr {
3885
fn to_tokens(&self, tokens: &mut TokenStream) {
3886
print_expr_raw_addr(self, tokens, FixupContext::NONE);
3887
}
3888
}
3889
3890
#[cfg(feature = "full")]
3891
fn print_expr_raw_addr(e: &ExprRawAddr, tokens: &mut TokenStream, fixup: FixupContext) {
3892
outer_attrs_to_tokens(&e.attrs, tokens);
3893
e.and_token.to_tokens(tokens);
3894
e.raw.to_tokens(tokens);
3895
e.mutability.to_tokens(tokens);
3896
let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Prefix);
3897
print_subexpression(
3898
&e.expr,
3899
right_prec < Precedence::Prefix,
3900
tokens,
3901
right_fixup,
3902
);
3903
}
3904
3905
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3906
impl ToTokens for ExprReference {
3907
fn to_tokens(&self, tokens: &mut TokenStream) {
3908
print_expr_reference(self, tokens, FixupContext::NONE);
3909
}
3910
}
3911
3912
fn print_expr_reference(e: &ExprReference, tokens: &mut TokenStream, fixup: FixupContext) {
3913
outer_attrs_to_tokens(&e.attrs, tokens);
3914
e.and_token.to_tokens(tokens);
3915
e.mutability.to_tokens(tokens);
3916
let (right_prec, right_fixup) = fixup.rightmost_subexpression(
3917
&e.expr,
3918
#[cfg(feature = "full")]
3919
Precedence::Prefix,
3920
);
3921
print_subexpression(
3922
&e.expr,
3923
right_prec < Precedence::Prefix,
3924
tokens,
3925
right_fixup,
3926
);
3927
}
3928
3929
#[cfg(feature = "full")]
3930
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3931
impl ToTokens for ExprRepeat {
3932
fn to_tokens(&self, tokens: &mut TokenStream) {
3933
outer_attrs_to_tokens(&self.attrs, tokens);
3934
self.bracket_token.surround(tokens, |tokens| {
3935
self.expr.to_tokens(tokens);
3936
self.semi_token.to_tokens(tokens);
3937
self.len.to_tokens(tokens);
3938
});
3939
}
3940
}
3941
3942
#[cfg(feature = "full")]
3943
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3944
impl ToTokens for ExprReturn {
3945
fn to_tokens(&self, tokens: &mut TokenStream) {
3946
print_expr_return(self, tokens, FixupContext::NONE);
3947
}
3948
}
3949
3950
#[cfg(feature = "full")]
3951
fn print_expr_return(e: &ExprReturn, tokens: &mut TokenStream, fixup: FixupContext) {
3952
outer_attrs_to_tokens(&e.attrs, tokens);
3953
e.return_token.to_tokens(tokens);
3954
if let Some(expr) = &e.expr {
3955
print_expr(
3956
expr,
3957
tokens,
3958
fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
3959
);
3960
}
3961
}
3962
3963
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3964
impl ToTokens for ExprStruct {
3965
fn to_tokens(&self, tokens: &mut TokenStream) {
3966
outer_attrs_to_tokens(&self.attrs, tokens);
3967
path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3968
self.brace_token.surround(tokens, |tokens| {
3969
self.fields.to_tokens(tokens);
3970
if let Some(dot2_token) = &self.dot2_token {
3971
dot2_token.to_tokens(tokens);
3972
} else if self.rest.is_some() {
3973
Token![..](Span::call_site()).to_tokens(tokens);
3974
}
3975
self.rest.to_tokens(tokens);
3976
});
3977
}
3978
}
3979
3980
#[cfg(feature = "full")]
3981
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3982
impl ToTokens for ExprTry {
3983
fn to_tokens(&self, tokens: &mut TokenStream) {
3984
print_expr_try(self, tokens, FixupContext::NONE);
3985
}
3986
}
3987
3988
#[cfg(feature = "full")]
3989
fn print_expr_try(e: &ExprTry, tokens: &mut TokenStream, fixup: FixupContext) {
3990
outer_attrs_to_tokens(&e.attrs, tokens);
3991
let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.expr);
3992
print_subexpression(
3993
&e.expr,
3994
left_prec < Precedence::Unambiguous,
3995
tokens,
3996
left_fixup,
3997
);
3998
e.question_token.to_tokens(tokens);
3999
}
4000
4001
#[cfg(feature = "full")]
4002
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4003
impl ToTokens for ExprTryBlock {
4004
fn to_tokens(&self, tokens: &mut TokenStream) {
4005
outer_attrs_to_tokens(&self.attrs, tokens);
4006
self.try_token.to_tokens(tokens);
4007
self.block.to_tokens(tokens);
4008
}
4009
}
4010
4011
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4012
impl ToTokens for ExprTuple {
4013
fn to_tokens(&self, tokens: &mut TokenStream) {
4014
outer_attrs_to_tokens(&self.attrs, tokens);
4015
self.paren_token.surround(tokens, |tokens| {
4016
self.elems.to_tokens(tokens);
4017
// If we only have one argument, we need a trailing comma to
4018
// distinguish ExprTuple from ExprParen.
4019
if self.elems.len() == 1 && !self.elems.trailing_punct() {
4020
<Token![,]>::default().to_tokens(tokens);
4021
}
4022
});
4023
}
4024
}
4025
4026
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4027
impl ToTokens for ExprUnary {
4028
fn to_tokens(&self, tokens: &mut TokenStream) {
4029
print_expr_unary(self, tokens, FixupContext::NONE);
4030
}
4031
}
4032
4033
fn print_expr_unary(e: &ExprUnary, tokens: &mut TokenStream, fixup: FixupContext) {
4034
outer_attrs_to_tokens(&e.attrs, tokens);
4035
e.op.to_tokens(tokens);
4036
let (right_prec, right_fixup) = fixup.rightmost_subexpression(
4037
&e.expr,
4038
#[cfg(feature = "full")]
4039
Precedence::Prefix,
4040
);
4041
print_subexpression(
4042
&e.expr,
4043
right_prec < Precedence::Prefix,
4044
tokens,
4045
right_fixup,
4046
);
4047
}
4048
4049
#[cfg(feature = "full")]
4050
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4051
impl ToTokens for ExprUnsafe {
4052
fn to_tokens(&self, tokens: &mut TokenStream) {
4053
outer_attrs_to_tokens(&self.attrs, tokens);
4054
self.unsafe_token.to_tokens(tokens);
4055
self.block.brace_token.surround(tokens, |tokens| {
4056
inner_attrs_to_tokens(&self.attrs, tokens);
4057
tokens.append_all(&self.block.stmts);
4058
});
4059
}
4060
}
4061
4062
#[cfg(feature = "full")]
4063
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4064
impl ToTokens for ExprWhile {
4065
fn to_tokens(&self, tokens: &mut TokenStream) {
4066
outer_attrs_to_tokens(&self.attrs, tokens);
4067
self.label.to_tokens(tokens);
4068
self.while_token.to_tokens(tokens);
4069
print_expr(&self.cond, tokens, FixupContext::new_condition());
4070
self.body.brace_token.surround(tokens, |tokens| {
4071
inner_attrs_to_tokens(&self.attrs, tokens);
4072
tokens.append_all(&self.body.stmts);
4073
});
4074
}
4075
}
4076
4077
#[cfg(feature = "full")]
4078
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4079
impl ToTokens for ExprYield {
4080
fn to_tokens(&self, tokens: &mut TokenStream) {
4081
print_expr_yield(self, tokens, FixupContext::NONE);
4082
}
4083
}
4084
4085
#[cfg(feature = "full")]
4086
fn print_expr_yield(e: &ExprYield, tokens: &mut TokenStream, fixup: FixupContext) {
4087
outer_attrs_to_tokens(&e.attrs, tokens);
4088
e.yield_token.to_tokens(tokens);
4089
if let Some(expr) = &e.expr {
4090
print_expr(
4091
expr,
4092
tokens,
4093
fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
4094
);
4095
}
4096
}
4097
4098
#[cfg(feature = "full")]
4099
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4100
impl ToTokens for Arm {
4101
fn to_tokens(&self, tokens: &mut TokenStream) {
4102
tokens.append_all(&self.attrs);
4103
self.pat.to_tokens(tokens);
4104
if let Some((if_token, guard)) = &self.guard {
4105
if_token.to_tokens(tokens);
4106
guard.to_tokens(tokens);
4107
}
4108
self.fat_arrow_token.to_tokens(tokens);
4109
print_expr(&self.body, tokens, FixupContext::new_match_arm());
4110
self.comma.to_tokens(tokens);
4111
}
4112
}
4113
4114
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4115
impl ToTokens for FieldValue {
4116
fn to_tokens(&self, tokens: &mut TokenStream) {
4117
outer_attrs_to_tokens(&self.attrs, tokens);
4118
self.member.to_tokens(tokens);
4119
if let Some(colon_token) = &self.colon_token {
4120
colon_token.to_tokens(tokens);
4121
self.expr.to_tokens(tokens);
4122
}
4123
}
4124
}
4125
4126
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4127
impl ToTokens for Index {
4128
fn to_tokens(&self, tokens: &mut TokenStream) {
4129
let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
4130
lit.set_span(self.span);
4131
tokens.append(lit);
4132
}
4133
}
4134
4135
#[cfg(feature = "full")]
4136
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4137
impl ToTokens for Label {
4138
fn to_tokens(&self, tokens: &mut TokenStream) {
4139
self.name.to_tokens(tokens);
4140
self.colon_token.to_tokens(tokens);
4141
}
4142
}
4143
4144
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4145
impl ToTokens for Member {
4146
fn to_tokens(&self, tokens: &mut TokenStream) {
4147
match self {
4148
Member::Named(ident) => ident.to_tokens(tokens),
4149
Member::Unnamed(index) => index.to_tokens(tokens),
4150
}
4151
}
4152
}
4153
4154
#[cfg(feature = "full")]
4155
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4156
impl ToTokens for RangeLimits {
4157
fn to_tokens(&self, tokens: &mut TokenStream) {
4158
match self {
4159
RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
4160
RangeLimits::Closed(t) => t.to_tokens(tokens),
4161
}
4162
}
4163
}
4164
4165
#[cfg(feature = "full")]
4166
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4167
impl ToTokens for PointerMutability {
4168
fn to_tokens(&self, tokens: &mut TokenStream) {
4169
match self {
4170
PointerMutability::Const(const_token) => const_token.to_tokens(tokens),
4171
PointerMutability::Mut(mut_token) => mut_token.to_tokens(tokens),
4172
}
4173
}
4174
}
4175
}
4176
4177