prettyplease/
expr.rs

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