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 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 #[allow(non_exhaustive_omitted_patterns)] match func.member {
Member::Named(_) => true,
_ => false,
}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 #[allow(non_exhaustive_omitted_patterns)] match func.member {
Member::Named(_) => true,
_ => false,
}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 #[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())
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 self.stmts(&expr.body.stmts);
564 self.offset(-INDENT);
565 self.end();
566 self.word("}");
567 self.end();
568 }
569
570 fn expr_group(&mut self, expr: &ExprGroup, fixup: FixupContext) {
571 self.outer_attrs(&expr.attrs);
572 self.expr(&expr.expr, fixup);
573 }
574
575 fn expr_if(&mut self, expr: &ExprIf) {
576 self.outer_attrs(&expr.attrs);
577 self.cbox(INDENT);
578 self.word("if ");
579 self.cbox(-INDENT);
580 self.expr_condition(&expr.cond);
581 self.end();
582 if let Some((_else_token, else_branch)) = &expr.else_branch {
583 let mut else_branch = &**else_branch;
584 self.small_block(&expr.then_branch, &[]);
585 loop {
586 self.word(" else ");
587 match else_branch {
588 Expr::If(expr) => {
589 self.word("if ");
590 self.cbox(-INDENT);
591 self.expr_condition(&expr.cond);
592 self.end();
593 self.small_block(&expr.then_branch, &[]);
594 if let Some((_else_token, next)) = &expr.else_branch {
595 else_branch = next;
596 continue;
597 }
598 }
599 Expr::Block(expr) => {
600 self.small_block(&expr.block, &[]);
601 }
602 other => self.expr_as_small_block(other, INDENT),
605 }
606 break;
607 }
608 } else if expr.then_branch.stmts.is_empty() {
609 self.word("{}");
610 } else {
611 self.word("{");
612 self.hardbreak();
613 self.stmts(&expr.then_branch.stmts);
614 self.offset(-INDENT);
615 self.word("}");
616 }
617 self.end();
618 }
619
620 fn expr_index(&mut self, expr: &ExprIndex, beginning_of_line: bool, fixup: FixupContext) {
621 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
622 &expr.expr,
623 true,
624 false,
625 Precedence::Unambiguous,
626 );
627
628 self.outer_attrs(&expr.attrs);
629 self.expr_beginning_of_line(
630 &expr.expr,
631 left_prec < Precedence::Unambiguous,
632 beginning_of_line,
633 left_fixup,
634 );
635 self.word("[");
636 self.expr(&expr.index, FixupContext::NONE);
637 self.word("]");
638 }
639
640 fn prefix_subexpr_index(
641 &mut self,
642 expr: &ExprIndex,
643 beginning_of_line: bool,
644 fixup: FixupContext,
645 ) {
646 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
647 &expr.expr,
648 true,
649 false,
650 Precedence::Unambiguous,
651 );
652
653 self.prefix_subexpr(
654 &expr.expr,
655 left_prec < Precedence::Unambiguous,
656 beginning_of_line,
657 left_fixup,
658 );
659 self.word("[");
660 self.expr(&expr.index, FixupContext::NONE);
661 self.word("]");
662 }
663
664 fn expr_infer(&mut self, expr: &ExprInfer) {
665 self.outer_attrs(&expr.attrs);
666 self.word("_");
667 }
668
669 fn expr_let(&mut self, expr: &ExprLet, fixup: FixupContext) {
670 let (right_prec, right_fixup) = fixup.rightmost_subexpression(&expr.expr, Precedence::Let);
671
672 self.outer_attrs(&expr.attrs);
673 self.ibox(0);
674 self.word("let ");
675 self.ibox(0);
676 self.pat(&expr.pat);
677 self.end();
678 self.word(" = ");
679 self.neverbreak();
680 self.ibox(0);
681 self.subexpr(&expr.expr, right_prec < Precedence::Let, right_fixup);
682 self.end();
683 self.end();
684 }
685
686 pub fn expr_lit(&mut self, expr: &ExprLit) {
687 self.outer_attrs(&expr.attrs);
688 self.lit(&expr.lit);
689 }
690
691 fn expr_loop(&mut self, expr: &ExprLoop) {
692 self.outer_attrs(&expr.attrs);
693 if let Some(label) = &expr.label {
694 self.label(label);
695 }
696 self.word("loop {");
697 self.cbox(INDENT);
698 self.hardbreak_if_nonempty();
699 self.inner_attrs(&expr.attrs);
700 self.stmts(&expr.body.stmts);
701 self.offset(-INDENT);
702 self.end();
703 self.word("}");
704 }
705
706 pub fn expr_macro(&mut self, expr: &ExprMacro) {
707 self.outer_attrs(&expr.attrs);
708 let semicolon = false;
709 self.mac(&expr.mac, None, semicolon);
710 }
711
712 fn expr_match(&mut self, expr: &ExprMatch) {
713 self.outer_attrs(&expr.attrs);
714 self.ibox(0);
715 self.word("match ");
716 self.expr_condition(&expr.expr);
717 self.word("{");
718 self.neverbreak();
719 self.cbox(INDENT);
720 self.hardbreak_if_nonempty();
721 self.inner_attrs(&expr.attrs);
722 for arm in &expr.arms {
723 self.arm(arm);
724 self.hardbreak();
725 }
726 self.offset(-INDENT);
727 self.end();
728 self.word("}");
729 self.end();
730 }
731
732 fn expr_method_call(
733 &mut self,
734 expr: &ExprMethodCall,
735 beginning_of_line: bool,
736 fixup: FixupContext,
737 ) {
738 self.outer_attrs(&expr.attrs);
739 self.cbox(INDENT);
740 let unindent_call_args = beginning_of_line && is_short_ident(&expr.receiver);
741 self.prefix_subexpr_method_call(expr, beginning_of_line, unindent_call_args, fixup);
742 self.end();
743 }
744
745 fn prefix_subexpr_method_call(
746 &mut self,
747 expr: &ExprMethodCall,
748 beginning_of_line: bool,
749 unindent_call_args: bool,
750 fixup: FixupContext,
751 ) {
752 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.receiver);
753
754 self.prefix_subexpr(
755 &expr.receiver,
756 left_prec < Precedence::Unambiguous,
757 beginning_of_line,
758 left_fixup,
759 );
760 if !(beginning_of_line && is_short_ident(&expr.receiver)) {
761 self.scan_break(BreakToken {
762 no_break: self.ends_with('.').then_some(' '),
763 ..BreakToken::default()
764 });
765 }
766 self.word(".");
767 self.ident(&expr.method);
768 if let Some(turbofish) = &expr.turbofish {
769 self.angle_bracketed_generic_arguments(turbofish, PathKind::Expr);
770 }
771 self.cbox(if unindent_call_args { -INDENT } else { 0 });
772 self.word("(");
773 self.call_args(&expr.args);
774 self.word(")");
775 self.end();
776 }
777
778 fn expr_paren(&mut self, expr: &ExprParen) {
779 self.outer_attrs(&expr.attrs);
780 self.word("(");
781 self.expr(&expr.expr, FixupContext::NONE);
782 self.word(")");
783 }
784
785 pub fn expr_path(&mut self, expr: &ExprPath) {
786 self.outer_attrs(&expr.attrs);
787 self.qpath(&expr.qself, &expr.path, PathKind::Expr);
788 }
789
790 pub fn expr_range(&mut self, expr: &ExprRange, fixup: FixupContext) {
791 self.outer_attrs(&expr.attrs);
792 if !expr.attrs.is_empty() {
793 self.word("(");
794 }
795 if let Some(start) = &expr.start {
796 let (left_prec, left_fixup) =
797 fixup.leftmost_subexpression_with_operator(start, true, false, Precedence::Range);
798 self.subexpr(start, left_prec <= Precedence::Range, left_fixup);
799 } else if self.ends_with('.') {
800 self.nbsp();
801 }
802 self.word(match expr.limits {
803 RangeLimits::HalfOpen(_) => "..",
804 RangeLimits::Closed(_) => "..=",
805 });
806 if let Some(end) = &expr.end {
807 let right_fixup = fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
808 let right_prec = right_fixup.rightmost_subexpression_precedence(end);
809 self.subexpr(end, right_prec <= Precedence::Range, right_fixup);
810 }
811 if !expr.attrs.is_empty() {
812 self.word(")");
813 }
814 }
815
816 fn expr_raw_addr(&mut self, expr: &ExprRawAddr, fixup: FixupContext) {
817 let (right_prec, right_fixup) =
818 fixup.rightmost_subexpression(&expr.expr, Precedence::Prefix);
819
820 self.outer_attrs(&expr.attrs);
821 self.word("&raw ");
822 self.pointer_mutability(&expr.mutability);
823 self.nbsp();
824 self.subexpr(&expr.expr, right_prec < Precedence::Prefix, right_fixup);
825 }
826
827 fn expr_reference(&mut self, expr: &ExprReference, fixup: FixupContext) {
828 let (right_prec, right_fixup) =
829 fixup.rightmost_subexpression(&expr.expr, Precedence::Prefix);
830
831 self.outer_attrs(&expr.attrs);
832 self.word("&");
833 if expr.mutability.is_some() {
834 self.word("mut ");
835 }
836 self.subexpr(&expr.expr, right_prec < Precedence::Prefix, right_fixup);
837 }
838
839 fn expr_repeat(&mut self, expr: &ExprRepeat) {
840 self.outer_attrs(&expr.attrs);
841 self.word("[");
842 self.expr(&expr.expr, FixupContext::NONE);
843 self.word("; ");
844 self.expr(&expr.len, FixupContext::NONE);
845 self.word("]");
846 }
847
848 fn expr_return(&mut self, expr: &ExprReturn, fixup: FixupContext) {
849 self.outer_attrs(&expr.attrs);
850 self.word("return");
851 if let Some(value) = &expr.expr {
852 self.nbsp();
853 self.expr(
854 value,
855 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
856 );
857 }
858 }
859
860 fn expr_struct(&mut self, expr: &ExprStruct) {
861 self.outer_attrs(&expr.attrs);
862 self.cbox(INDENT);
863 self.ibox(-INDENT);
864 self.qpath(&expr.qself, &expr.path, PathKind::Expr);
865 self.end();
866 self.word(" {");
867 self.space_if_nonempty();
868 for field_value in expr.fields.iter().delimited() {
869 self.field_value(&field_value);
870 self.trailing_comma_or_space(field_value.is_last && expr.rest.is_none());
871 }
872 if let Some(rest) = &expr.rest {
873 self.word("..");
874 self.expr(rest, FixupContext::NONE);
875 self.space();
876 }
877 self.offset(-INDENT);
878 self.end_with_max_width(34);
879 self.word("}");
880 }
881
882 fn expr_try(&mut self, expr: &ExprTry, beginning_of_line: bool, fixup: FixupContext) {
883 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.expr);
884
885 self.outer_attrs(&expr.attrs);
886 self.expr_beginning_of_line(
887 &expr.expr,
888 left_prec < Precedence::Unambiguous,
889 beginning_of_line,
890 left_fixup,
891 );
892 self.word("?");
893 }
894
895 fn prefix_subexpr_try(&mut self, expr: &ExprTry, beginning_of_line: bool, fixup: FixupContext) {
896 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.expr);
897
898 self.prefix_subexpr(
899 &expr.expr,
900 left_prec < Precedence::Unambiguous,
901 beginning_of_line,
902 left_fixup,
903 );
904 self.word("?");
905 }
906
907 fn expr_try_block(&mut self, expr: &ExprTryBlock) {
908 self.outer_attrs(&expr.attrs);
909 self.word("try ");
910 self.cbox(INDENT);
911 self.small_block(&expr.block, &expr.attrs);
912 self.end();
913 }
914
915 fn expr_tuple(&mut self, expr: &ExprTuple) {
916 self.outer_attrs(&expr.attrs);
917 self.word("(");
918 self.cbox(INDENT);
919 self.zerobreak();
920 for elem in expr.elems.iter().delimited() {
921 self.expr(&elem, FixupContext::NONE);
922 if expr.elems.len() == 1 {
923 self.word(",");
924 self.zerobreak();
925 } else {
926 self.trailing_comma(elem.is_last);
927 }
928 }
929 self.offset(-INDENT);
930 self.end();
931 self.word(")");
932 }
933
934 fn expr_unary(&mut self, expr: &ExprUnary, fixup: FixupContext) {
935 let (right_prec, right_fixup) =
936 fixup.rightmost_subexpression(&expr.expr, Precedence::Prefix);
937
938 self.outer_attrs(&expr.attrs);
939 self.unary_operator(&expr.op);
940 self.subexpr(&expr.expr, right_prec < Precedence::Prefix, right_fixup);
941 }
942
943 fn expr_unsafe(&mut self, expr: &ExprUnsafe) {
944 self.outer_attrs(&expr.attrs);
945 self.word("unsafe ");
946 self.cbox(INDENT);
947 self.small_block(&expr.block, &expr.attrs);
948 self.end();
949 }
950
951 #[cfg(not(feature = "verbatim"))]
952 fn expr_verbatim(&mut self, expr: &TokenStream, _fixup: FixupContext) {
953 if !expr.is_empty() {
954 {
::core::panicking::panic_fmt(format_args!("not implemented: {0}",
format_args!("Expr::Verbatim `{0}`", expr)));
};unimplemented!("Expr::Verbatim `{}`", expr);
955 }
956 }
957
958 #[cfg(feature = "verbatim")]
959 fn expr_verbatim(&mut self, tokens: &TokenStream, fixup: FixupContext) {
960 use syn::parse::discouraged::Speculative;
961 use syn::parse::{Parse, ParseStream, Result};
962 use syn::{parenthesized, Ident};
963
964 enum ExprVerbatim {
965 Empty,
966 Ellipsis,
967 Become(Become),
968 Builtin(Builtin),
969 }
970
971 struct Become {
972 attrs: Vec<Attribute>,
973 tail_call: Expr,
974 }
975
976 struct Builtin {
977 attrs: Vec<Attribute>,
978 name: Ident,
979 args: TokenStream,
980 }
981
982 mod kw {
983 syn::custom_keyword!(builtin);
984 syn::custom_keyword!(raw);
985 }
986
987 impl Parse for ExprVerbatim {
988 fn parse(input: ParseStream) -> Result<Self> {
989 let ahead = input.fork();
990 let attrs = ahead.call(Attribute::parse_outer)?;
991 let lookahead = ahead.lookahead1();
992 if input.is_empty() {
993 Ok(ExprVerbatim::Empty)
994 } else if lookahead.peek(Token![become]) {
995 input.advance_to(&ahead);
996 input.parse::<Token![become]>()?;
997 let tail_call: Expr = input.parse()?;
998 Ok(ExprVerbatim::Become(Become { attrs, tail_call }))
999 } else if lookahead.peek(kw::builtin) {
1000 input.advance_to(&ahead);
1001 input.parse::<kw::builtin>()?;
1002 input.parse::<Token![#]>()?;
1003 let name: Ident = input.parse()?;
1004 let args;
1005 parenthesized!(args in input);
1006 let args: TokenStream = args.parse()?;
1007 Ok(ExprVerbatim::Builtin(Builtin { attrs, name, args }))
1008 } else if lookahead.peek(Token![...]) {
1009 input.parse::<Token![...]>()?;
1010 Ok(ExprVerbatim::Ellipsis)
1011 } else {
1012 Err(lookahead.error())
1013 }
1014 }
1015 }
1016
1017 let expr: ExprVerbatim = match syn::parse2(tokens.clone()) {
1018 Ok(expr) => expr,
1019 Err(_) => unimplemented!("Expr::Verbatim `{}`", tokens),
1020 };
1021
1022 match expr {
1023 ExprVerbatim::Empty => {}
1024 ExprVerbatim::Ellipsis => {
1025 self.word("...");
1026 }
1027 ExprVerbatim::Become(expr) => {
1028 self.outer_attrs(&expr.attrs);
1029 self.word("become");
1030 self.nbsp();
1031 self.expr(
1032 &expr.tail_call,
1033 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
1034 );
1035 }
1036 ExprVerbatim::Builtin(expr) => {
1037 self.outer_attrs(&expr.attrs);
1038 self.word("builtin # ");
1039 self.ident(&expr.name);
1040 self.word("(");
1041 if !expr.args.is_empty() {
1042 self.cbox(INDENT);
1043 self.zerobreak();
1044 self.ibox(0);
1045 self.macro_rules_tokens(expr.args, false);
1046 self.end();
1047 self.zerobreak();
1048 self.offset(-INDENT);
1049 self.end();
1050 }
1051 self.word(")");
1052 }
1053 }
1054 }
1055
1056 fn expr_while(&mut self, expr: &ExprWhile) {
1057 self.outer_attrs(&expr.attrs);
1058 if let Some(label) = &expr.label {
1059 self.label(label);
1060 }
1061 self.word("while ");
1062 self.expr_condition(&expr.cond);
1063 self.word("{");
1064 self.neverbreak();
1065 self.cbox(INDENT);
1066 self.hardbreak_if_nonempty();
1067 self.inner_attrs(&expr.attrs);
1068 self.stmts(&expr.body.stmts);
1069 self.offset(-INDENT);
1070 self.end();
1071 self.word("}");
1072 }
1073
1074 fn expr_yield(&mut self, expr: &ExprYield, fixup: FixupContext) {
1075 self.outer_attrs(&expr.attrs);
1076 self.word("yield");
1077 if let Some(value) = &expr.expr {
1078 self.nbsp();
1079 self.expr(
1080 value,
1081 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
1082 );
1083 }
1084 }
1085
1086 fn label(&mut self, label: &Label) {
1087 self.lifetime(&label.name);
1088 self.word(": ");
1089 }
1090
1091 fn field_value(&mut self, field_value: &FieldValue) {
1092 self.outer_attrs(&field_value.attrs);
1093 self.member(&field_value.member);
1094 if field_value.colon_token.is_some() {
1095 self.word(": ");
1096 self.ibox(0);
1097 self.expr(&field_value.expr, FixupContext::NONE);
1098 self.end();
1099 }
1100 }
1101
1102 fn arm(&mut self, arm: &Arm) {
1103 self.outer_attrs(&arm.attrs);
1104 self.ibox(0);
1105 self.pat(&arm.pat);
1106 if let Some((_if_token, guard)) = &arm.guard {
1107 self.word(" if ");
1108 self.expr(guard, FixupContext::NONE);
1109 }
1110 self.word(" => ");
1111 let empty_block;
1112 let mut body = &*arm.body;
1113 while let Expr::Block(expr) = body {
1114 if expr.attrs.is_empty() && expr.label.is_none() {
1115 let mut stmts = expr.block.stmts.iter();
1116 if let (Some(Stmt::Expr(inner, None)), None) = (stmts.next(), stmts.next()) {
1117 body = inner;
1118 continue;
1119 }
1120 }
1121 break;
1122 }
1123 if let Expr::Tuple(expr) = body {
1124 if expr.elems.is_empty() && expr.attrs.is_empty() {
1125 empty_block = Expr::Block(ExprBlock {
1126 attrs: Vec::new(),
1127 label: None,
1128 block: Block {
1129 brace_token: token::Brace::default(),
1130 stmts: Vec::new(),
1131 },
1132 });
1133 body = &empty_block;
1134 }
1135 }
1136 if let Expr::Block(body) = body {
1137 if let Some(label) = &body.label {
1138 self.label(label);
1139 }
1140 self.word("{");
1141 self.neverbreak();
1142 self.cbox(INDENT);
1143 self.hardbreak_if_nonempty();
1144 self.inner_attrs(&body.attrs);
1145 self.stmts(&body.block.stmts);
1146 self.offset(-INDENT);
1147 self.end();
1148 self.word("}");
1149 } else {
1150 self.neverbreak();
1151 self.cbox(INDENT);
1152 let okay_to_brace = parseable_as_stmt(body);
1153 self.scan_break(BreakToken {
1154 pre_break: Some(if okay_to_brace { '{' } else { '(' }),
1155 ..BreakToken::default()
1156 });
1157 self.expr_beginning_of_line(body, false, true, FixupContext::new_match_arm());
1158 self.scan_break(BreakToken {
1159 offset: -INDENT,
1160 pre_break: (okay_to_brace && stmt::add_semi(body)).then_some(';'),
1161 post_break: if okay_to_brace { "}" } else { ")," },
1162 no_break: classify::requires_comma_to_be_match_arm(body).then_some(','),
1163 ..BreakToken::default()
1164 });
1165 self.end();
1166 }
1167 self.end();
1168 }
1169
1170 fn call_args(&mut self, args: &Punctuated<Expr, ::syn::token::CommaToken![,]>) {
1171 let mut iter = args.iter();
1172 match (iter.next(), iter.next()) {
1173 (Some(expr), None) if is_blocklike(expr) => {
1174 self.expr(expr, FixupContext::NONE);
1175 }
1176 _ => {
1177 self.cbox(INDENT);
1178 self.zerobreak();
1179 for arg in args.iter().delimited() {
1180 self.expr(&arg, FixupContext::NONE);
1181 self.trailing_comma(arg.is_last);
1182 }
1183 self.offset(-INDENT);
1184 self.end();
1185 }
1186 }
1187 }
1188
1189 pub fn small_block(&mut self, block: &Block, attrs: &[Attribute]) {
1190 self.word("{");
1191 if attr::has_inner(attrs) || !block.stmts.is_empty() {
1192 self.space();
1193 self.inner_attrs(attrs);
1194 match block.stmts.as_slice() {
1195 [Stmt::Expr(expr, None)] if stmt::break_after(expr) => {
1196 self.ibox(0);
1197 self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt());
1198 self.end();
1199 self.space();
1200 }
1201 _ => {
1202 self.stmts(&block.stmts);
1203 }
1204 }
1205 self.offset(-INDENT);
1206 }
1207 self.word("}");
1208 }
1209
1210 pub fn expr_as_small_block(&mut self, expr: &Expr, indent: isize) {
1211 self.word("{");
1212 self.space();
1213 self.ibox(indent);
1214 self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt());
1215 self.end();
1216 self.space();
1217 self.offset(-INDENT);
1218 self.word("}");
1219 }
1220
1221 pub fn member(&mut self, member: &Member) {
1222 match member {
1223 Member::Named(ident) => self.ident(ident),
1224 Member::Unnamed(index) => self.index(index),
1225 }
1226 }
1227
1228 fn index(&mut self, member: &Index) {
1229 self.word(member.index.to_string());
1230 }
1231
1232 fn binary_operator(&mut self, op: &BinOp) {
1233 self.word(
1234 match op {
1235 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1236 BinOp::Add(_) => "+",
1237 BinOp::Sub(_) => "-",
1238 BinOp::Mul(_) => "*",
1239 BinOp::Div(_) => "/",
1240 BinOp::Rem(_) => "%",
1241 BinOp::And(_) => "&&",
1242 BinOp::Or(_) => "||",
1243 BinOp::BitXor(_) => "^",
1244 BinOp::BitAnd(_) => "&",
1245 BinOp::BitOr(_) => "|",
1246 BinOp::Shl(_) => "<<",
1247 BinOp::Shr(_) => ">>",
1248 BinOp::Eq(_) => "==",
1249 BinOp::Lt(_) => "<",
1250 BinOp::Le(_) => "<=",
1251 BinOp::Ne(_) => "!=",
1252 BinOp::Ge(_) => ">=",
1253 BinOp::Gt(_) => ">",
1254 BinOp::AddAssign(_) => "+=",
1255 BinOp::SubAssign(_) => "-=",
1256 BinOp::MulAssign(_) => "*=",
1257 BinOp::DivAssign(_) => "/=",
1258 BinOp::RemAssign(_) => "%=",
1259 BinOp::BitXorAssign(_) => "^=",
1260 BinOp::BitAndAssign(_) => "&=",
1261 BinOp::BitOrAssign(_) => "|=",
1262 BinOp::ShlAssign(_) => "<<=",
1263 BinOp::ShrAssign(_) => ">>=",
1264 _ => {
::core::panicking::panic_fmt(format_args!("not implemented: {0}",
format_args!("unknown BinOp")));
}unimplemented!("unknown BinOp"),
1265 },
1266 );
1267 }
1268
1269 fn unary_operator(&mut self, op: &UnOp) {
1270 self.word(
1271 match op {
1272 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1273 UnOp::Deref(_) => "*",
1274 UnOp::Not(_) => "!",
1275 UnOp::Neg(_) => "-",
1276 _ => {
::core::panicking::panic_fmt(format_args!("not implemented: {0}",
format_args!("unknown UnOp")));
}unimplemented!("unknown UnOp"),
1277 },
1278 );
1279 }
1280
1281 fn pointer_mutability(&mut self, mutability: &PointerMutability) {
1282 match mutability {
1283 PointerMutability::Const(_) => self.word("const"),
1284 PointerMutability::Mut(_) => self.word("mut"),
1285 }
1286 }
1287}
1288
1289fn needs_newline_if_wrap(expr: &Expr) -> bool {
1290 match expr {
1291 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1292 Expr::Array(_)
1293 | Expr::Async(_)
1294 | Expr::Block(_)
1295 | Expr::Break(ExprBreak { expr: None, .. })
1296 | Expr::Closure(_)
1297 | Expr::Const(_)
1298 | Expr::Continue(_)
1299 | Expr::ForLoop(_)
1300 | Expr::If(_)
1301 | Expr::Infer(_)
1302 | Expr::Lit(_)
1303 | Expr::Loop(_)
1304 | Expr::Macro(_)
1305 | Expr::Match(_)
1306 | Expr::Path(_)
1307 | Expr::Range(ExprRange { end: None, .. })
1308 | Expr::Repeat(_)
1309 | Expr::Return(ExprReturn { expr: None, .. })
1310 | Expr::Struct(_)
1311 | Expr::TryBlock(_)
1312 | Expr::Tuple(_)
1313 | Expr::Unsafe(_)
1314 | Expr::Verbatim(_)
1315 | Expr::While(_)
1316 | Expr::Yield(ExprYield { expr: None, .. }) => false,
1317
1318 Expr::Assign(_)
1319 | Expr::Await(_)
1320 | Expr::Binary(_)
1321 | Expr::Cast(_)
1322 | Expr::Field(_)
1323 | Expr::Index(_)
1324 | Expr::MethodCall(_) => true,
1325
1326 Expr::Break(ExprBreak { expr: Some(e), .. })
1327 | Expr::Call(ExprCall { func: e, .. })
1328 | Expr::Group(ExprGroup { expr: e, .. })
1329 | Expr::Let(ExprLet { expr: e, .. })
1330 | Expr::Paren(ExprParen { expr: e, .. })
1331 | Expr::Range(ExprRange { end: Some(e), .. })
1332 | Expr::RawAddr(ExprRawAddr { expr: e, .. })
1333 | Expr::Reference(ExprReference { expr: e, .. })
1334 | Expr::Return(ExprReturn { expr: Some(e), .. })
1335 | Expr::Try(ExprTry { expr: e, .. })
1336 | Expr::Unary(ExprUnary { expr: e, .. })
1337 | Expr::Yield(ExprYield { expr: Some(e), .. }) => needs_newline_if_wrap(e),
1338
1339 _ => false,
1340 }
1341}
1342
1343fn is_short_ident(expr: &Expr) -> bool {
1344 if let Expr::Path(expr) = expr {
1345 return expr.attrs.is_empty()
1346 && expr.qself.is_none()
1347 && expr
1348 .path
1349 .get_ident()
1350 .is_some_and(|ident| ident.to_string().len() as isize <= INDENT);
1351 }
1352 false
1353}
1354
1355fn is_blocklike(expr: &Expr) -> bool {
1356 match expr {
1357 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1358 Expr::Array(ExprArray { attrs, .. })
1359 | Expr::Async(ExprAsync { attrs, .. })
1360 | Expr::Block(ExprBlock { attrs, .. })
1361 | Expr::Closure(ExprClosure { attrs, .. })
1362 | Expr::Const(ExprConst { attrs, .. })
1363 | Expr::Struct(ExprStruct { attrs, .. })
1364 | Expr::TryBlock(ExprTryBlock { attrs, .. })
1365 | Expr::Tuple(ExprTuple { attrs, .. })
1366 | Expr::Unsafe(ExprUnsafe { attrs, .. }) => !attr::has_outer(attrs),
1367
1368 Expr::Assign(_)
1369 | Expr::Await(_)
1370 | Expr::Binary(_)
1371 | Expr::Break(_)
1372 | Expr::Call(_)
1373 | Expr::Cast(_)
1374 | Expr::Continue(_)
1375 | Expr::Field(_)
1376 | Expr::ForLoop(_)
1377 | Expr::If(_)
1378 | Expr::Index(_)
1379 | Expr::Infer(_)
1380 | Expr::Let(_)
1381 | Expr::Lit(_)
1382 | Expr::Loop(_)
1383 | Expr::Macro(_)
1384 | Expr::Match(_)
1385 | Expr::MethodCall(_)
1386 | Expr::Paren(_)
1387 | Expr::Path(_)
1388 | Expr::Range(_)
1389 | Expr::RawAddr(_)
1390 | Expr::Reference(_)
1391 | Expr::Repeat(_)
1392 | Expr::Return(_)
1393 | Expr::Try(_)
1394 | Expr::Unary(_)
1395 | Expr::Verbatim(_)
1396 | Expr::While(_)
1397 | Expr::Yield(_) => false,
1398
1399 Expr::Group(e) => is_blocklike(&e.expr),
1400
1401 _ => false,
1402 }
1403}
1404
1405pub fn simple_block(expr: &Expr) -> Option<&ExprBlock> {
1406 if let Expr::Block(expr) = expr {
1407 if expr.attrs.is_empty() && expr.label.is_none() {
1408 return Some(expr);
1409 }
1410 }
1411 None
1412}
1413
1414pub fn simple_array(elements: &Punctuated<Expr, ::syn::token::CommaToken![,]>) -> bool {
1415 for expr in elements {
1416 if let Expr::Lit(expr) = expr {
1417 match expr.lit {
1418 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1419 Lit::Byte(_) | Lit::Char(_) | Lit::Int(_) | Lit::Bool(_) => {}
1420
1421 Lit::Str(_) | Lit::ByteStr(_) | Lit::CStr(_) | Lit::Float(_) | Lit::Verbatim(_) => {
1422 return false;
1423 }
1424
1425 _ => return false,
1426 }
1427 } else {
1428 return false;
1429 }
1430 }
1431 true
1432}
1433
1434fn parseable_as_stmt(mut expr: &Expr) -> bool {
1439 loop {
1440 match expr {
1441 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1442 Expr::Array(_)
1443 | Expr::Async(_)
1444 | Expr::Block(_)
1445 | Expr::Break(_)
1446 | Expr::Closure(_)
1447 | Expr::Const(_)
1448 | Expr::Continue(_)
1449 | Expr::ForLoop(_)
1450 | Expr::If(_)
1451 | Expr::Infer(_)
1452 | Expr::Lit(_)
1453 | Expr::Loop(_)
1454 | Expr::Macro(_)
1455 | Expr::Match(_)
1456 | Expr::Paren(_)
1457 | Expr::Path(_)
1458 | Expr::RawAddr(_)
1459 | Expr::Reference(_)
1460 | Expr::Repeat(_)
1461 | Expr::Return(_)
1462 | Expr::Struct(_)
1463 | Expr::TryBlock(_)
1464 | Expr::Tuple(_)
1465 | Expr::Unary(_)
1466 | Expr::Unsafe(_)
1467 | Expr::Verbatim(_)
1468 | Expr::While(_)
1469 | Expr::Yield(_) => return true,
1470
1471 Expr::Let(_) => return false,
1472
1473 Expr::Assign(e) => {
1474 if !classify::requires_semi_to_be_stmt(&e.left) {
1475 return false;
1476 }
1477 expr = &e.left;
1478 }
1479 Expr::Await(e) => expr = &e.base,
1480 Expr::Binary(e) => {
1481 if !classify::requires_semi_to_be_stmt(&e.left) {
1482 return false;
1483 }
1484 expr = &e.left;
1485 }
1486 Expr::Call(e) => {
1487 if !classify::requires_semi_to_be_stmt(&e.func) {
1488 return false;
1489 }
1490 expr = &e.func;
1491 }
1492 Expr::Cast(e) => {
1493 if !classify::requires_semi_to_be_stmt(&e.expr) {
1494 return false;
1495 }
1496 expr = &e.expr;
1497 }
1498 Expr::Field(e) => expr = &e.base,
1499 Expr::Group(e) => expr = &e.expr,
1500 Expr::Index(e) => {
1501 if !classify::requires_semi_to_be_stmt(&e.expr) {
1502 return false;
1503 }
1504 expr = &e.expr;
1505 }
1506 Expr::MethodCall(e) => expr = &e.receiver,
1507 Expr::Range(e) => match &e.start {
1508 None => return true,
1509 Some(start) => {
1510 if !classify::requires_semi_to_be_stmt(start) {
1511 return false;
1512 }
1513 expr = start;
1514 }
1515 },
1516 Expr::Try(e) => expr = &e.expr,
1517
1518 _ => return false,
1519 }
1520 }
1521}