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