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