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 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
1422fn 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}