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