@@ -9,7 +9,7 @@ use crate::expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewr
9
9
use crate :: items:: { span_hi_for_param, span_lo_for_param} ;
10
10
use crate :: lists:: { definitive_tactic, itemize_list, write_list, ListFormatting , Separator } ;
11
11
use crate :: overflow:: OverflowableItem ;
12
- use crate :: rewrite:: { Rewrite , RewriteContext } ;
12
+ use crate :: rewrite:: { Rewrite , RewriteContext , RewriteError , RewriteErrorExt , RewriteResult } ;
13
13
use crate :: shape:: Shape ;
14
14
use crate :: source_map:: SpanUtils ;
15
15
use crate :: types:: rewrite_bound_params;
@@ -36,7 +36,7 @@ pub(crate) fn rewrite_closure(
36
36
span : Span ,
37
37
context : & RewriteContext < ' _ > ,
38
38
shape : Shape ,
39
- ) -> Option < String > {
39
+ ) -> RewriteResult {
40
40
debug ! ( "rewrite_closure {:?}" , body) ;
41
41
42
42
let ( prefix, extra_offset) = rewrite_closure_fn_decl (
@@ -52,29 +52,31 @@ pub(crate) fn rewrite_closure(
52
52
shape,
53
53
) ?;
54
54
// 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) ?;
56
58
57
59
if let ast:: ExprKind :: Block ( ref block, _) = body. kind {
58
60
// The body of the closure is an empty block.
59
61
if block. stmts . is_empty ( ) && !block_contains_comment ( context, block) {
60
62
return body
61
- . rewrite ( context, shape)
63
+ . rewrite_result ( context, shape)
62
64
. map ( |s| format ! ( "{} {}" , prefix, s) ) ;
63
65
}
64
66
65
67
let result = match fn_decl. output {
66
68
ast:: FnRetTy :: Default ( _) if !context. inside_macro ( ) => {
67
69
try_rewrite_without_block ( body, & prefix, context, shape, body_shape)
68
70
}
69
- _ => None ,
71
+ _ => Err ( RewriteError :: Unknown ) ,
70
72
} ;
71
73
72
- result. or_else ( || {
74
+ result. or_else ( |_ | {
73
75
// Either we require a block, or tried without and failed.
74
76
rewrite_closure_block ( block, & prefix, context, body_shape)
75
77
} )
76
78
} else {
77
- rewrite_closure_expr ( body, & prefix, context, body_shape) . or_else ( || {
79
+ rewrite_closure_expr ( body, & prefix, context, body_shape) . or_else ( |_ | {
78
80
// The closure originally had a non-block expression, but we can't fit on
79
81
// one line, so we'll insert a block.
80
82
rewrite_closure_with_block ( body, & prefix, context, body_shape)
@@ -88,7 +90,7 @@ fn try_rewrite_without_block(
88
90
context : & RewriteContext < ' _ > ,
89
91
shape : Shape ,
90
92
body_shape : Shape ,
91
- ) -> Option < String > {
93
+ ) -> RewriteResult {
92
94
let expr = get_inner_expr ( expr, prefix, context) ;
93
95
94
96
if is_block_closure_forced ( context, expr) {
@@ -152,11 +154,11 @@ fn rewrite_closure_with_block(
152
154
prefix : & str ,
153
155
context : & RewriteContext < ' _ > ,
154
156
shape : Shape ,
155
- ) -> Option < String > {
157
+ ) -> RewriteResult {
156
158
let left_most = left_most_sub_expr ( body) ;
157
159
let veto_block = veto_block ( body) && !expr_requires_semi_to_be_stmt ( left_most) ;
158
160
if veto_block {
159
- return None ;
161
+ return Err ( RewriteError :: Unknown ) ;
160
162
}
161
163
162
164
let block = ast:: Block {
@@ -183,9 +185,8 @@ fn rewrite_closure_with_block(
183
185
None ,
184
186
shape,
185
187
false ,
186
- )
187
- . ok ( ) ?;
188
- Some ( format ! ( "{prefix} {block}" ) )
188
+ ) ?;
189
+ Ok ( format ! ( "{prefix} {block}" ) )
189
190
}
190
191
191
192
// Rewrite closure with a single expression without wrapping its body with block.
@@ -194,7 +195,7 @@ fn rewrite_closure_expr(
194
195
prefix : & str ,
195
196
context : & RewriteContext < ' _ > ,
196
197
shape : Shape ,
197
- ) -> Option < String > {
198
+ ) -> RewriteResult {
198
199
fn allow_multi_line ( expr : & ast:: Expr ) -> bool {
199
200
match expr. kind {
200
201
ast:: ExprKind :: Match ( ..)
@@ -217,12 +218,12 @@ fn rewrite_closure_expr(
217
218
// unless it is a block-like expression or we are inside macro call.
218
219
let veto_multiline = ( !allow_multi_line ( expr) && !context. inside_macro ( ) )
219
220
|| context. config . force_multiline_blocks ( ) ;
220
- expr. rewrite ( context, shape)
221
+ expr. rewrite_result ( context, shape)
221
222
. and_then ( |rw| {
222
223
if veto_multiline && rw. contains ( '\n' ) {
223
- None
224
+ Err ( RewriteError :: Unknown )
224
225
} else {
225
- Some ( rw)
226
+ Ok ( rw)
226
227
}
227
228
} )
228
229
. map ( |rw| format ! ( "{} {}" , prefix, rw) )
@@ -234,8 +235,12 @@ fn rewrite_closure_block(
234
235
prefix : & str ,
235
236
context : & RewriteContext < ' _ > ,
236
237
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
+ ) )
239
244
}
240
245
241
246
// Return type is (prefix, extra_offset)
@@ -250,13 +255,14 @@ fn rewrite_closure_fn_decl(
250
255
span : Span ,
251
256
context : & RewriteContext < ' _ > ,
252
257
shape : Shape ,
253
- ) -> Option < ( String , usize ) > {
258
+ ) -> Result < ( String , usize ) , RewriteError > {
254
259
let binder = match binder {
255
260
ast:: ClosureBinder :: For { generic_params, .. } if generic_params. is_empty ( ) => {
256
261
"for<> " . to_owned ( )
257
262
}
258
263
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 ( ) ?;
260
266
format ! ( "for<{lifetime_str}> " )
261
267
}
262
268
ast:: ClosureBinder :: NotPresent => "" . to_owned ( ) ,
@@ -287,13 +293,17 @@ fn rewrite_closure_fn_decl(
287
293
// 4 = "|| {".len(), which is overconservative when the closure consists of
288
294
// a single expression.
289
295
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) ?;
292
299
293
300
// 1 = |
294
301
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) ?;
297
307
298
308
let param_items = itemize_list (
299
309
context. snippet_provider ,
@@ -317,14 +327,16 @@ fn rewrite_closure_fn_decl(
317
327
horizontal_budget,
318
328
) ;
319
329
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) ?,
321
333
_ => param_shape,
322
334
} ;
323
335
324
336
let fmt = ListFormatting :: new ( param_shape, context. config )
325
337
. tactic ( tactic)
326
338
. preserve_newline ( true ) ;
327
- let list_str = write_list ( & item_vec, & fmt) ?;
339
+ let list_str = write_list ( & item_vec, & fmt) . unknown_error ( ) ?;
328
340
let mut prefix = format ! ( "{binder}{const_}{immovable}{coro}{mover}|{list_str}|" ) ;
329
341
330
342
if !ret_str. is_empty ( ) {
@@ -339,7 +351,7 @@ fn rewrite_closure_fn_decl(
339
351
// 1 = space between `|...|` and body.
340
352
let extra_offset = last_line_width ( & prefix) + 1 ;
341
353
342
- Some ( ( prefix, extra_offset) )
354
+ Ok ( ( prefix, extra_offset) )
343
355
}
344
356
345
357
// Rewriting closure which is placed at the end of the function call's arg.
@@ -348,7 +360,7 @@ pub(crate) fn rewrite_last_closure(
348
360
context : & RewriteContext < ' _ > ,
349
361
expr : & ast:: Expr ,
350
362
shape : Shape ,
351
- ) -> Option < String > {
363
+ ) -> RewriteResult {
352
364
if let ast:: ExprKind :: Closure ( ref closure) = expr. kind {
353
365
let ast:: Closure {
354
366
ref binder,
@@ -385,10 +397,12 @@ pub(crate) fn rewrite_last_closure(
385
397
) ?;
386
398
// If the closure goes multi line before its body, do not overflow the closure.
387
399
if prefix. contains ( '\n' ) {
388
- return None ;
400
+ return Err ( RewriteError :: Unknown ) ;
389
401
}
390
402
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 ) ?;
392
406
393
407
// We force to use block for the body of the closure for certain kinds of expressions.
394
408
if is_block_closure_forced ( context, body) {
@@ -400,7 +414,7 @@ pub(crate) fn rewrite_last_closure(
400
414
// closure. However, if the closure has a return type, then we must
401
415
// keep the blocks.
402
416
match rewrite_closure_expr ( body, & prefix, context, shape) {
403
- Some ( single_line_body_str)
417
+ Ok ( single_line_body_str)
404
418
if !single_line_body_str. contains ( '\n' ) =>
405
419
{
406
420
single_line_body_str
@@ -424,9 +438,9 @@ pub(crate) fn rewrite_last_closure(
424
438
}
425
439
426
440
// Seems fine, just format the closure in usual manner.
427
- return expr. rewrite ( context, shape) ;
441
+ return expr. rewrite_result ( context, shape) ;
428
442
}
429
- None
443
+ Err ( RewriteError :: Unknown )
430
444
}
431
445
432
446
/// Returns `true` if the given vector of arguments has more than one `ast::ExprKind::Closure`.
0 commit comments