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