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