1use std::cmp::min;
4
5use itertools::Itertools;
6use rustc_ast::token::Delimiter;
7use rustc_ast::{ast, ptr};
8use rustc_span::Span;
9use tracing::debug;
10
11use crate::closures;
12use crate::config::StyleEdition;
13use crate::config::{Config, lists::*};
14use crate::expr::{
15 can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, is_simple_expr,
16 rewrite_cond,
17};
18use crate::lists::{
19 ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list,
20};
21use crate::macros::MacroArg;
22use crate::patterns::{TuplePatField, can_be_overflowed_pat};
23use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
24use crate::shape::Shape;
25use crate::source_map::SpanUtils;
26use crate::spanned::Spanned;
27use crate::types::{SegmentParam, can_be_overflowed_type};
28use crate::utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp};
29
30const SPECIAL_CASE_MACROS: &[(&str, usize)] = &[
37 ("eprint!", 0),
40 ("eprintln!", 0),
41 ("format!", 0),
42 ("format_args!", 0),
43 ("print!", 0),
44 ("println!", 0),
45 ("panic!", 0),
46 ("unreachable!", 0),
47 ("debug!", 0),
49 ("error!", 0),
50 ("info!", 0),
51 ("warn!", 0),
52 ("assert!", 1),
54 ("debug_assert!", 1),
55 ("write!", 1),
56 ("writeln!", 1),
57 ("assert_eq!", 2),
59 ("assert_ne!", 2),
60 ("debug_assert_eq!", 2),
61 ("debug_assert_ne!", 2),
62];
63
64const SPECIAL_CASE_MACROS_V2: &[(&str, usize)] = &[
67 ("trace!", 0),
69];
70
71const SPECIAL_CASE_ATTR: &[(&str, usize)] = &[
72 ("fail", 0),
74];
75
76#[derive(Debug)]
77pub(crate) enum OverflowableItem<'a> {
78 Expr(&'a ast::Expr),
79 GenericParam(&'a ast::GenericParam),
80 MacroArg(&'a MacroArg),
81 MetaItemInner(&'a ast::MetaItemInner),
82 SegmentParam(&'a SegmentParam<'a>),
83 FieldDef(&'a ast::FieldDef),
84 TuplePatField(&'a TuplePatField<'a>),
85 Ty(&'a ast::Ty),
86 Pat(&'a ast::Pat),
87 PreciseCapturingArg(&'a ast::PreciseCapturingArg),
88}
89
90impl<'a> Rewrite for OverflowableItem<'a> {
91 fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
92 self.map(|item| item.rewrite(context, shape))
93 }
94
95 fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
96 self.map(|item| item.rewrite_result(context, shape))
97 }
98}
99
100impl<'a> Spanned for OverflowableItem<'a> {
101 fn span(&self) -> Span {
102 self.map(|item| item.span())
103 }
104}
105
106impl<'a> OverflowableItem<'a> {
107 fn has_attrs(&self) -> bool {
108 match self {
109 OverflowableItem::Expr(ast::Expr { attrs, .. })
110 | OverflowableItem::GenericParam(ast::GenericParam { attrs, .. }) => !attrs.is_empty(),
111 OverflowableItem::FieldDef(ast::FieldDef { attrs, .. }) => !attrs.is_empty(),
112 OverflowableItem::MacroArg(MacroArg::Expr(expr)) => !expr.attrs.is_empty(),
113 OverflowableItem::MacroArg(MacroArg::Item(item)) => !item.attrs.is_empty(),
114 _ => false,
115 }
116 }
117
118 pub(crate) fn map<F, T>(&self, f: F) -> T
119 where
120 F: Fn(&dyn IntoOverflowableItem<'a>) -> T,
121 {
122 match self {
123 OverflowableItem::Expr(expr) => f(*expr),
124 OverflowableItem::GenericParam(gp) => f(*gp),
125 OverflowableItem::MacroArg(macro_arg) => f(*macro_arg),
126 OverflowableItem::MetaItemInner(nmi) => f(*nmi),
127 OverflowableItem::SegmentParam(sp) => f(*sp),
128 OverflowableItem::FieldDef(sf) => f(*sf),
129 OverflowableItem::TuplePatField(pat) => f(*pat),
130 OverflowableItem::Ty(ty) => f(*ty),
131 OverflowableItem::Pat(pat) => f(*pat),
132 OverflowableItem::PreciseCapturingArg(arg) => f(*arg),
133 }
134 }
135
136 pub(crate) fn is_simple(&self) -> bool {
137 match self {
138 OverflowableItem::Expr(expr) => is_simple_expr(expr),
139 OverflowableItem::MacroArg(MacroArg::Keyword(..)) => true,
140 OverflowableItem::MacroArg(MacroArg::Expr(expr)) => is_simple_expr(expr),
141 OverflowableItem::MetaItemInner(meta_item_inner) => match meta_item_inner {
142 ast::MetaItemInner::Lit(..) => true,
143 ast::MetaItemInner::MetaItem(ref meta_item) => {
144 matches!(meta_item.kind, ast::MetaItemKind::Word)
145 }
146 },
147 _ => false,
151 }
152 }
153
154 pub(crate) fn is_expr(&self) -> bool {
155 matches!(
156 self,
157 OverflowableItem::Expr(..) | OverflowableItem::MacroArg(MacroArg::Expr(..))
158 )
159 }
160
161 pub(crate) fn is_nested_call(&self) -> bool {
162 match self {
163 OverflowableItem::Expr(expr) => is_nested_call(expr),
164 OverflowableItem::MacroArg(MacroArg::Expr(expr)) => is_nested_call(expr),
165 _ => false,
166 }
167 }
168
169 pub(crate) fn to_expr(&self) -> Option<&'a ast::Expr> {
170 match self {
171 OverflowableItem::Expr(expr) => Some(expr),
172 OverflowableItem::MacroArg(MacroArg::Expr(ref expr)) => Some(expr),
173 _ => None,
174 }
175 }
176
177 pub(crate) fn can_be_overflowed(&self, context: &RewriteContext<'_>, len: usize) -> bool {
178 match self {
179 OverflowableItem::Expr(expr) => can_be_overflowed_expr(context, expr, len),
180 OverflowableItem::MacroArg(macro_arg) => match macro_arg {
181 MacroArg::Expr(ref expr) => can_be_overflowed_expr(context, expr, len),
182 MacroArg::Ty(ref ty) => can_be_overflowed_type(context, ty, len),
183 MacroArg::Pat(..) => false,
184 MacroArg::Item(..) => len == 1,
185 MacroArg::Keyword(..) => false,
186 },
187 OverflowableItem::MetaItemInner(meta_item_inner) if len == 1 => match meta_item_inner {
188 ast::MetaItemInner::Lit(..) => false,
189 ast::MetaItemInner::MetaItem(..) => true,
190 },
191 OverflowableItem::SegmentParam(SegmentParam::Type(ty)) => {
192 can_be_overflowed_type(context, ty, len)
193 }
194 OverflowableItem::TuplePatField(pat) => can_be_overflowed_pat(context, pat, len),
195 OverflowableItem::Ty(ty) => can_be_overflowed_type(context, ty, len),
196 _ => false,
197 }
198 }
199
200 fn special_cases(&self, config: &Config) -> impl Iterator<Item = &(&'static str, usize)> {
201 let base_cases = match self {
202 OverflowableItem::MacroArg(..) => SPECIAL_CASE_MACROS,
203 OverflowableItem::MetaItemInner(..) => SPECIAL_CASE_ATTR,
204 _ => &[],
205 };
206 let additional_cases = match self {
207 OverflowableItem::MacroArg(..)
208 if config.style_edition() >= StyleEdition::Edition2024 =>
209 {
210 SPECIAL_CASE_MACROS_V2
211 }
212 _ => &[],
213 };
214 base_cases.iter().chain(additional_cases)
215 }
216}
217
218pub(crate) trait IntoOverflowableItem<'a>: Rewrite + Spanned {
219 fn into_overflowable_item(&'a self) -> OverflowableItem<'a>;
220}
221
222impl<'a, T: 'a + IntoOverflowableItem<'a>> IntoOverflowableItem<'a> for ptr::P<T> {
223 fn into_overflowable_item(&'a self) -> OverflowableItem<'a> {
224 (**self).into_overflowable_item()
225 }
226}
227
228macro_rules! impl_into_overflowable_item_for_ast_node {
229 ($($ast_node:ident),*) => {
230 $(
231 impl<'a> IntoOverflowableItem<'a> for ast::$ast_node {
232 fn into_overflowable_item(&'a self) -> OverflowableItem<'a> {
233 OverflowableItem::$ast_node(self)
234 }
235 }
236 )*
237 }
238}
239
240macro_rules! impl_into_overflowable_item_for_rustfmt_types {
241 ([$($ty:ident),*], [$($ty_with_lifetime:ident),*]) => {
242 $(
243 impl<'a> IntoOverflowableItem<'a> for $ty {
244 fn into_overflowable_item(&'a self) -> OverflowableItem<'a> {
245 OverflowableItem::$ty(self)
246 }
247 }
248 )*
249 $(
250 impl<'a> IntoOverflowableItem<'a> for $ty_with_lifetime<'a> {
251 fn into_overflowable_item(&'a self) -> OverflowableItem<'a> {
252 OverflowableItem::$ty_with_lifetime(self)
253 }
254 }
255 )*
256 }
257}
258
259impl_into_overflowable_item_for_ast_node!(
260 Expr,
261 GenericParam,
262 MetaItemInner,
263 FieldDef,
264 Ty,
265 Pat,
266 PreciseCapturingArg
267);
268impl_into_overflowable_item_for_rustfmt_types!([MacroArg], [SegmentParam, TuplePatField]);
269
270pub(crate) fn into_overflowable_list<'a, T>(
271 iter: impl Iterator<Item = &'a T>,
272) -> impl Iterator<Item = OverflowableItem<'a>>
273where
274 T: 'a + IntoOverflowableItem<'a>,
275{
276 iter.map(|x| IntoOverflowableItem::into_overflowable_item(x))
277}
278
279pub(crate) fn rewrite_with_parens<'a, T: 'a + IntoOverflowableItem<'a>>(
280 context: &'a RewriteContext<'_>,
281 ident: &'a str,
282 items: impl Iterator<Item = &'a T>,
283 shape: Shape,
284 span: Span,
285 item_max_width: usize,
286 force_separator_tactic: Option<SeparatorTactic>,
287) -> RewriteResult {
288 Context::new(
289 context,
290 items,
291 ident,
292 shape,
293 span,
294 "(",
295 ")",
296 item_max_width,
297 force_separator_tactic,
298 None,
299 )
300 .rewrite(shape)
301}
302
303pub(crate) fn rewrite_with_angle_brackets<'a, T: 'a + IntoOverflowableItem<'a>>(
304 context: &'a RewriteContext<'_>,
305 ident: &'a str,
306 items: impl Iterator<Item = &'a T>,
307 shape: Shape,
308 span: Span,
309) -> RewriteResult {
310 Context::new(
311 context,
312 items,
313 ident,
314 shape,
315 span,
316 "<",
317 ">",
318 context.config.max_width(),
319 None,
320 None,
321 )
322 .rewrite(shape)
323}
324
325pub(crate) fn rewrite_with_square_brackets<'a, T: 'a + IntoOverflowableItem<'a>>(
326 context: &'a RewriteContext<'_>,
327 name: &'a str,
328 items: impl Iterator<Item = &'a T>,
329 shape: Shape,
330 span: Span,
331 force_separator_tactic: Option<SeparatorTactic>,
332 delim_token: Option<Delimiter>,
333) -> RewriteResult {
334 let (lhs, rhs) = match delim_token {
335 Some(Delimiter::Parenthesis) => ("(", ")"),
336 Some(Delimiter::Brace) => ("{", "}"),
337 _ => ("[", "]"),
338 };
339 Context::new(
340 context,
341 items,
342 name,
343 shape,
344 span,
345 lhs,
346 rhs,
347 context.config.array_width(),
348 force_separator_tactic,
349 Some(("[", "]")),
350 )
351 .rewrite(shape)
352}
353
354struct Context<'a> {
355 context: &'a RewriteContext<'a>,
356 items: Vec<OverflowableItem<'a>>,
357 ident: &'a str,
358 prefix: &'static str,
359 suffix: &'static str,
360 one_line_shape: Shape,
361 nested_shape: Shape,
362 span: Span,
363 item_max_width: usize,
364 one_line_width: usize,
365 force_separator_tactic: Option<SeparatorTactic>,
366 custom_delims: Option<(&'a str, &'a str)>,
367}
368
369impl<'a> Context<'a> {
370 fn new<T: 'a + IntoOverflowableItem<'a>>(
371 context: &'a RewriteContext<'_>,
372 items: impl Iterator<Item = &'a T>,
373 ident: &'a str,
374 shape: Shape,
375 span: Span,
376 prefix: &'static str,
377 suffix: &'static str,
378 item_max_width: usize,
379 force_separator_tactic: Option<SeparatorTactic>,
380 custom_delims: Option<(&'a str, &'a str)>,
381 ) -> Context<'a> {
382 let used_width = extra_offset(ident, shape);
383 let one_line_width = shape.width.saturating_sub(used_width + 2);
385
386 let one_line_shape = shape
388 .offset_left(last_line_width(ident) + 1)
389 .and_then(|shape| shape.sub_width(1))
390 .unwrap_or(Shape { width: 0, ..shape });
391 let nested_shape = shape_from_indent_style(context, shape, used_width + 2, used_width + 1);
392 Context {
393 context,
394 items: into_overflowable_list(items).collect(),
395 ident,
396 one_line_shape,
397 nested_shape,
398 span,
399 prefix,
400 suffix,
401 item_max_width,
402 one_line_width,
403 force_separator_tactic,
404 custom_delims,
405 }
406 }
407
408 fn last_item(&self) -> Option<&OverflowableItem<'_>> {
409 self.items.last()
410 }
411
412 fn items_span(&self) -> Span {
413 let span_lo = self
414 .context
415 .snippet_provider
416 .span_after(self.span, self.prefix);
417 mk_sp(span_lo, self.span.hi())
418 }
419
420 fn rewrite_last_item_with_overflow(
421 &self,
422 last_list_item: &mut ListItem,
423 shape: Shape,
424 ) -> Option<String> {
425 let last_item = self.last_item()?;
426 let rewrite = match last_item {
427 OverflowableItem::Expr(expr) => {
428 match expr.kind {
429 ast::ExprKind::Closure(..) => {
432 if closures::args_have_many_closure(&self.items) {
435 None
436 } else {
437 closures::rewrite_last_closure(self.context, expr, shape).ok()
438 }
439 }
440
441 ast::ExprKind::If(..)
444 | ast::ExprKind::ForLoop { .. }
445 | ast::ExprKind::Loop(..)
446 | ast::ExprKind::While(..)
447 | ast::ExprKind::Match(..) => {
448 let multi_line = rewrite_cond(self.context, expr, shape)
449 .map_or(false, |cond| cond.contains('\n'));
450
451 if multi_line {
452 None
453 } else {
454 expr.rewrite(self.context, shape)
455 }
456 }
457
458 _ => expr.rewrite(self.context, shape),
459 }
460 }
461 item => item.rewrite(self.context, shape),
462 };
463
464 if let Some(rewrite) = rewrite {
465 let rewrite_first_line = Ok(rewrite.splitn(2, '\n').next().unwrap().to_owned());
467 last_list_item.item = rewrite_first_line;
468 Some(rewrite)
469 } else {
470 None
471 }
472 }
473
474 fn default_tactic(&self, list_items: &[ListItem]) -> DefinitiveListTactic {
475 definitive_tactic(
476 list_items,
477 ListTactic::LimitedHorizontalVertical(self.item_max_width),
478 Separator::Comma,
479 self.one_line_width,
480 )
481 }
482
483 fn try_overflow_last_item(&self, list_items: &mut Vec<ListItem>) -> DefinitiveListTactic {
484 let combine_arg_with_callee = self.items.len() == 1
486 && self.items[0].is_expr()
487 && !self.items[0].has_attrs()
488 && self.ident.len() < self.context.config.tab_spaces();
489 let overflow_last = combine_arg_with_callee || can_be_overflowed(self.context, &self.items);
490
491 let placeholder = if overflow_last {
494 let old_value = self.context.force_one_line_chain.get();
495 match self.last_item() {
496 Some(OverflowableItem::Expr(expr))
497 if !combine_arg_with_callee && is_method_call(expr) =>
498 {
499 self.context.force_one_line_chain.replace(true);
500 }
501 Some(OverflowableItem::MacroArg(MacroArg::Expr(expr)))
502 if !combine_arg_with_callee
503 && is_method_call(expr)
504 && self.context.config.style_edition() >= StyleEdition::Edition2024 =>
505 {
506 self.context.force_one_line_chain.replace(true);
507 }
508 _ => (),
509 }
510 let result = last_item_shape(
511 &self.items,
512 list_items,
513 self.one_line_shape,
514 self.item_max_width,
515 )
516 .and_then(|arg_shape| {
517 self.rewrite_last_item_with_overflow(
518 &mut list_items[self.items.len() - 1],
519 arg_shape,
520 )
521 });
522 self.context.force_one_line_chain.replace(old_value);
523 result
524 } else {
525 None
526 };
527
528 let mut tactic = definitive_tactic(
529 &*list_items,
530 ListTactic::LimitedHorizontalVertical(self.item_max_width),
531 Separator::Comma,
532 self.one_line_width,
533 );
534
535 match (overflow_last, tactic, placeholder) {
538 (true, DefinitiveListTactic::Horizontal, Some(ref overflowed))
539 if self.items.len() == 1 =>
540 {
541 if count_newlines(overflowed) == 1 {
548 let rw = self
549 .items
550 .last()
551 .and_then(|last_item| last_item.rewrite(self.context, self.nested_shape));
552 let no_newline = rw.as_ref().map_or(false, |s| !s.contains('\n'));
553 if no_newline {
554 list_items[self.items.len() - 1].item = rw.unknown_error();
555 } else {
556 list_items[self.items.len() - 1].item = Ok(overflowed.to_owned());
557 }
558 } else {
559 list_items[self.items.len() - 1].item = Ok(overflowed.to_owned());
560 }
561 }
562 (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => {
563 list_items[self.items.len() - 1].item = placeholder.unknown_error();
564 }
565 _ if !self.items.is_empty() => {
566 list_items[self.items.len() - 1].item = self
567 .items
568 .last()
569 .and_then(|last_item| last_item.rewrite(self.context, self.nested_shape))
570 .unknown_error();
571
572 if self.items.len() == 1
576 && self.one_line_width != 0
577 && !list_items[0].has_comment()
578 && !list_items[0].inner_as_ref().contains('\n')
579 && crate::lists::total_item_width(&list_items[0]) <= self.one_line_width
580 {
581 tactic = DefinitiveListTactic::Horizontal;
582 } else {
583 tactic = self.default_tactic(list_items);
584
585 if tactic == DefinitiveListTactic::Vertical {
586 if let Some((all_simple, num_args_before)) =
587 maybe_get_args_offset(self.ident, &self.items, &self.context.config)
588 {
589 let one_line = all_simple
590 && definitive_tactic(
591 &list_items[..num_args_before],
592 ListTactic::HorizontalVertical,
593 Separator::Comma,
594 self.nested_shape.width,
595 ) == DefinitiveListTactic::Horizontal
596 && definitive_tactic(
597 &list_items[num_args_before + 1..],
598 ListTactic::HorizontalVertical,
599 Separator::Comma,
600 self.nested_shape.width,
601 ) == DefinitiveListTactic::Horizontal;
602
603 if one_line {
604 tactic = DefinitiveListTactic::SpecialMacro(num_args_before);
605 };
606 } else if is_every_expr_simple(&self.items)
607 && no_long_items(
608 list_items,
609 self.context.config.short_array_element_width_threshold(),
610 )
611 {
612 tactic = DefinitiveListTactic::Mixed;
613 }
614 }
615 }
616 }
617 _ => (),
618 }
619
620 tactic
621 }
622
623 fn rewrite_items(&self) -> Result<(bool, String), RewriteError> {
624 let span = self.items_span();
625 debug!("items: {:?}", self.items);
626
627 let items = itemize_list(
628 self.context.snippet_provider,
629 self.items.iter(),
630 self.suffix,
631 ",",
632 |item| item.span().lo(),
633 |item| item.span().hi(),
634 |item| item.rewrite_result(self.context, self.nested_shape),
635 span.lo(),
636 span.hi(),
637 true,
638 );
639 let mut list_items: Vec<_> = items.collect();
640
641 debug!("items: {list_items:?}");
642
643 let tactic = self.try_overflow_last_item(&mut list_items);
647 let trailing_separator = if let Some(tactic) = self.force_separator_tactic {
648 tactic
649 } else if !self.context.use_block_indent() {
650 SeparatorTactic::Never
651 } else {
652 self.context.config.trailing_comma()
653 };
654 let ends_with_newline = match tactic {
655 DefinitiveListTactic::Vertical | DefinitiveListTactic::Mixed => {
656 self.context.use_block_indent()
657 }
658 _ => false,
659 };
660
661 let fmt = ListFormatting::new(self.nested_shape, self.context.config)
662 .tactic(tactic)
663 .trailing_separator(trailing_separator)
664 .ends_with_newline(ends_with_newline);
665
666 write_list(&list_items, &fmt)
667 .map(|items_str| (tactic == DefinitiveListTactic::Horizontal, items_str))
668 }
669
670 fn wrap_items(&self, items_str: &str, shape: Shape, is_extendable: bool) -> String {
671 let shape = Shape {
672 width: shape.width.saturating_sub(last_line_width(self.ident)),
673 ..shape
674 };
675
676 let (prefix, suffix) = match self.custom_delims {
677 Some((lhs, rhs)) => (lhs, rhs),
678 _ => (self.prefix, self.suffix),
679 };
680
681 let extend_width = if items_str.is_empty() {
682 2
683 } else {
684 first_line_width(items_str) + 1
685 };
686 let nested_indent_str = self
687 .nested_shape
688 .indent
689 .to_string_with_newline(self.context.config);
690 let indent_str = shape
691 .block()
692 .indent
693 .to_string_with_newline(self.context.config);
694 let mut result = String::with_capacity(
695 self.ident.len() + items_str.len() + 2 + indent_str.len() + nested_indent_str.len(),
696 );
697 result.push_str(self.ident);
698 result.push_str(prefix);
699 let force_single_line = if self.context.config.style_edition() >= StyleEdition::Edition2024
700 {
701 !self.context.use_block_indent() || (is_extendable && extend_width <= shape.width)
702 } else {
703 let fits_one_line = items_str.len() + 2 <= shape.width;
705 !self.context.use_block_indent()
706 || (self.context.inside_macro() && !items_str.contains('\n') && fits_one_line)
707 || (is_extendable && extend_width <= shape.width)
708 };
709 if force_single_line {
710 result.push_str(items_str);
711 } else {
712 if !items_str.is_empty() {
713 result.push_str(&nested_indent_str);
714 result.push_str(items_str);
715 }
716 result.push_str(&indent_str);
717 }
718 result.push_str(suffix);
719 result
720 }
721
722 fn rewrite(&self, shape: Shape) -> RewriteResult {
723 let (extendable, items_str) = self.rewrite_items()?;
724
725 if !self.context.use_block_indent()
727 && need_block_indent(&items_str, self.nested_shape)
728 && !extendable
729 {
730 self.context.use_block.replace(true);
731 let result = self.rewrite(shape);
732 self.context.use_block.replace(false);
733 return result;
734 }
735
736 Ok(self.wrap_items(&items_str, shape, extendable))
737 }
738}
739
740fn need_block_indent(s: &str, shape: Shape) -> bool {
741 s.lines().skip(1).any(|s| {
742 s.find(|c| !char::is_whitespace(c))
743 .map_or(false, |w| w + 1 < shape.indent.width())
744 })
745}
746
747fn can_be_overflowed(context: &RewriteContext<'_>, items: &[OverflowableItem<'_>]) -> bool {
748 items
749 .last()
750 .map_or(false, |x| x.can_be_overflowed(context, items.len()))
751}
752
753fn last_item_shape(
755 lists: &[OverflowableItem<'_>],
756 items: &[ListItem],
757 shape: Shape,
758 args_max_width: usize,
759) -> Option<Shape> {
760 if items.len() == 1 && !lists.get(0)?.is_nested_call() {
761 return Some(shape);
762 }
763 let offset = items
764 .iter()
765 .dropping_back(1)
766 .map(|i| {
767 2 + i.inner_as_ref().len()
769 })
770 .sum();
771 Shape {
772 width: min(args_max_width, shape.width),
773 ..shape
774 }
775 .offset_left(offset)
776}
777
778fn shape_from_indent_style(
779 context: &RewriteContext<'_>,
780 shape: Shape,
781 overhead: usize,
782 offset: usize,
783) -> Shape {
784 let (shape, overhead) = if context.use_block_indent() {
785 let shape = shape
786 .block()
787 .block_indent(context.config.tab_spaces())
788 .with_max_width(context.config);
789 (shape, 1) } else {
791 (shape.visual_indent(offset), overhead)
792 };
793 Shape {
794 width: shape.width.saturating_sub(overhead),
795 ..shape
796 }
797}
798
799fn no_long_items(list: &[ListItem], short_array_element_width_threshold: usize) -> bool {
800 list.iter()
801 .all(|item| item.inner_as_ref().len() <= short_array_element_width_threshold)
802}
803
804pub(crate) fn maybe_get_args_offset(
806 callee_str: &str,
807 args: &[OverflowableItem<'_>],
808 config: &Config,
809) -> Option<(bool, usize)> {
810 if let Some(&(_, num_args_before)) = args
811 .get(0)?
812 .special_cases(config)
813 .find(|&&(s, _)| s == callee_str)
814 {
815 let all_simple = args.len() > num_args_before
816 && is_every_expr_simple(&args[0..num_args_before])
817 && is_every_expr_simple(&args[num_args_before + 1..]);
818
819 Some((all_simple, num_args_before))
820 } else {
821 None
822 }
823}