Skip to content

Commit b504a18

Browse files
committed
implement rustfmt formatting for for<> closure binders
1 parent d2923b4 commit b504a18

File tree

4 files changed

+40
-13
lines changed

4 files changed

+40
-13
lines changed

src/tools/rustfmt/src/closures.rs

+27-6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::overflow::OverflowableItem;
1111
use crate::rewrite::{Rewrite, RewriteContext};
1212
use crate::shape::Shape;
1313
use crate::source_map::SpanUtils;
14+
use crate::types::rewrite_lifetime_param;
1415
use crate::utils::{last_line_width, left_most_sub_expr, stmt_expr, NodeIdExt};
1516

1617
// This module is pretty messy because of the rules around closures and blocks:
@@ -24,6 +25,7 @@ use crate::utils::{last_line_width, left_most_sub_expr, stmt_expr, NodeIdExt};
2425
// can change whether it is treated as an expression or statement.
2526

2627
pub(crate) fn rewrite_closure(
28+
binder: &ast::ClosureBinder,
2729
capture: ast::CaptureBy,
2830
is_async: &ast::Async,
2931
movability: ast::Movability,
@@ -36,7 +38,7 @@ pub(crate) fn rewrite_closure(
3638
debug!("rewrite_closure {:?}", body);
3739

3840
let (prefix, extra_offset) = rewrite_closure_fn_decl(
39-
capture, is_async, movability, fn_decl, body, span, context, shape,
41+
binder, capture, is_async, movability, fn_decl, body, span, context, shape,
4042
)?;
4143
// 1 = space between `|...|` and body.
4244
let body_shape = shape.offset_left(extra_offset)?;
@@ -227,6 +229,7 @@ fn rewrite_closure_block(
227229

228230
// Return type is (prefix, extra_offset)
229231
fn rewrite_closure_fn_decl(
232+
binder: &ast::ClosureBinder,
230233
capture: ast::CaptureBy,
231234
asyncness: &ast::Async,
232235
movability: ast::Movability,
@@ -236,6 +239,17 @@ fn rewrite_closure_fn_decl(
236239
context: &RewriteContext<'_>,
237240
shape: Shape,
238241
) -> Option<(String, usize)> {
242+
let binder = match binder {
243+
ast::ClosureBinder::For { generic_params, .. } if generic_params.is_empty() => {
244+
"for<> ".to_owned()
245+
}
246+
ast::ClosureBinder::For { generic_params, .. } => {
247+
let lifetime_str = rewrite_lifetime_param(context, shape, generic_params)?;
248+
format!("for<{lifetime_str}> ")
249+
}
250+
ast::ClosureBinder::NotPresent => "".to_owned(),
251+
};
252+
239253
let immovable = if movability == ast::Movability::Static {
240254
"static "
241255
} else {
@@ -250,7 +264,7 @@ fn rewrite_closure_fn_decl(
250264
// 4 = "|| {".len(), which is overconservative when the closure consists of
251265
// a single expression.
252266
let nested_shape = shape
253-
.shrink_left(immovable.len() + is_async.len() + mover.len())?
267+
.shrink_left(binder.len() + immovable.len() + is_async.len() + mover.len())?
254268
.sub_width(4)?;
255269

256270
// 1 = |
@@ -288,7 +302,7 @@ fn rewrite_closure_fn_decl(
288302
.tactic(tactic)
289303
.preserve_newline(true);
290304
let list_str = write_list(&item_vec, &fmt)?;
291-
let mut prefix = format!("{}{}{}|{}|", immovable, is_async, mover, list_str);
305+
let mut prefix = format!("{}{}{}{}|{}|", binder, immovable, is_async, mover, list_str);
292306

293307
if !ret_str.is_empty() {
294308
if prefix.contains('\n') {
@@ -312,8 +326,15 @@ pub(crate) fn rewrite_last_closure(
312326
expr: &ast::Expr,
313327
shape: Shape,
314328
) -> Option<String> {
315-
if let ast::ExprKind::Closure(capture, ref is_async, movability, ref fn_decl, ref body, _) =
316-
expr.kind
329+
if let ast::ExprKind::Closure(
330+
ref binder,
331+
capture,
332+
ref is_async,
333+
movability,
334+
ref fn_decl,
335+
ref body,
336+
_,
337+
) = expr.kind
317338
{
318339
let body = match body.kind {
319340
ast::ExprKind::Block(ref block, _)
@@ -326,7 +347,7 @@ pub(crate) fn rewrite_last_closure(
326347
_ => body,
327348
};
328349
let (prefix, extra_offset) = rewrite_closure_fn_decl(
329-
capture, is_async, movability, fn_decl, body, expr.span, context, shape,
350+
binder, capture, is_async, movability, fn_decl, body, expr.span, context, shape,
330351
)?;
331352
// If the closure goes multi line before its body, do not overflow the closure.
332353
if prefix.contains('\n') {

src/tools/rustfmt/src/expr.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,17 @@ pub(crate) fn format_expr(
203203
Some("yield".to_string())
204204
}
205205
}
206-
ast::ExprKind::Closure(capture, ref is_async, movability, ref fn_decl, ref body, _) => {
207-
closures::rewrite_closure(
208-
capture, is_async, movability, fn_decl, body, expr.span, context, shape,
209-
)
210-
}
206+
ast::ExprKind::Closure(
207+
ref binder,
208+
capture,
209+
ref is_async,
210+
movability,
211+
ref fn_decl,
212+
ref body,
213+
_,
214+
) => closures::rewrite_closure(
215+
binder, capture, is_async, movability, fn_decl, body, expr.span, context, shape,
216+
),
211217
ast::ExprKind::Try(..)
212218
| ast::ExprKind::Field(..)
213219
| ast::ExprKind::MethodCall(..)

src/tools/rustfmt/src/types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1067,7 +1067,7 @@ pub(crate) fn can_be_overflowed_type(
10671067
}
10681068

10691069
/// Returns `None` if there is no `LifetimeDef` in the given generic parameters.
1070-
fn rewrite_lifetime_param(
1070+
pub(crate) fn rewrite_lifetime_param(
10711071
context: &RewriteContext<'_>,
10721072
shape: Shape,
10731073
generic_params: &[ast::GenericParam],

src/tools/rustfmt/src/utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr
479479
| ast::ExprKind::Binary(_, _, ref expr)
480480
| ast::ExprKind::Index(_, ref expr)
481481
| ast::ExprKind::Unary(_, ref expr)
482-
| ast::ExprKind::Closure(_, _, _, _, ref expr, _)
482+
| ast::ExprKind::Closure(_, _, _, _, _, ref expr, _)
483483
| ast::ExprKind::Try(ref expr)
484484
| ast::ExprKind::Yield(Some(ref expr)) => is_block_expr(context, expr, repr),
485485
// This can only be a string lit

0 commit comments

Comments
 (0)