- // Try to format closure body as a single line expression without braces.
- if is_simple_block(body, context.codemap) && !prefix.contains('\n') {
- let (spacer, closer) = if ret_str.is_empty() {
- (" ", "")
- } else {
- (" { ", " }")
- };
- let expr = body.expr.as_ref().unwrap();
- // All closure bodies are blocks in the eyes of the AST, but we may not
- // want to unwrap them when they only contain a single expression.
- let inner_expr = match expr.node {
- ast::ExprKind::Block(ref inner) if inner.stmts.is_empty() && inner.expr.is_some() &&
- inner.rules == ast::BlockCheckMode::Default => {
- inner.expr.as_ref().unwrap()
+ assert!(body.stmts.is_empty(),
+ "unexpected statements in closure: `{}`",
+ context.snippet(span));
+
+ if body.expr.is_none() {
+ return Some(format!("{} {{}}", prefix));
+ }
+
+ // 1 = space between `|...|` and body.
+ let extra_offset = extra_offset(&prefix, offset) + 1;
+ let budget = try_opt!(width.checked_sub(extra_offset));
+
+ // This is where we figure out whether to use braces or not.
+ let mut had_braces = false;
+ let mut inner_block = body;
+ if let ast::ExprKind::Block(ref inner) = inner_block.expr.as_ref().unwrap().node {
+ had_braces = true;
+ inner_block = inner;
+ };
+ assert!(!force_block || !had_braces,
+ "Closure requires braces, but they weren't present. How did this parse? `{}`",
+ context.snippet(span));
+
+ let try_single_line = is_simple_block(inner_block, context.codemap) &&
+ inner_block.rules == ast::BlockCheckMode::Default;
+
+ if try_single_line && !force_block {
+ let must_preserve_braces =
+ !classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(inner_block.expr
+ .as_ref()
+ .unwrap()));
+ if !(must_preserve_braces && had_braces) &&
+ (must_preserve_braces || !prefix.contains('\n')) {
+ // If we got here, then we can try to format without braces.
+
+ let inner_expr = inner_block.expr.as_ref().unwrap();
+ let mut rewrite = inner_expr.rewrite(context, budget, offset + extra_offset);
+
+ if must_preserve_braces {
+ // If we are here, then failure to rewrite is unacceptable.
+ if rewrite.is_none() {
+ return None;
+ }
+ } else {
+ // Checks if rewrite succeeded and fits on a single line.
+ rewrite = and_one_line(rewrite);