prettyplease/
expr.rs

1use crate::algorithm::{BreakToken, Printer};
2use crate::attr;
3use crate::classify;
4use crate::fixup::FixupContext;
5use crate::iter::IterDelimited;
6use crate::path::PathKind;
7use crate::precedence::Precedence;
8use crate::stmt;
9use crate::INDENT;
10use proc_macro2::TokenStream;
11use syn::punctuated::Punctuated;
12use syn::{
13    token, Arm, Attribute, BinOp, Block, Expr, ExprArray, ExprAssign, ExprAsync, ExprAwait,
14    ExprBinary, ExprBlock, ExprBreak, ExprCall, ExprCast, ExprClosure, ExprConst, ExprContinue,
15    ExprField, ExprForLoop, ExprGroup, ExprIf, ExprIndex, ExprInfer, ExprLet, ExprLit, ExprLoop,
16    ExprMacro, ExprMatch, ExprMethodCall, ExprParen, ExprPath, ExprRange, ExprRawAddr,
17    ExprReference, ExprRepeat, ExprReturn, ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprUnary,
18    ExprUnsafe, ExprWhile, ExprYield, FieldValue, Index, Label, Lit, Member, PointerMutability,
19    RangeLimits, ReturnType, Stmt, Token, UnOp,
20};
21
22impl Printer {
23    pub fn expr(&mut self, expr: &Expr, mut fixup: FixupContext) {
24        let needs_paren = fixup.parenthesize(expr);
25        if needs_paren {
26            self.word("(");
27            fixup = FixupContext::NONE;
28        }
29
30        let beginning_of_line = false;
31
32        match expr {
33            #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
34            Expr::Array(expr) => self.expr_array(expr),
35            Expr::Assign(expr) => self.expr_assign(expr, fixup),
36            Expr::Async(expr) => self.expr_async(expr),
37            Expr::Await(expr) => self.expr_await(expr, beginning_of_line, fixup),
38            Expr::Binary(expr) => self.expr_binary(expr, fixup),
39            Expr::Block(expr) => self.expr_block(expr),
40            Expr::Break(expr) => self.expr_break(expr, fixup),
41            Expr::Call(expr) => self.expr_call(expr, beginning_of_line, fixup),
42            Expr::Cast(expr) => self.expr_cast(expr, fixup),
43            Expr::Closure(expr) => self.expr_closure(expr, fixup),
44            Expr::Const(expr) => self.expr_const(expr),
45            Expr::Continue(expr) => self.expr_continue(expr),
46            Expr::Field(expr) => self.expr_field(expr, beginning_of_line, fixup),
47            Expr::ForLoop(expr) => self.expr_for_loop(expr),
48            Expr::Group(expr) => self.expr_group(expr, fixup),
49            Expr::If(expr) => self.expr_if(expr),
50            Expr::Index(expr) => self.expr_index(expr, beginning_of_line, fixup),
51            Expr::Infer(expr) => self.expr_infer(expr),
52            Expr::Let(expr) => self.expr_let(expr, fixup),
53            Expr::Lit(expr) => self.expr_lit(expr),
54            Expr::Loop(expr) => self.expr_loop(expr),
55            Expr::Macro(expr) => self.expr_macro(expr),
56            Expr::Match(expr) => self.expr_match(expr),
57            Expr::MethodCall(expr) => self.expr_method_call(expr, beginning_of_line, fixup),
58            Expr::Paren(expr) => self.expr_paren(expr),
59            Expr::Path(expr) => self.expr_path(expr),
60            Expr::Range(expr) => self.expr_range(expr, fixup),
61            Expr::RawAddr(expr) => self.expr_raw_addr(expr, fixup),
62            Expr::Reference(expr) => self.expr_reference(expr, fixup),
63            Expr::Repeat(expr) => self.expr_repeat(expr),
64            Expr::Return(expr) => self.expr_return(expr, fixup),
65            Expr::Struct(expr) => self.expr_struct(expr),
66            Expr::Try(expr) => self.expr_try(expr, beginning_of_line, fixup),
67            Expr::TryBlock(expr) => self.expr_try_block(expr),
68            Expr::Tuple(expr) => self.expr_tuple(expr),
69            Expr::Unary(expr) => self.expr_unary(expr, fixup),
70            Expr::Unsafe(expr) => self.expr_unsafe(expr),
71            Expr::Verbatim(expr) => self.expr_verbatim(expr, fixup),
72            Expr::While(expr) => self.expr_while(expr),
73            Expr::Yield(expr) => self.expr_yield(expr, fixup),
74            _ => unimplemented!("unknown Expr"),
75        }
76
77        if needs_paren {
78            self.word(")");
79        }
80    }
81
82    pub fn expr_beginning_of_line(
83        &mut self,
84        expr: &Expr,
85        mut needs_paren: bool,
86        beginning_of_line: bool,
87        mut fixup: FixupContext,
88    ) {
89        needs_paren |= fixup.parenthesize(expr);
90        if needs_paren {
91            self.word("(");
92            fixup = FixupContext::NONE;
93        }
94
95        match expr {
96            Expr::Await(expr) => self.expr_await(expr, beginning_of_line, fixup),
97            Expr::Field(expr) => self.expr_field(expr, beginning_of_line, fixup),
98            Expr::Index(expr) => self.expr_index(expr, beginning_of_line, fixup),
99            Expr::MethodCall(expr) => self.expr_method_call(expr, beginning_of_line, fixup),
100            Expr::Try(expr) => self.expr_try(expr, beginning_of_line, fixup),
101            _ => self.expr(expr, fixup),
102        }
103
104        if needs_paren {
105            self.word(")");
106        }
107    }
108
109    fn prefix_subexpr(
110        &mut self,
111        expr: &Expr,
112        mut needs_paren: bool,
113        beginning_of_line: bool,
114        mut fixup: FixupContext,
115    ) {
116        needs_paren |= fixup.parenthesize(expr);
117        if needs_paren {
118            self.word("(");
119            fixup = FixupContext::NONE;
120        }
121
122        match expr {
123            Expr::Await(expr) => self.prefix_subexpr_await(expr, beginning_of_line, fixup),
124            Expr::Call(expr) => self.prefix_subexpr_call(expr, fixup),
125            Expr::Field(expr) => self.prefix_subexpr_field(expr, beginning_of_line, fixup),
126            Expr::Index(expr) => self.prefix_subexpr_index(expr, beginning_of_line, fixup),
127            Expr::MethodCall(expr) => {
128                let unindent_call_args = false;
129                self.prefix_subexpr_method_call(expr, beginning_of_line, unindent_call_args, fixup);
130            }
131            Expr::Try(expr) => self.prefix_subexpr_try(expr, beginning_of_line, fixup),
132            _ => {
133                self.cbox(-INDENT);
134                self.expr(expr, fixup);
135                self.end();
136            }
137        }
138
139        if needs_paren {
140            self.word(")");
141        }
142    }
143
144    fn expr_condition(&mut self, expr: &Expr) {
145        self.cbox(0);
146        self.expr(expr, FixupContext::new_condition());
147        if needs_newline_if_wrap(expr) {
148            self.space();
149        } else {
150            self.nbsp();
151        }
152        self.end();
153    }
154
155    pub fn subexpr(&mut self, expr: &Expr, needs_paren: bool, mut fixup: FixupContext) {
156        if needs_paren {
157            self.word("(");
158            fixup = FixupContext::NONE;
159        }
160
161        self.expr(expr, fixup);
162
163        if needs_paren {
164            self.word(")");
165        }
166    }
167
168    fn expr_array(&mut self, expr: &ExprArray) {
169        self.outer_attrs(&expr.attrs);
170        if expr.elems.is_empty() {
171            self.word("[]");
172        } else if simple_array(&expr.elems) {
173            self.cbox(INDENT);
174            self.word("[");
175            self.zerobreak();
176            self.ibox(0);
177            for elem in expr.elems.iter().delimited() {
178                self.expr(&elem, FixupContext::NONE);
179                if !elem.is_last {
180                    self.word(",");
181                    self.space();
182                }
183            }
184            self.end();
185            self.trailing_comma(true);
186            self.offset(-INDENT);
187            self.word("]");
188            self.end();
189        } else {
190            self.word("[");
191            self.cbox(INDENT);
192            self.zerobreak();
193            for elem in expr.elems.iter().delimited() {
194                self.expr(&elem, FixupContext::NONE);
195                self.trailing_comma(elem.is_last);
196            }
197            self.offset(-INDENT);
198            self.end();
199            self.word("]");
200        }
201    }
202
203    fn expr_assign(&mut self, expr: &ExprAssign, fixup: FixupContext) {
204        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
205            &expr.left,
206            false,
207            false,
208            Precedence::Assign,
209        );
210        let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign);
211
212        self.outer_attrs(&expr.attrs);
213        self.ibox(0);
214        if !expr.attrs.is_empty() {
215            self.word("(");
216        }
217        self.subexpr(&expr.left, left_prec <= Precedence::Range, left_fixup);
218        self.word(" = ");
219        self.neverbreak();
220        self.expr(&expr.right, right_fixup);
221        if !expr.attrs.is_empty() {
222            self.word(")");
223        }
224        self.end();
225    }
226
227    fn expr_async(&mut self, expr: &ExprAsync) {
228        self.outer_attrs(&expr.attrs);
229        self.word("async ");
230        if expr.capture.is_some() {
231            self.word("move ");
232        }
233        self.cbox(INDENT);
234        self.small_block(&expr.block, &expr.attrs);
235        self.end();
236    }
237
238    fn expr_await(&mut self, expr: &ExprAwait, beginning_of_line: bool, fixup: FixupContext) {
239        self.outer_attrs(&expr.attrs);
240        self.cbox(INDENT);
241        self.prefix_subexpr_await(expr, beginning_of_line, fixup);
242        self.end();
243    }
244
245    fn prefix_subexpr_await(
246        &mut self,
247        expr: &ExprAwait,
248        beginning_of_line: bool,
249        fixup: FixupContext,
250    ) {
251        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.base);
252
253        self.prefix_subexpr(
254            &expr.base,
255            left_prec < Precedence::Unambiguous,
256            beginning_of_line,
257            left_fixup,
258        );
259        if !(beginning_of_line && is_short_ident(&expr.base)) {
260            self.scan_break(BreakToken {
261                no_break: self.ends_with('.').then_some(' '),
262                ..BreakToken::default()
263            });
264        }
265        self.word(".await");
266    }
267
268    fn expr_binary(&mut self, expr: &ExprBinary, fixup: FixupContext) {
269        let binop_prec = Precedence::of_binop(&expr.op);
270        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
271            &expr.left,
272            match &expr.op {
273                BinOp::Sub(_)
274                | BinOp::Mul(_)
275                | BinOp::And(_)
276                | BinOp::Or(_)
277                | BinOp::BitAnd(_)
278                | BinOp::BitOr(_)
279                | BinOp::Shl(_)
280                | BinOp::Lt(_) => true,
281                _ => false,
282            },
283            match &expr.op {
284                BinOp::Shl(_) | BinOp::Lt(_) => true,
285                _ => false,
286            },
287            binop_prec,
288        );
289        let left_needs_group = match binop_prec {
290            Precedence::Assign => left_prec <= Precedence::Range,
291            Precedence::Compare => left_prec <= binop_prec,
292            _ => left_prec < binop_prec,
293        };
294        let right_fixup = fixup.rightmost_subexpression_fixup(false, false, binop_prec);
295        let right_needs_group = binop_prec != Precedence::Assign
296            && right_fixup.rightmost_subexpression_precedence(&expr.right) <= binop_prec;
297
298        self.outer_attrs(&expr.attrs);
299        self.ibox(INDENT);
300        self.ibox(-INDENT);
301        if !expr.attrs.is_empty() {
302            self.word("(");
303        }
304        self.subexpr(&expr.left, left_needs_group, left_fixup);
305        self.end();
306        self.space();
307        self.binary_operator(&expr.op);
308        self.nbsp();
309        self.subexpr(&expr.right, right_needs_group, right_fixup);
310        if !expr.attrs.is_empty() {
311            self.word(")");
312        }
313        self.end();
314    }
315
316    pub fn expr_block(&mut self, expr: &ExprBlock) {
317        self.outer_attrs(&expr.attrs);
318        if let Some(label) = &expr.label {
319            self.label(label);
320        }
321        self.cbox(INDENT);
322        self.small_block(&expr.block, &expr.attrs);
323        self.end();
324    }
325
326    fn expr_break(&mut self, expr: &ExprBreak, fixup: FixupContext) {
327        self.outer_attrs(&expr.attrs);
328        self.word("break");
329        if let Some(lifetime) = &expr.label {
330            self.nbsp();
331            self.lifetime(lifetime);
332        }
333        if let Some(value) = &expr.expr {
334            self.nbsp();
335            self.subexpr(
336                value,
337                expr.label.is_none() && classify::expr_leading_label(value),
338                fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump),
339            );
340        }
341    }
342
343    fn expr_call(&mut self, expr: &ExprCall, beginning_of_line: bool, fixup: FixupContext) {
344        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
345            &expr.func,
346            true,
347            false,
348            Precedence::Unambiguous,
349        );
350        let needs_paren = if let Expr::Field(func) = &*expr.func {
351            matches!(func.member, Member::Named(_))
352        } else {
353            left_prec < Precedence::Unambiguous
354        };
355
356        self.outer_attrs(&expr.attrs);
357        self.expr_beginning_of_line(&expr.func, needs_paren, beginning_of_line, left_fixup);
358        self.word("(");
359        self.call_args(&expr.args);
360        self.word(")");
361    }
362
363    fn prefix_subexpr_call(&mut self, expr: &ExprCall, fixup: FixupContext) {
364        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
365            &expr.func,
366            true,
367            false,
368            Precedence::Unambiguous,
369        );
370        let needs_paren = if let Expr::Field(func) = &*expr.func {
371            matches!(func.member, Member::Named(_))
372        } else {
373            left_prec < Precedence::Unambiguous
374        };
375
376        let beginning_of_line = false;
377        self.prefix_subexpr(&expr.func, needs_paren, beginning_of_line, left_fixup);
378        self.word("(");
379        self.call_args(&expr.args);
380        self.word(")");
381    }
382
383    fn expr_cast(&mut self, expr: &ExprCast, fixup: FixupContext) {
384        let (left_prec, left_fixup) =
385            fixup.leftmost_subexpression_with_operator(&expr.expr, false, false, Precedence::Cast);
386
387        self.outer_attrs(&expr.attrs);
388        self.ibox(INDENT);
389        self.ibox(-INDENT);
390        if !expr.attrs.is_empty() {
391            self.word("(");
392        }
393        self.subexpr(&expr.expr, left_prec < Precedence::Cast, left_fixup);
394        self.end();
395        self.space();
396        self.word("as ");
397        self.ty(&expr.ty);
398        if !expr.attrs.is_empty() {
399            self.word(")");
400        }
401        self.end();
402    }
403
404    fn expr_closure(&mut self, expr: &ExprClosure, fixup: FixupContext) {
405        self.outer_attrs(&expr.attrs);
406        self.ibox(0);
407        if let Some(bound_lifetimes) = &expr.lifetimes {
408            self.bound_lifetimes(bound_lifetimes);
409        }
410        if expr.constness.is_some() {
411            self.word("const ");
412        }
413        if expr.movability.is_some() {
414            self.word("static ");
415        }
416        if expr.asyncness.is_some() {
417            self.word("async ");
418        }
419        if expr.capture.is_some() {
420            self.word("move ");
421        }
422        self.cbox(INDENT);
423        self.word("|");
424        for pat in expr.inputs.iter().delimited() {
425            if pat.is_first {
426                self.zerobreak();
427            }
428            self.pat(&pat);
429            if !pat.is_last {
430                self.word(",");
431                self.space();
432            }
433        }
434        match &expr.output {
435            ReturnType::Default => {
436                self.word("|");
437                self.space();
438                self.offset(-INDENT);
439                self.end();
440                self.neverbreak();
441                let wrap_in_brace = match &*expr.body {
442                    Expr::Match(ExprMatch { attrs, .. }) | Expr::Call(ExprCall { attrs, .. }) => {
443                        attr::has_outer(attrs)
444                    }
445                    body => !is_blocklike(body),
446                };
447                if wrap_in_brace {
448                    self.cbox(INDENT);
449                    let okay_to_brace = parseable_as_stmt(&expr.body);
450                    self.scan_break(BreakToken {
451                        pre_break: Some(if okay_to_brace { '{' } else { '(' }),
452                        ..BreakToken::default()
453                    });
454                    self.expr(
455                        &expr.body,
456                        fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
457                    );
458                    self.scan_break(BreakToken {
459                        offset: -INDENT,
460                        pre_break: (okay_to_brace && stmt::add_semi(&expr.body)).then_some(';'),
461                        post_break: if okay_to_brace { "}" } else { ")" },
462                        ..BreakToken::default()
463                    });
464                    self.end();
465                } else {
466                    self.expr(
467                        &expr.body,
468                        fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
469                    );
470                }
471            }
472            ReturnType::Type(_arrow, ty) => {
473                if !expr.inputs.is_empty() {
474                    self.trailing_comma(true);
475                    self.offset(-INDENT);
476                }
477                self.word("|");
478                self.end();
479                self.word(" -> ");
480                self.ty(ty);
481                self.nbsp();
482                self.neverbreak();
483                if matches!(&*expr.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
484                {
485                    self.expr(
486                        &expr.body,
487                        fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
488                    );
489                } else {
490                    self.cbox(INDENT);
491                    self.expr_as_small_block(&expr.body, 0);
492                    self.end();
493                }
494            }
495        }
496        self.end();
497    }
498
499    pub fn expr_const(&mut self, expr: &ExprConst) {
500        self.outer_attrs(&expr.attrs);
501        self.word("const ");
502        self.cbox(INDENT);
503        self.small_block(&expr.block, &expr.attrs);
504        self.end();
505    }
506
507    fn expr_continue(&mut self, expr: &ExprContinue) {
508        self.outer_attrs(&expr.attrs);
509        self.word("continue");
510        if let Some(lifetime) = &expr.label {
511            self.nbsp();
512            self.lifetime(lifetime);
513        }
514    }
515
516    fn expr_field(&mut self, expr: &ExprField, beginning_of_line: bool, fixup: FixupContext) {
517        self.outer_attrs(&expr.attrs);
518        self.cbox(INDENT);
519        self.prefix_subexpr_field(expr, beginning_of_line, fixup);
520        self.end();
521    }
522
523    fn prefix_subexpr_field(
524        &mut self,
525        expr: &ExprField,
526        beginning_of_line: bool,
527        fixup: FixupContext,
528    ) {
529        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.base);
530
531        self.prefix_subexpr(
532            &expr.base,
533            left_prec < Precedence::Unambiguous,
534            beginning_of_line,
535            left_fixup,
536        );
537        if !(beginning_of_line && is_short_ident(&expr.base)) {
538            self.scan_break(BreakToken {
539                no_break: self.ends_with('.').then_some(' '),
540                ..BreakToken::default()
541            });
542        }
543        self.word(".");
544        self.member(&expr.member);
545    }
546
547    fn expr_for_loop(&mut self, expr: &ExprForLoop) {
548        self.outer_attrs(&expr.attrs);
549        self.ibox(0);
550        if let Some(label) = &expr.label {
551            self.label(label);
552        }
553        self.word("for ");
554        self.pat(&expr.pat);
555        self.word(" in ");
556        self.neverbreak();
557        self.expr_condition(&expr.expr);
558        self.word("{");
559        self.neverbreak();
560        self.cbox(INDENT);
561        self.hardbreak_if_nonempty();
562        self.inner_attrs(&expr.attrs);
563        for stmt in expr.body.stmts.iter().delimited() {
564            self.stmt(&stmt, stmt.is_last);
565        }
566        self.offset(-INDENT);
567        self.end();
568        self.word("}");
569        self.end();
570    }
571
572    fn expr_group(&mut self, expr: &ExprGroup, fixup: FixupContext) {
573        self.outer_attrs(&expr.attrs);
574        self.expr(&expr.expr, fixup);
575    }
576
577    fn expr_if(&mut self, expr: &ExprIf) {
578        self.outer_attrs(&expr.attrs);
579        self.cbox(INDENT);
580        self.word("if ");
581        self.cbox(-INDENT);
582        self.expr_condition(&expr.cond);
583        self.end();
584        if let Some((_else_token, else_branch)) = &expr.else_branch {
585            let mut else_branch = &**else_branch;
586            self.small_block(&expr.then_branch, &[]);
587            loop {
588                self.word(" else ");
589                match else_branch {
590                    Expr::If(expr) => {
591                        self.word("if ");
592                        self.cbox(-INDENT);
593                        self.expr_condition(&expr.cond);
594                        self.end();
595                        self.small_block(&expr.then_branch, &[]);
596                        if let Some((_else_token, next)) = &expr.else_branch {
597                            else_branch = next;
598                            continue;
599                        }
600                    }
601                    Expr::Block(expr) => {
602                        self.small_block(&expr.block, &[]);
603                    }
604                    // If not one of the valid expressions to exist in an else
605                    // clause, wrap in a block.
606                    other => self.expr_as_small_block(other, INDENT),
607                }
608                break;
609            }
610        } else if expr.then_branch.stmts.is_empty() {
611            self.word("{}");
612        } else {
613            self.word("{");
614            self.hardbreak();
615            for stmt in expr.then_branch.stmts.iter().delimited() {
616                self.stmt(&stmt, stmt.is_last);
617            }
618            self.offset(-INDENT);
619            self.word("}");
620        }
621        self.end();
622    }
623
624    fn expr_index(&mut self, expr: &ExprIndex, beginning_of_line: bool, fixup: FixupContext) {
625        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
626            &expr.expr,
627            true,
628            false,
629            Precedence::Unambiguous,
630        );
631
632        self.outer_attrs(&expr.attrs);
633        self.expr_beginning_of_line(
634            &expr.expr,
635            left_prec < Precedence::Unambiguous,
636            beginning_of_line,
637            left_fixup,
638        );
639        self.word("[");
640        self.expr(&expr.index, FixupContext::NONE);
641        self.word("]");
642    }
643
644    fn prefix_subexpr_index(
645        &mut self,
646        expr: &ExprIndex,
647        beginning_of_line: bool,
648        fixup: FixupContext,
649    ) {
650        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
651            &expr.expr,
652            true,
653            false,
654            Precedence::Unambiguous,
655        );
656
657        self.prefix_subexpr(
658            &expr.expr,
659            left_prec < Precedence::Unambiguous,
660            beginning_of_line,
661            left_fixup,
662        );
663        self.word("[");
664        self.expr(&expr.index, FixupContext::NONE);
665        self.word("]");
666    }
667
668    fn expr_infer(&mut self, expr: &ExprInfer) {
669        self.outer_attrs(&expr.attrs);
670        self.word("_");
671    }
672
673    fn expr_let(&mut self, expr: &ExprLet, fixup: FixupContext) {
674        let (right_prec, right_fixup) = fixup.rightmost_subexpression(&expr.expr, Precedence::Let);
675
676        self.outer_attrs(&expr.attrs);
677        self.ibox(0);
678        self.word("let ");
679        self.ibox(0);
680        self.pat(&expr.pat);
681        self.end();
682        self.word(" = ");
683        self.neverbreak();
684        self.ibox(0);
685        self.subexpr(&expr.expr, right_prec < Precedence::Let, right_fixup);
686        self.end();
687        self.end();
688    }
689
690    pub fn expr_lit(&mut self, expr: &ExprLit) {
691        self.outer_attrs(&expr.attrs);
692        self.lit(&expr.lit);
693    }
694
695    fn expr_loop(&mut self, expr: &ExprLoop) {
696        self.outer_attrs(&expr.attrs);
697        if let Some(label) = &expr.label {
698            self.label(label);
699        }
700        self.word("loop {");
701        self.cbox(INDENT);
702        self.hardbreak_if_nonempty();
703        self.inner_attrs(&expr.attrs);
704        for stmt in expr.body.stmts.iter().delimited() {
705            self.stmt(&stmt, stmt.is_last);
706        }
707        self.offset(-INDENT);
708        self.end();
709        self.word("}");
710    }
711
712    pub fn expr_macro(&mut self, expr: &ExprMacro) {
713        self.outer_attrs(&expr.attrs);
714        let semicolon = false;
715        self.mac(&expr.mac, None, semicolon);
716    }
717
718    fn expr_match(&mut self, expr: &ExprMatch) {
719        self.outer_attrs(&expr.attrs);
720        self.ibox(0);
721        self.word("match ");
722        self.expr_condition(&expr.expr);
723        self.word("{");
724        self.neverbreak();
725        self.cbox(INDENT);
726        self.hardbreak_if_nonempty();
727        self.inner_attrs(&expr.attrs);
728        for arm in &expr.arms {
729            self.arm(arm);
730            self.hardbreak();
731        }
732        self.offset(-INDENT);
733        self.end();
734        self.word("}");
735        self.end();
736    }
737
738    fn expr_method_call(
739        &mut self,
740        expr: &ExprMethodCall,
741        beginning_of_line: bool,
742        fixup: FixupContext,
743    ) {
744        self.outer_attrs(&expr.attrs);
745        self.cbox(INDENT);
746        let unindent_call_args = beginning_of_line && is_short_ident(&expr.receiver);
747        self.prefix_subexpr_method_call(expr, beginning_of_line, unindent_call_args, fixup);
748        self.end();
749    }
750
751    fn prefix_subexpr_method_call(
752        &mut self,
753        expr: &ExprMethodCall,
754        beginning_of_line: bool,
755        unindent_call_args: bool,
756        fixup: FixupContext,
757    ) {
758        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.receiver);
759
760        self.prefix_subexpr(
761            &expr.receiver,
762            left_prec < Precedence::Unambiguous,
763            beginning_of_line,
764            left_fixup,
765        );
766        if !(beginning_of_line && is_short_ident(&expr.receiver)) {
767            self.scan_break(BreakToken {
768                no_break: self.ends_with('.').then_some(' '),
769                ..BreakToken::default()
770            });
771        }
772        self.word(".");
773        self.ident(&expr.method);
774        if let Some(turbofish) = &expr.turbofish {
775            self.angle_bracketed_generic_arguments(turbofish, PathKind::Expr);
776        }
777        self.cbox(if unindent_call_args { -INDENT } else { 0 });
778        self.word("(");
779        self.call_args(&expr.args);
780        self.word(")");
781        self.end();
782    }
783
784    fn expr_paren(&mut self, expr: &ExprParen) {
785        self.outer_attrs(&expr.attrs);
786        self.word("(");
787        self.expr(&expr.expr, FixupContext::NONE);
788        self.word(")");
789    }
790
791    pub fn expr_path(&mut self, expr: &ExprPath) {
792        self.outer_attrs(&expr.attrs);
793        self.qpath(&expr.qself, &expr.path, PathKind::Expr);
794    }
795
796    pub fn expr_range(&mut self, expr: &ExprRange, fixup: FixupContext) {
797        self.outer_attrs(&expr.attrs);
798        if !expr.attrs.is_empty() {
799            self.word("(");
800        }
801        if let Some(start) = &expr.start {
802            let (left_prec, left_fixup) =
803                fixup.leftmost_subexpression_with_operator(start, true, false, Precedence::Range);
804            self.subexpr(start, left_prec <= Precedence::Range, left_fixup);
805        } else if self.ends_with('.') {
806            self.nbsp();
807        }
808        self.word(match expr.limits {
809            RangeLimits::HalfOpen(_) => "..",
810            RangeLimits::Closed(_) => "..=",
811        });
812        if let Some(end) = &expr.end {
813            let right_fixup = fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
814            let right_prec = right_fixup.rightmost_subexpression_precedence(end);
815            self.subexpr(end, right_prec <= Precedence::Range, right_fixup);
816        }
817        if !expr.attrs.is_empty() {
818            self.word(")");
819        }
820    }
821
822    fn expr_raw_addr(&mut self, expr: &ExprRawAddr, fixup: FixupContext) {
823        let (right_prec, right_fixup) =
824            fixup.rightmost_subexpression(&expr.expr, Precedence::Prefix);
825
826        self.outer_attrs(&expr.attrs);
827        self.word("&raw ");
828        self.pointer_mutability(&expr.mutability);
829        self.nbsp();
830        self.subexpr(&expr.expr, right_prec < Precedence::Prefix, right_fixup);
831    }
832
833    fn expr_reference(&mut self, expr: &ExprReference, fixup: FixupContext) {
834        let (right_prec, right_fixup) =
835            fixup.rightmost_subexpression(&expr.expr, Precedence::Prefix);
836
837        self.outer_attrs(&expr.attrs);
838        self.word("&");
839        if expr.mutability.is_some() {
840            self.word("mut ");
841        }
842        self.subexpr(&expr.expr, right_prec < Precedence::Prefix, right_fixup);
843    }
844
845    fn expr_repeat(&mut self, expr: &ExprRepeat) {
846        self.outer_attrs(&expr.attrs);
847        self.word("[");
848        self.expr(&expr.expr, FixupContext::NONE);
849        self.word("; ");
850        self.expr(&expr.len, FixupContext::NONE);
851        self.word("]");
852    }
853
854    fn expr_return(&mut self, expr: &ExprReturn, fixup: FixupContext) {
855        self.outer_attrs(&expr.attrs);
856        self.word("return");
857        if let Some(value) = &expr.expr {
858            self.nbsp();
859            self.expr(
860                value,
861                fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
862            );
863        }
864    }
865
866    fn expr_struct(&mut self, expr: &ExprStruct) {
867        self.outer_attrs(&expr.attrs);
868        self.cbox(INDENT);
869        self.ibox(-INDENT);
870        self.qpath(&expr.qself, &expr.path, PathKind::Expr);
871        self.end();
872        self.word(" {");
873        self.space_if_nonempty();
874        for field_value in expr.fields.iter().delimited() {
875            self.field_value(&field_value);
876            self.trailing_comma_or_space(field_value.is_last && expr.rest.is_none());
877        }
878        if let Some(rest) = &expr.rest {
879            self.word("..");
880            self.expr(rest, FixupContext::NONE);
881            self.space();
882        }
883        self.offset(-INDENT);
884        self.end_with_max_width(34);
885        self.word("}");
886    }
887
888    fn expr_try(&mut self, expr: &ExprTry, beginning_of_line: bool, fixup: FixupContext) {
889        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.expr);
890
891        self.outer_attrs(&expr.attrs);
892        self.expr_beginning_of_line(
893            &expr.expr,
894            left_prec < Precedence::Unambiguous,
895            beginning_of_line,
896            left_fixup,
897        );
898        self.word("?");
899    }
900
901    fn prefix_subexpr_try(&mut self, expr: &ExprTry, beginning_of_line: bool, fixup: FixupContext) {
902        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.expr);
903
904        self.prefix_subexpr(
905            &expr.expr,
906            left_prec < Precedence::Unambiguous,
907            beginning_of_line,
908            left_fixup,
909        );
910        self.word("?");
911    }
912
913    fn expr_try_block(&mut self, expr: &ExprTryBlock) {
914        self.outer_attrs(&expr.attrs);
915        self.word("try ");
916        self.cbox(INDENT);
917        self.small_block(&expr.block, &expr.attrs);
918        self.end();
919    }
920
921    fn expr_tuple(&mut self, expr: &ExprTuple) {
922        self.outer_attrs(&expr.attrs);
923        self.word("(");
924        self.cbox(INDENT);
925        self.zerobreak();
926        for elem in expr.elems.iter().delimited() {
927            self.expr(&elem, FixupContext::NONE);
928            if expr.elems.len() == 1 {
929                self.word(",");
930                self.zerobreak();
931            } else {
932                self.trailing_comma(elem.is_last);
933            }
934        }
935        self.offset(-INDENT);
936        self.end();
937        self.word(")");
938    }
939
940    fn expr_unary(&mut self, expr: &ExprUnary, fixup: FixupContext) {
941        let (right_prec, right_fixup) =
942            fixup.rightmost_subexpression(&expr.expr, Precedence::Prefix);
943
944        self.outer_attrs(&expr.attrs);
945        self.unary_operator(&expr.op);
946        self.subexpr(&expr.expr, right_prec < Precedence::Prefix, right_fixup);
947    }
948
949    fn expr_unsafe(&mut self, expr: &ExprUnsafe) {
950        self.outer_attrs(&expr.attrs);
951        self.word("unsafe ");
952        self.cbox(INDENT);
953        self.small_block(&expr.block, &expr.attrs);
954        self.end();
955    }
956
957    #[cfg(not(feature = "verbatim"))]
958    fn expr_verbatim(&mut self, expr: &TokenStream, _fixup: FixupContext) {
959        if !expr.is_empty() {
960            unimplemented!("Expr::Verbatim `{}`", expr);
961        }
962    }
963
964    #[cfg(feature = "verbatim")]
965    fn expr_verbatim(&mut self, tokens: &TokenStream, fixup: FixupContext) {
966        use syn::parse::discouraged::Speculative;
967        use syn::parse::{Parse, ParseStream, Result};
968        use syn::{parenthesized, Ident};
969
970        enum ExprVerbatim {
971            Empty,
972            Ellipsis,
973            Become(Become),
974            Builtin(Builtin),
975        }
976
977        struct Become {
978            attrs: Vec<Attribute>,
979            tail_call: Expr,
980        }
981
982        struct Builtin {
983            attrs: Vec<Attribute>,
984            name: Ident,
985            args: TokenStream,
986        }
987
988        mod kw {
989            syn::custom_keyword!(builtin);
990            syn::custom_keyword!(raw);
991        }
992
993        impl Parse for ExprVerbatim {
994            fn parse(input: ParseStream) -> Result<Self> {
995                let ahead = input.fork();
996                let attrs = ahead.call(Attribute::parse_outer)?;
997                let lookahead = ahead.lookahead1();
998                if input.is_empty() {
999                    Ok(ExprVerbatim::Empty)
1000                } else if lookahead.peek(Token![become]) {
1001                    input.advance_to(&ahead);
1002                    input.parse::<Token![become]>()?;
1003                    let tail_call: Expr = input.parse()?;
1004                    Ok(ExprVerbatim::Become(Become { attrs, tail_call }))
1005                } else if lookahead.peek(kw::builtin) {
1006                    input.advance_to(&ahead);
1007                    input.parse::<kw::builtin>()?;
1008                    input.parse::<Token![#]>()?;
1009                    let name: Ident = input.parse()?;
1010                    let args;
1011                    parenthesized!(args in input);
1012                    let args: TokenStream = args.parse()?;
1013                    Ok(ExprVerbatim::Builtin(Builtin { attrs, name, args }))
1014                } else if lookahead.peek(Token![...]) {
1015                    input.parse::<Token![...]>()?;
1016                    Ok(ExprVerbatim::Ellipsis)
1017                } else {
1018                    Err(lookahead.error())
1019                }
1020            }
1021        }
1022
1023        let expr: ExprVerbatim = match syn::parse2(tokens.clone()) {
1024            Ok(expr) => expr,
1025            Err(_) => unimplemented!("Expr::Verbatim `{}`", tokens),
1026        };
1027
1028        match expr {
1029            ExprVerbatim::Empty => {}
1030            ExprVerbatim::Ellipsis => {
1031                self.word("...");
1032            }
1033            ExprVerbatim::Become(expr) => {
1034                self.outer_attrs(&expr.attrs);
1035                self.word("become");
1036                self.nbsp();
1037                self.expr(
1038                    &expr.tail_call,
1039                    fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
1040                );
1041            }
1042            ExprVerbatim::Builtin(expr) => {
1043                self.outer_attrs(&expr.attrs);
1044                self.word("builtin # ");
1045                self.ident(&expr.name);
1046                self.word("(");
1047                if !expr.args.is_empty() {
1048                    self.cbox(INDENT);
1049                    self.zerobreak();
1050                    self.ibox(0);
1051                    self.macro_rules_tokens(expr.args, false);
1052                    self.end();
1053                    self.zerobreak();
1054                    self.offset(-INDENT);
1055                    self.end();
1056                }
1057                self.word(")");
1058            }
1059        }
1060    }
1061
1062    fn expr_while(&mut self, expr: &ExprWhile) {
1063        self.outer_attrs(&expr.attrs);
1064        if let Some(label) = &expr.label {
1065            self.label(label);
1066        }
1067        self.word("while ");
1068        self.expr_condition(&expr.cond);
1069        self.word("{");
1070        self.neverbreak();
1071        self.cbox(INDENT);
1072        self.hardbreak_if_nonempty();
1073        self.inner_attrs(&expr.attrs);
1074        for stmt in expr.body.stmts.iter().delimited() {
1075            self.stmt(&stmt, stmt.is_last);
1076        }
1077        self.offset(-INDENT);
1078        self.end();
1079        self.word("}");
1080    }
1081
1082    fn expr_yield(&mut self, expr: &ExprYield, fixup: FixupContext) {
1083        self.outer_attrs(&expr.attrs);
1084        self.word("yield");
1085        if let Some(value) = &expr.expr {
1086            self.nbsp();
1087            self.expr(
1088                value,
1089                fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
1090            );
1091        }
1092    }
1093
1094    fn label(&mut self, label: &Label) {
1095        self.lifetime(&label.name);
1096        self.word(": ");
1097    }
1098
1099    fn field_value(&mut self, field_value: &FieldValue) {
1100        self.outer_attrs(&field_value.attrs);
1101        self.member(&field_value.member);
1102        if field_value.colon_token.is_some() {
1103            self.word(": ");
1104            self.ibox(0);
1105            self.expr(&field_value.expr, FixupContext::NONE);
1106            self.end();
1107        }
1108    }
1109
1110    fn arm(&mut self, arm: &Arm) {
1111        self.outer_attrs(&arm.attrs);
1112        self.ibox(0);
1113        self.pat(&arm.pat);
1114        if let Some((_if_token, guard)) = &arm.guard {
1115            self.word(" if ");
1116            self.expr(guard, FixupContext::NONE);
1117        }
1118        self.word(" => ");
1119        let empty_block;
1120        let mut body = &*arm.body;
1121        while let Expr::Block(expr) = body {
1122            if expr.attrs.is_empty() && expr.label.is_none() {
1123                let mut stmts = expr.block.stmts.iter();
1124                if let (Some(Stmt::Expr(inner, None)), None) = (stmts.next(), stmts.next()) {
1125                    body = inner;
1126                    continue;
1127                }
1128            }
1129            break;
1130        }
1131        if let Expr::Tuple(expr) = body {
1132            if expr.elems.is_empty() && expr.attrs.is_empty() {
1133                empty_block = Expr::Block(ExprBlock {
1134                    attrs: Vec::new(),
1135                    label: None,
1136                    block: Block {
1137                        brace_token: token::Brace::default(),
1138                        stmts: Vec::new(),
1139                    },
1140                });
1141                body = &empty_block;
1142            }
1143        }
1144        if let Expr::Block(body) = body {
1145            if let Some(label) = &body.label {
1146                self.label(label);
1147            }
1148            self.word("{");
1149            self.neverbreak();
1150            self.cbox(INDENT);
1151            self.hardbreak_if_nonempty();
1152            self.inner_attrs(&body.attrs);
1153            for stmt in body.block.stmts.iter().delimited() {
1154                self.stmt(&stmt, stmt.is_last);
1155            }
1156            self.offset(-INDENT);
1157            self.end();
1158            self.word("}");
1159        } else {
1160            self.neverbreak();
1161            self.cbox(INDENT);
1162            let okay_to_brace = parseable_as_stmt(body);
1163            self.scan_break(BreakToken {
1164                pre_break: Some(if okay_to_brace { '{' } else { '(' }),
1165                ..BreakToken::default()
1166            });
1167            self.expr_beginning_of_line(body, false, true, FixupContext::new_match_arm());
1168            self.scan_break(BreakToken {
1169                offset: -INDENT,
1170                pre_break: (okay_to_brace && stmt::add_semi(body)).then_some(';'),
1171                post_break: if okay_to_brace { "}" } else { ")," },
1172                no_break: classify::requires_comma_to_be_match_arm(body).then_some(','),
1173                ..BreakToken::default()
1174            });
1175            self.end();
1176        }
1177        self.end();
1178    }
1179
1180    fn call_args(&mut self, args: &Punctuated<Expr, Token![,]>) {
1181        let mut iter = args.iter();
1182        match (iter.next(), iter.next()) {
1183            (Some(expr), None) if is_blocklike(expr) => {
1184                self.expr(expr, FixupContext::NONE);
1185            }
1186            _ => {
1187                self.cbox(INDENT);
1188                self.zerobreak();
1189                for arg in args.iter().delimited() {
1190                    self.expr(&arg, FixupContext::NONE);
1191                    self.trailing_comma(arg.is_last);
1192                }
1193                self.offset(-INDENT);
1194                self.end();
1195            }
1196        }
1197    }
1198
1199    pub fn small_block(&mut self, block: &Block, attrs: &[Attribute]) {
1200        self.word("{");
1201        if attr::has_inner(attrs) || !block.stmts.is_empty() {
1202            self.space();
1203            self.inner_attrs(attrs);
1204            match block.stmts.as_slice() {
1205                [Stmt::Expr(expr, None)] if stmt::break_after(expr) => {
1206                    self.ibox(0);
1207                    self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt());
1208                    self.end();
1209                    self.space();
1210                }
1211                _ => {
1212                    for stmt in block.stmts.iter().delimited() {
1213                        self.stmt(&stmt, stmt.is_last);
1214                    }
1215                }
1216            }
1217            self.offset(-INDENT);
1218        }
1219        self.word("}");
1220    }
1221
1222    pub fn expr_as_small_block(&mut self, expr: &Expr, indent: isize) {
1223        self.word("{");
1224        self.space();
1225        self.ibox(indent);
1226        self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt());
1227        self.end();
1228        self.space();
1229        self.offset(-INDENT);
1230        self.word("}");
1231    }
1232
1233    pub fn member(&mut self, member: &Member) {
1234        match member {
1235            Member::Named(ident) => self.ident(ident),
1236            Member::Unnamed(index) => self.index(index),
1237        }
1238    }
1239
1240    fn index(&mut self, member: &Index) {
1241        self.word(member.index.to_string());
1242    }
1243
1244    fn binary_operator(&mut self, op: &BinOp) {
1245        self.word(
1246            match op {
1247                #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1248                BinOp::Add(_) => "+",
1249                BinOp::Sub(_) => "-",
1250                BinOp::Mul(_) => "*",
1251                BinOp::Div(_) => "/",
1252                BinOp::Rem(_) => "%",
1253                BinOp::And(_) => "&&",
1254                BinOp::Or(_) => "||",
1255                BinOp::BitXor(_) => "^",
1256                BinOp::BitAnd(_) => "&",
1257                BinOp::BitOr(_) => "|",
1258                BinOp::Shl(_) => "<<",
1259                BinOp::Shr(_) => ">>",
1260                BinOp::Eq(_) => "==",
1261                BinOp::Lt(_) => "<",
1262                BinOp::Le(_) => "<=",
1263                BinOp::Ne(_) => "!=",
1264                BinOp::Ge(_) => ">=",
1265                BinOp::Gt(_) => ">",
1266                BinOp::AddAssign(_) => "+=",
1267                BinOp::SubAssign(_) => "-=",
1268                BinOp::MulAssign(_) => "*=",
1269                BinOp::DivAssign(_) => "/=",
1270                BinOp::RemAssign(_) => "%=",
1271                BinOp::BitXorAssign(_) => "^=",
1272                BinOp::BitAndAssign(_) => "&=",
1273                BinOp::BitOrAssign(_) => "|=",
1274                BinOp::ShlAssign(_) => "<<=",
1275                BinOp::ShrAssign(_) => ">>=",
1276                _ => unimplemented!("unknown BinOp"),
1277            },
1278        );
1279    }
1280
1281    fn unary_operator(&mut self, op: &UnOp) {
1282        self.word(
1283            match op {
1284                #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1285                UnOp::Deref(_) => "*",
1286                UnOp::Not(_) => "!",
1287                UnOp::Neg(_) => "-",
1288                _ => unimplemented!("unknown UnOp"),
1289            },
1290        );
1291    }
1292
1293    fn pointer_mutability(&mut self, mutability: &PointerMutability) {
1294        match mutability {
1295            PointerMutability::Const(_) => self.word("const"),
1296            PointerMutability::Mut(_) => self.word("mut"),
1297        }
1298    }
1299}
1300
1301fn needs_newline_if_wrap(expr: &Expr) -> bool {
1302    match expr {
1303        #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1304        Expr::Array(_)
1305        | Expr::Async(_)
1306        | Expr::Block(_)
1307        | Expr::Break(ExprBreak { expr: None, .. })
1308        | Expr::Closure(_)
1309        | Expr::Const(_)
1310        | Expr::Continue(_)
1311        | Expr::ForLoop(_)
1312        | Expr::If(_)
1313        | Expr::Infer(_)
1314        | Expr::Lit(_)
1315        | Expr::Loop(_)
1316        | Expr::Macro(_)
1317        | Expr::Match(_)
1318        | Expr::Path(_)
1319        | Expr::Range(ExprRange { end: None, .. })
1320        | Expr::Repeat(_)
1321        | Expr::Return(ExprReturn { expr: None, .. })
1322        | Expr::Struct(_)
1323        | Expr::TryBlock(_)
1324        | Expr::Tuple(_)
1325        | Expr::Unsafe(_)
1326        | Expr::Verbatim(_)
1327        | Expr::While(_)
1328        | Expr::Yield(ExprYield { expr: None, .. }) => false,
1329
1330        Expr::Assign(_)
1331        | Expr::Await(_)
1332        | Expr::Binary(_)
1333        | Expr::Cast(_)
1334        | Expr::Field(_)
1335        | Expr::Index(_)
1336        | Expr::MethodCall(_) => true,
1337
1338        Expr::Break(ExprBreak { expr: Some(e), .. })
1339        | Expr::Call(ExprCall { func: e, .. })
1340        | Expr::Group(ExprGroup { expr: e, .. })
1341        | Expr::Let(ExprLet { expr: e, .. })
1342        | Expr::Paren(ExprParen { expr: e, .. })
1343        | Expr::Range(ExprRange { end: Some(e), .. })
1344        | Expr::RawAddr(ExprRawAddr { expr: e, .. })
1345        | Expr::Reference(ExprReference { expr: e, .. })
1346        | Expr::Return(ExprReturn { expr: Some(e), .. })
1347        | Expr::Try(ExprTry { expr: e, .. })
1348        | Expr::Unary(ExprUnary { expr: e, .. })
1349        | Expr::Yield(ExprYield { expr: Some(e), .. }) => needs_newline_if_wrap(e),
1350
1351        _ => false,
1352    }
1353}
1354
1355fn is_short_ident(expr: &Expr) -> bool {
1356    if let Expr::Path(expr) = expr {
1357        return expr.attrs.is_empty()
1358            && expr.qself.is_none()
1359            && expr
1360                .path
1361                .get_ident()
1362                .map_or(false, |ident| ident.to_string().len() as isize <= INDENT);
1363    }
1364    false
1365}
1366
1367fn is_blocklike(expr: &Expr) -> bool {
1368    match expr {
1369        #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1370        Expr::Array(ExprArray { attrs, .. })
1371        | Expr::Async(ExprAsync { attrs, .. })
1372        | Expr::Block(ExprBlock { attrs, .. })
1373        | Expr::Closure(ExprClosure { attrs, .. })
1374        | Expr::Const(ExprConst { attrs, .. })
1375        | Expr::Struct(ExprStruct { attrs, .. })
1376        | Expr::TryBlock(ExprTryBlock { attrs, .. })
1377        | Expr::Tuple(ExprTuple { attrs, .. })
1378        | Expr::Unsafe(ExprUnsafe { attrs, .. }) => !attr::has_outer(attrs),
1379
1380        Expr::Assign(_)
1381        | Expr::Await(_)
1382        | Expr::Binary(_)
1383        | Expr::Break(_)
1384        | Expr::Call(_)
1385        | Expr::Cast(_)
1386        | Expr::Continue(_)
1387        | Expr::Field(_)
1388        | Expr::ForLoop(_)
1389        | Expr::If(_)
1390        | Expr::Index(_)
1391        | Expr::Infer(_)
1392        | Expr::Let(_)
1393        | Expr::Lit(_)
1394        | Expr::Loop(_)
1395        | Expr::Macro(_)
1396        | Expr::Match(_)
1397        | Expr::MethodCall(_)
1398        | Expr::Paren(_)
1399        | Expr::Path(_)
1400        | Expr::Range(_)
1401        | Expr::RawAddr(_)
1402        | Expr::Reference(_)
1403        | Expr::Repeat(_)
1404        | Expr::Return(_)
1405        | Expr::Try(_)
1406        | Expr::Unary(_)
1407        | Expr::Verbatim(_)
1408        | Expr::While(_)
1409        | Expr::Yield(_) => false,
1410
1411        Expr::Group(e) => is_blocklike(&e.expr),
1412
1413        _ => false,
1414    }
1415}
1416
1417pub fn simple_block(expr: &Expr) -> Option<&ExprBlock> {
1418    if let Expr::Block(expr) = expr {
1419        if expr.attrs.is_empty() && expr.label.is_none() {
1420            return Some(expr);
1421        }
1422    }
1423    None
1424}
1425
1426pub fn simple_array(elements: &Punctuated<Expr, Token![,]>) -> bool {
1427    for expr in elements {
1428        if let Expr::Lit(expr) = expr {
1429            match expr.lit {
1430                #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1431                Lit::Byte(_) | Lit::Char(_) | Lit::Int(_) | Lit::Bool(_) => {}
1432
1433                Lit::Str(_) | Lit::ByteStr(_) | Lit::CStr(_) | Lit::Float(_) | Lit::Verbatim(_) => {
1434                    return false;
1435                }
1436
1437                _ => return false,
1438            }
1439        } else {
1440            return false;
1441        }
1442    }
1443    true
1444}
1445
1446// Expressions for which `$expr` and `{ $expr }` mean the same thing.
1447//
1448// This is not the case for all expressions. For example `{} | x | x` has some
1449// bitwise OR operators while `{ {} |x| x }` has a block followed by a closure.
1450fn parseable_as_stmt(mut expr: &Expr) -> bool {
1451    loop {
1452        match expr {
1453            #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1454            Expr::Array(_)
1455            | Expr::Async(_)
1456            | Expr::Block(_)
1457            | Expr::Break(_)
1458            | Expr::Closure(_)
1459            | Expr::Const(_)
1460            | Expr::Continue(_)
1461            | Expr::ForLoop(_)
1462            | Expr::If(_)
1463            | Expr::Infer(_)
1464            | Expr::Lit(_)
1465            | Expr::Loop(_)
1466            | Expr::Macro(_)
1467            | Expr::Match(_)
1468            | Expr::Paren(_)
1469            | Expr::Path(_)
1470            | Expr::RawAddr(_)
1471            | Expr::Reference(_)
1472            | Expr::Repeat(_)
1473            | Expr::Return(_)
1474            | Expr::Struct(_)
1475            | Expr::TryBlock(_)
1476            | Expr::Tuple(_)
1477            | Expr::Unary(_)
1478            | Expr::Unsafe(_)
1479            | Expr::Verbatim(_)
1480            | Expr::While(_)
1481            | Expr::Yield(_) => return true,
1482
1483            Expr::Let(_) => return false,
1484
1485            Expr::Assign(e) => {
1486                if !classify::requires_semi_to_be_stmt(&e.left) {
1487                    return false;
1488                }
1489                expr = &e.left;
1490            }
1491            Expr::Await(e) => expr = &e.base,
1492            Expr::Binary(e) => {
1493                if !classify::requires_semi_to_be_stmt(&e.left) {
1494                    return false;
1495                }
1496                expr = &e.left;
1497            }
1498            Expr::Call(e) => {
1499                if !classify::requires_semi_to_be_stmt(&e.func) {
1500                    return false;
1501                }
1502                expr = &e.func;
1503            }
1504            Expr::Cast(e) => {
1505                if !classify::requires_semi_to_be_stmt(&e.expr) {
1506                    return false;
1507                }
1508                expr = &e.expr;
1509            }
1510            Expr::Field(e) => expr = &e.base,
1511            Expr::Group(e) => expr = &e.expr,
1512            Expr::Index(e) => {
1513                if !classify::requires_semi_to_be_stmt(&e.expr) {
1514                    return false;
1515                }
1516                expr = &e.expr;
1517            }
1518            Expr::MethodCall(e) => expr = &e.receiver,
1519            Expr::Range(e) => match &e.start {
1520                None => return true,
1521                Some(start) => {
1522                    if !classify::requires_semi_to_be_stmt(start) {
1523                        return false;
1524                    }
1525                    expr = start;
1526                }
1527            },
1528            Expr::Try(e) => expr = &e.expr,
1529
1530            _ => return false,
1531        }
1532    }
1533}