Skip to main content

a9_prettyplease/
expr.rs

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