refactor rewrite_closure
This commit is contained in:
parent
bb56224d2a
commit
071ca7dc45
@ -9,7 +9,7 @@ use crate::expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewr
|
|||||||
use crate::items::{span_hi_for_param, span_lo_for_param};
|
use crate::items::{span_hi_for_param, span_lo_for_param};
|
||||||
use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
|
use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
|
||||||
use crate::overflow::OverflowableItem;
|
use crate::overflow::OverflowableItem;
|
||||||
use crate::rewrite::{Rewrite, RewriteContext};
|
use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
|
||||||
use crate::shape::Shape;
|
use crate::shape::Shape;
|
||||||
use crate::source_map::SpanUtils;
|
use crate::source_map::SpanUtils;
|
||||||
use crate::types::rewrite_bound_params;
|
use crate::types::rewrite_bound_params;
|
||||||
@ -36,7 +36,7 @@ pub(crate) fn rewrite_closure(
|
|||||||
span: Span,
|
span: Span,
|
||||||
context: &RewriteContext<'_>,
|
context: &RewriteContext<'_>,
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
) -> Option<String> {
|
) -> RewriteResult {
|
||||||
debug!("rewrite_closure {:?}", body);
|
debug!("rewrite_closure {:?}", body);
|
||||||
|
|
||||||
let (prefix, extra_offset) = rewrite_closure_fn_decl(
|
let (prefix, extra_offset) = rewrite_closure_fn_decl(
|
||||||
@ -52,13 +52,15 @@ pub(crate) fn rewrite_closure(
|
|||||||
shape,
|
shape,
|
||||||
)?;
|
)?;
|
||||||
// 1 = space between `|...|` and body.
|
// 1 = space between `|...|` and body.
|
||||||
let body_shape = shape.offset_left(extra_offset)?;
|
let body_shape = shape
|
||||||
|
.offset_left(extra_offset)
|
||||||
|
.max_width_error(shape.width, span)?;
|
||||||
|
|
||||||
if let ast::ExprKind::Block(ref block, _) = body.kind {
|
if let ast::ExprKind::Block(ref block, _) = body.kind {
|
||||||
// The body of the closure is an empty block.
|
// The body of the closure is an empty block.
|
||||||
if block.stmts.is_empty() && !block_contains_comment(context, block) {
|
if block.stmts.is_empty() && !block_contains_comment(context, block) {
|
||||||
return body
|
return body
|
||||||
.rewrite(context, shape)
|
.rewrite_result(context, shape)
|
||||||
.map(|s| format!("{} {}", prefix, s));
|
.map(|s| format!("{} {}", prefix, s));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,15 +68,15 @@ pub(crate) fn rewrite_closure(
|
|||||||
ast::FnRetTy::Default(_) if !context.inside_macro() => {
|
ast::FnRetTy::Default(_) if !context.inside_macro() => {
|
||||||
try_rewrite_without_block(body, &prefix, context, shape, body_shape)
|
try_rewrite_without_block(body, &prefix, context, shape, body_shape)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => Err(RewriteError::Unknown),
|
||||||
};
|
};
|
||||||
|
|
||||||
result.or_else(|| {
|
result.or_else(|_| {
|
||||||
// Either we require a block, or tried without and failed.
|
// Either we require a block, or tried without and failed.
|
||||||
rewrite_closure_block(block, &prefix, context, body_shape)
|
rewrite_closure_block(block, &prefix, context, body_shape)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| {
|
rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|_| {
|
||||||
// The closure originally had a non-block expression, but we can't fit on
|
// The closure originally had a non-block expression, but we can't fit on
|
||||||
// one line, so we'll insert a block.
|
// one line, so we'll insert a block.
|
||||||
rewrite_closure_with_block(body, &prefix, context, body_shape)
|
rewrite_closure_with_block(body, &prefix, context, body_shape)
|
||||||
@ -88,7 +90,7 @@ fn try_rewrite_without_block(
|
|||||||
context: &RewriteContext<'_>,
|
context: &RewriteContext<'_>,
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
body_shape: Shape,
|
body_shape: Shape,
|
||||||
) -> Option<String> {
|
) -> RewriteResult {
|
||||||
let expr = get_inner_expr(expr, prefix, context);
|
let expr = get_inner_expr(expr, prefix, context);
|
||||||
|
|
||||||
if is_block_closure_forced(context, expr) {
|
if is_block_closure_forced(context, expr) {
|
||||||
@ -152,11 +154,11 @@ fn rewrite_closure_with_block(
|
|||||||
prefix: &str,
|
prefix: &str,
|
||||||
context: &RewriteContext<'_>,
|
context: &RewriteContext<'_>,
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
) -> Option<String> {
|
) -> RewriteResult {
|
||||||
let left_most = left_most_sub_expr(body);
|
let left_most = left_most_sub_expr(body);
|
||||||
let veto_block = veto_block(body) && !expr_requires_semi_to_be_stmt(left_most);
|
let veto_block = veto_block(body) && !expr_requires_semi_to_be_stmt(left_most);
|
||||||
if veto_block {
|
if veto_block {
|
||||||
return None;
|
return Err(RewriteError::Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
let block = ast::Block {
|
let block = ast::Block {
|
||||||
@ -183,9 +185,8 @@ fn rewrite_closure_with_block(
|
|||||||
None,
|
None,
|
||||||
shape,
|
shape,
|
||||||
false,
|
false,
|
||||||
)
|
)?;
|
||||||
.ok()?;
|
Ok(format!("{prefix} {block}"))
|
||||||
Some(format!("{prefix} {block}"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewrite closure with a single expression without wrapping its body with block.
|
// Rewrite closure with a single expression without wrapping its body with block.
|
||||||
@ -194,7 +195,7 @@ fn rewrite_closure_expr(
|
|||||||
prefix: &str,
|
prefix: &str,
|
||||||
context: &RewriteContext<'_>,
|
context: &RewriteContext<'_>,
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
) -> Option<String> {
|
) -> RewriteResult {
|
||||||
fn allow_multi_line(expr: &ast::Expr) -> bool {
|
fn allow_multi_line(expr: &ast::Expr) -> bool {
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ast::ExprKind::Match(..)
|
ast::ExprKind::Match(..)
|
||||||
@ -217,12 +218,12 @@ fn rewrite_closure_expr(
|
|||||||
// unless it is a block-like expression or we are inside macro call.
|
// unless it is a block-like expression or we are inside macro call.
|
||||||
let veto_multiline = (!allow_multi_line(expr) && !context.inside_macro())
|
let veto_multiline = (!allow_multi_line(expr) && !context.inside_macro())
|
||||||
|| context.config.force_multiline_blocks();
|
|| context.config.force_multiline_blocks();
|
||||||
expr.rewrite(context, shape)
|
expr.rewrite_result(context, shape)
|
||||||
.and_then(|rw| {
|
.and_then(|rw| {
|
||||||
if veto_multiline && rw.contains('\n') {
|
if veto_multiline && rw.contains('\n') {
|
||||||
None
|
Err(RewriteError::Unknown)
|
||||||
} else {
|
} else {
|
||||||
Some(rw)
|
Ok(rw)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.map(|rw| format!("{} {}", prefix, rw))
|
.map(|rw| format!("{} {}", prefix, rw))
|
||||||
@ -234,8 +235,12 @@ fn rewrite_closure_block(
|
|||||||
prefix: &str,
|
prefix: &str,
|
||||||
context: &RewriteContext<'_>,
|
context: &RewriteContext<'_>,
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
) -> Option<String> {
|
) -> RewriteResult {
|
||||||
Some(format!("{} {}", prefix, block.rewrite(context, shape)?))
|
Ok(format!(
|
||||||
|
"{} {}",
|
||||||
|
prefix,
|
||||||
|
block.rewrite_result(context, shape)?
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return type is (prefix, extra_offset)
|
// Return type is (prefix, extra_offset)
|
||||||
@ -250,13 +255,14 @@ fn rewrite_closure_fn_decl(
|
|||||||
span: Span,
|
span: Span,
|
||||||
context: &RewriteContext<'_>,
|
context: &RewriteContext<'_>,
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
) -> Option<(String, usize)> {
|
) -> Result<(String, usize), RewriteError> {
|
||||||
let binder = match binder {
|
let binder = match binder {
|
||||||
ast::ClosureBinder::For { generic_params, .. } if generic_params.is_empty() => {
|
ast::ClosureBinder::For { generic_params, .. } if generic_params.is_empty() => {
|
||||||
"for<> ".to_owned()
|
"for<> ".to_owned()
|
||||||
}
|
}
|
||||||
ast::ClosureBinder::For { generic_params, .. } => {
|
ast::ClosureBinder::For { generic_params, .. } => {
|
||||||
let lifetime_str = rewrite_bound_params(context, shape, generic_params)?;
|
let lifetime_str =
|
||||||
|
rewrite_bound_params(context, shape, generic_params).unknown_error()?;
|
||||||
format!("for<{lifetime_str}> ")
|
format!("for<{lifetime_str}> ")
|
||||||
}
|
}
|
||||||
ast::ClosureBinder::NotPresent => "".to_owned(),
|
ast::ClosureBinder::NotPresent => "".to_owned(),
|
||||||
@ -287,13 +293,17 @@ fn rewrite_closure_fn_decl(
|
|||||||
// 4 = "|| {".len(), which is overconservative when the closure consists of
|
// 4 = "|| {".len(), which is overconservative when the closure consists of
|
||||||
// a single expression.
|
// a single expression.
|
||||||
let nested_shape = shape
|
let nested_shape = shape
|
||||||
.shrink_left(binder.len() + const_.len() + immovable.len() + coro.len() + mover.len())?
|
.shrink_left(binder.len() + const_.len() + immovable.len() + coro.len() + mover.len())
|
||||||
.sub_width(4)?;
|
.and_then(|shape| shape.sub_width(4))
|
||||||
|
.max_width_error(shape.width, span)?;
|
||||||
|
|
||||||
// 1 = |
|
// 1 = |
|
||||||
let param_offset = nested_shape.indent + 1;
|
let param_offset = nested_shape.indent + 1;
|
||||||
let param_shape = nested_shape.offset_left(1)?.visual_indent(0);
|
let param_shape = nested_shape
|
||||||
let ret_str = fn_decl.output.rewrite(context, param_shape)?;
|
.offset_left(1)
|
||||||
|
.max_width_error(nested_shape.width, span)?
|
||||||
|
.visual_indent(0);
|
||||||
|
let ret_str = fn_decl.output.rewrite_result(context, param_shape)?;
|
||||||
|
|
||||||
let param_items = itemize_list(
|
let param_items = itemize_list(
|
||||||
context.snippet_provider,
|
context.snippet_provider,
|
||||||
@ -317,14 +327,16 @@ fn rewrite_closure_fn_decl(
|
|||||||
horizontal_budget,
|
horizontal_budget,
|
||||||
);
|
);
|
||||||
let param_shape = match tactic {
|
let param_shape = match tactic {
|
||||||
DefinitiveListTactic::Horizontal => param_shape.sub_width(ret_str.len() + 1)?,
|
DefinitiveListTactic::Horizontal => param_shape
|
||||||
|
.sub_width(ret_str.len() + 1)
|
||||||
|
.max_width_error(param_shape.width, span)?,
|
||||||
_ => param_shape,
|
_ => param_shape,
|
||||||
};
|
};
|
||||||
|
|
||||||
let fmt = ListFormatting::new(param_shape, context.config)
|
let fmt = ListFormatting::new(param_shape, context.config)
|
||||||
.tactic(tactic)
|
.tactic(tactic)
|
||||||
.preserve_newline(true);
|
.preserve_newline(true);
|
||||||
let list_str = write_list(&item_vec, &fmt)?;
|
let list_str = write_list(&item_vec, &fmt).unknown_error()?;
|
||||||
let mut prefix = format!("{binder}{const_}{immovable}{coro}{mover}|{list_str}|");
|
let mut prefix = format!("{binder}{const_}{immovable}{coro}{mover}|{list_str}|");
|
||||||
|
|
||||||
if !ret_str.is_empty() {
|
if !ret_str.is_empty() {
|
||||||
@ -339,7 +351,7 @@ fn rewrite_closure_fn_decl(
|
|||||||
// 1 = space between `|...|` and body.
|
// 1 = space between `|...|` and body.
|
||||||
let extra_offset = last_line_width(&prefix) + 1;
|
let extra_offset = last_line_width(&prefix) + 1;
|
||||||
|
|
||||||
Some((prefix, extra_offset))
|
Ok((prefix, extra_offset))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewriting closure which is placed at the end of the function call's arg.
|
// Rewriting closure which is placed at the end of the function call's arg.
|
||||||
@ -348,7 +360,7 @@ pub(crate) fn rewrite_last_closure(
|
|||||||
context: &RewriteContext<'_>,
|
context: &RewriteContext<'_>,
|
||||||
expr: &ast::Expr,
|
expr: &ast::Expr,
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
) -> Option<String> {
|
) -> RewriteResult {
|
||||||
if let ast::ExprKind::Closure(ref closure) = expr.kind {
|
if let ast::ExprKind::Closure(ref closure) = expr.kind {
|
||||||
let ast::Closure {
|
let ast::Closure {
|
||||||
ref binder,
|
ref binder,
|
||||||
@ -385,10 +397,12 @@ pub(crate) fn rewrite_last_closure(
|
|||||||
)?;
|
)?;
|
||||||
// If the closure goes multi line before its body, do not overflow the closure.
|
// If the closure goes multi line before its body, do not overflow the closure.
|
||||||
if prefix.contains('\n') {
|
if prefix.contains('\n') {
|
||||||
return None;
|
return Err(RewriteError::Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
let body_shape = shape.offset_left(extra_offset)?;
|
let body_shape = shape
|
||||||
|
.offset_left(extra_offset)
|
||||||
|
.max_width_error(shape.width, expr.span)?;
|
||||||
|
|
||||||
// We force to use block for the body of the closure for certain kinds of expressions.
|
// We force to use block for the body of the closure for certain kinds of expressions.
|
||||||
if is_block_closure_forced(context, body) {
|
if is_block_closure_forced(context, body) {
|
||||||
@ -400,7 +414,7 @@ pub(crate) fn rewrite_last_closure(
|
|||||||
// closure. However, if the closure has a return type, then we must
|
// closure. However, if the closure has a return type, then we must
|
||||||
// keep the blocks.
|
// keep the blocks.
|
||||||
match rewrite_closure_expr(body, &prefix, context, shape) {
|
match rewrite_closure_expr(body, &prefix, context, shape) {
|
||||||
Some(single_line_body_str)
|
Ok(single_line_body_str)
|
||||||
if !single_line_body_str.contains('\n') =>
|
if !single_line_body_str.contains('\n') =>
|
||||||
{
|
{
|
||||||
single_line_body_str
|
single_line_body_str
|
||||||
@ -424,9 +438,9 @@ pub(crate) fn rewrite_last_closure(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Seems fine, just format the closure in usual manner.
|
// Seems fine, just format the closure in usual manner.
|
||||||
return expr.rewrite(context, shape);
|
return expr.rewrite_result(context, shape);
|
||||||
}
|
}
|
||||||
None
|
Err(RewriteError::Unknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the given vector of arguments has more than one `ast::ExprKind::Closure`.
|
/// Returns `true` if the given vector of arguments has more than one `ast::ExprKind::Closure`.
|
||||||
|
@ -230,7 +230,8 @@ pub(crate) fn format_expr(
|
|||||||
expr.span,
|
expr.span,
|
||||||
context,
|
context,
|
||||||
shape,
|
shape,
|
||||||
),
|
)
|
||||||
|
.ok(),
|
||||||
ast::ExprKind::Try(..)
|
ast::ExprKind::Try(..)
|
||||||
| ast::ExprKind::Field(..)
|
| ast::ExprKind::Field(..)
|
||||||
| ast::ExprKind::MethodCall(..)
|
| ast::ExprKind::MethodCall(..)
|
||||||
|
@ -427,7 +427,7 @@ impl<'a> Context<'a> {
|
|||||||
if closures::args_have_many_closure(&self.items) {
|
if closures::args_have_many_closure(&self.items) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
closures::rewrite_last_closure(self.context, expr, shape)
|
closures::rewrite_last_closure(self.context, expr, shape).ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user