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