Skip to content

Commit 071ca7d

Browse files
ding-youngytmimi
authored andcommitted
refactor rewrite_closure
1 parent bb56224 commit 071ca7d

File tree

3 files changed

+51
-36
lines changed

3 files changed

+51
-36
lines changed

src/closures.rs

+48-34
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewr
99
use crate::items::{span_hi_for_param, span_lo_for_param};
1010
use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
1111
use crate::overflow::OverflowableItem;
12-
use crate::rewrite::{Rewrite, RewriteContext};
12+
use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
1313
use crate::shape::Shape;
1414
use crate::source_map::SpanUtils;
1515
use crate::types::rewrite_bound_params;
@@ -36,7 +36,7 @@ pub(crate) fn rewrite_closure(
3636
span: Span,
3737
context: &RewriteContext<'_>,
3838
shape: Shape,
39-
) -> Option<String> {
39+
) -> RewriteResult {
4040
debug!("rewrite_closure {:?}", body);
4141

4242
let (prefix, extra_offset) = rewrite_closure_fn_decl(
@@ -52,29 +52,31 @@ pub(crate) fn rewrite_closure(
5252
shape,
5353
)?;
5454
// 1 = space between `|...|` and body.
55-
let body_shape = shape.offset_left(extra_offset)?;
55+
let body_shape = shape
56+
.offset_left(extra_offset)
57+
.max_width_error(shape.width, span)?;
5658

5759
if let ast::ExprKind::Block(ref block, _) = body.kind {
5860
// The body of the closure is an empty block.
5961
if block.stmts.is_empty() && !block_contains_comment(context, block) {
6062
return body
61-
.rewrite(context, shape)
63+
.rewrite_result(context, shape)
6264
.map(|s| format!("{} {}", prefix, s));
6365
}
6466

6567
let result = match fn_decl.output {
6668
ast::FnRetTy::Default(_) if !context.inside_macro() => {
6769
try_rewrite_without_block(body, &prefix, context, shape, body_shape)
6870
}
69-
_ => None,
71+
_ => Err(RewriteError::Unknown),
7072
};
7173

72-
result.or_else(|| {
74+
result.or_else(|_| {
7375
// Either we require a block, or tried without and failed.
7476
rewrite_closure_block(block, &prefix, context, body_shape)
7577
})
7678
} else {
77-
rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| {
79+
rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|_| {
7880
// The closure originally had a non-block expression, but we can't fit on
7981
// one line, so we'll insert a block.
8082
rewrite_closure_with_block(body, &prefix, context, body_shape)
@@ -88,7 +90,7 @@ fn try_rewrite_without_block(
8890
context: &RewriteContext<'_>,
8991
shape: Shape,
9092
body_shape: Shape,
91-
) -> Option<String> {
93+
) -> RewriteResult {
9294
let expr = get_inner_expr(expr, prefix, context);
9395

9496
if is_block_closure_forced(context, expr) {
@@ -152,11 +154,11 @@ fn rewrite_closure_with_block(
152154
prefix: &str,
153155
context: &RewriteContext<'_>,
154156
shape: Shape,
155-
) -> Option<String> {
157+
) -> RewriteResult {
156158
let left_most = left_most_sub_expr(body);
157159
let veto_block = veto_block(body) && !expr_requires_semi_to_be_stmt(left_most);
158160
if veto_block {
159-
return None;
161+
return Err(RewriteError::Unknown);
160162
}
161163

162164
let block = ast::Block {
@@ -183,9 +185,8 @@ fn rewrite_closure_with_block(
183185
None,
184186
shape,
185187
false,
186-
)
187-
.ok()?;
188-
Some(format!("{prefix} {block}"))
188+
)?;
189+
Ok(format!("{prefix} {block}"))
189190
}
190191

191192
// Rewrite closure with a single expression without wrapping its body with block.
@@ -194,7 +195,7 @@ fn rewrite_closure_expr(
194195
prefix: &str,
195196
context: &RewriteContext<'_>,
196197
shape: Shape,
197-
) -> Option<String> {
198+
) -> RewriteResult {
198199
fn allow_multi_line(expr: &ast::Expr) -> bool {
199200
match expr.kind {
200201
ast::ExprKind::Match(..)
@@ -217,12 +218,12 @@ fn rewrite_closure_expr(
217218
// unless it is a block-like expression or we are inside macro call.
218219
let veto_multiline = (!allow_multi_line(expr) && !context.inside_macro())
219220
|| context.config.force_multiline_blocks();
220-
expr.rewrite(context, shape)
221+
expr.rewrite_result(context, shape)
221222
.and_then(|rw| {
222223
if veto_multiline && rw.contains('\n') {
223-
None
224+
Err(RewriteError::Unknown)
224225
} else {
225-
Some(rw)
226+
Ok(rw)
226227
}
227228
})
228229
.map(|rw| format!("{} {}", prefix, rw))
@@ -234,8 +235,12 @@ fn rewrite_closure_block(
234235
prefix: &str,
235236
context: &RewriteContext<'_>,
236237
shape: Shape,
237-
) -> Option<String> {
238-
Some(format!("{} {}", prefix, block.rewrite(context, shape)?))
238+
) -> RewriteResult {
239+
Ok(format!(
240+
"{} {}",
241+
prefix,
242+
block.rewrite_result(context, shape)?
243+
))
239244
}
240245

241246
// Return type is (prefix, extra_offset)
@@ -250,13 +255,14 @@ fn rewrite_closure_fn_decl(
250255
span: Span,
251256
context: &RewriteContext<'_>,
252257
shape: Shape,
253-
) -> Option<(String, usize)> {
258+
) -> Result<(String, usize), RewriteError> {
254259
let binder = match binder {
255260
ast::ClosureBinder::For { generic_params, .. } if generic_params.is_empty() => {
256261
"for<> ".to_owned()
257262
}
258263
ast::ClosureBinder::For { generic_params, .. } => {
259-
let lifetime_str = rewrite_bound_params(context, shape, generic_params)?;
264+
let lifetime_str =
265+
rewrite_bound_params(context, shape, generic_params).unknown_error()?;
260266
format!("for<{lifetime_str}> ")
261267
}
262268
ast::ClosureBinder::NotPresent => "".to_owned(),
@@ -287,13 +293,17 @@ fn rewrite_closure_fn_decl(
287293
// 4 = "|| {".len(), which is overconservative when the closure consists of
288294
// a single expression.
289295
let nested_shape = shape
290-
.shrink_left(binder.len() + const_.len() + immovable.len() + coro.len() + mover.len())?
291-
.sub_width(4)?;
296+
.shrink_left(binder.len() + const_.len() + immovable.len() + coro.len() + mover.len())
297+
.and_then(|shape| shape.sub_width(4))
298+
.max_width_error(shape.width, span)?;
292299

293300
// 1 = |
294301
let param_offset = nested_shape.indent + 1;
295-
let param_shape = nested_shape.offset_left(1)?.visual_indent(0);
296-
let ret_str = fn_decl.output.rewrite(context, param_shape)?;
302+
let param_shape = nested_shape
303+
.offset_left(1)
304+
.max_width_error(nested_shape.width, span)?
305+
.visual_indent(0);
306+
let ret_str = fn_decl.output.rewrite_result(context, param_shape)?;
297307

298308
let param_items = itemize_list(
299309
context.snippet_provider,
@@ -317,14 +327,16 @@ fn rewrite_closure_fn_decl(
317327
horizontal_budget,
318328
);
319329
let param_shape = match tactic {
320-
DefinitiveListTactic::Horizontal => param_shape.sub_width(ret_str.len() + 1)?,
330+
DefinitiveListTactic::Horizontal => param_shape
331+
.sub_width(ret_str.len() + 1)
332+
.max_width_error(param_shape.width, span)?,
321333
_ => param_shape,
322334
};
323335

324336
let fmt = ListFormatting::new(param_shape, context.config)
325337
.tactic(tactic)
326338
.preserve_newline(true);
327-
let list_str = write_list(&item_vec, &fmt)?;
339+
let list_str = write_list(&item_vec, &fmt).unknown_error()?;
328340
let mut prefix = format!("{binder}{const_}{immovable}{coro}{mover}|{list_str}|");
329341

330342
if !ret_str.is_empty() {
@@ -339,7 +351,7 @@ fn rewrite_closure_fn_decl(
339351
// 1 = space between `|...|` and body.
340352
let extra_offset = last_line_width(&prefix) + 1;
341353

342-
Some((prefix, extra_offset))
354+
Ok((prefix, extra_offset))
343355
}
344356

345357
// Rewriting closure which is placed at the end of the function call's arg.
@@ -348,7 +360,7 @@ pub(crate) fn rewrite_last_closure(
348360
context: &RewriteContext<'_>,
349361
expr: &ast::Expr,
350362
shape: Shape,
351-
) -> Option<String> {
363+
) -> RewriteResult {
352364
if let ast::ExprKind::Closure(ref closure) = expr.kind {
353365
let ast::Closure {
354366
ref binder,
@@ -385,10 +397,12 @@ pub(crate) fn rewrite_last_closure(
385397
)?;
386398
// If the closure goes multi line before its body, do not overflow the closure.
387399
if prefix.contains('\n') {
388-
return None;
400+
return Err(RewriteError::Unknown);
389401
}
390402

391-
let body_shape = shape.offset_left(extra_offset)?;
403+
let body_shape = shape
404+
.offset_left(extra_offset)
405+
.max_width_error(shape.width, expr.span)?;
392406

393407
// We force to use block for the body of the closure for certain kinds of expressions.
394408
if is_block_closure_forced(context, body) {
@@ -400,7 +414,7 @@ pub(crate) fn rewrite_last_closure(
400414
// closure. However, if the closure has a return type, then we must
401415
// keep the blocks.
402416
match rewrite_closure_expr(body, &prefix, context, shape) {
403-
Some(single_line_body_str)
417+
Ok(single_line_body_str)
404418
if !single_line_body_str.contains('\n') =>
405419
{
406420
single_line_body_str
@@ -424,9 +438,9 @@ pub(crate) fn rewrite_last_closure(
424438
}
425439

426440
// Seems fine, just format the closure in usual manner.
427-
return expr.rewrite(context, shape);
441+
return expr.rewrite_result(context, shape);
428442
}
429-
None
443+
Err(RewriteError::Unknown)
430444
}
431445

432446
/// Returns `true` if the given vector of arguments has more than one `ast::ExprKind::Closure`.

src/expr.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ pub(crate) fn format_expr(
230230
expr.span,
231231
context,
232232
shape,
233-
),
233+
)
234+
.ok(),
234235
ast::ExprKind::Try(..)
235236
| ast::ExprKind::Field(..)
236237
| ast::ExprKind::MethodCall(..)

src/overflow.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ impl<'a> Context<'a> {
427427
if closures::args_have_many_closure(&self.items) {
428428
None
429429
} else {
430-
closures::rewrite_last_closure(self.context, expr, shape)
430+
closures::rewrite_last_closure(self.context, expr, shape).ok()
431431
}
432432
}
433433

0 commit comments

Comments
 (0)