about summary refs log tree commit diff
path: root/src/items.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/items.rs')
-rw-r--r--src/items.rs377
1 files changed, 194 insertions, 183 deletions
diff --git a/src/items.rs b/src/items.rs
index 002cffa9b0c..edb5a5b629a 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -75,6 +75,7 @@ impl Rewrite for ast::Local {
                 false,
             )?
         };
+        let let_kw_offset = result.len() - "let ".len();
 
         // 4 = "let ".len()
         let pat_shape = shape.offset_left(4)?;
@@ -127,8 +128,15 @@ impl Rewrite for ast::Local {
 
             if let Some(block) = else_block {
                 let else_kw_span = init.span.between(block.span);
+                // Strip attributes and comments to check if newline is needed before the else
+                // keyword from the initializer part. (#5901)
+                let init_str = if context.config.version() == Version::Two {
+                    &result[let_kw_offset..]
+                } else {
+                    result.as_str()
+                };
                 let force_newline_else = pat_str.contains('\n')
-                    || !same_line_else_kw_and_brace(&result, context, else_kw_span, nested_shape);
+                    || !same_line_else_kw_and_brace(init_str, context, else_kw_span, nested_shape);
                 let else_kw = rewrite_else_kw_with_comments(
                     force_newline_else,
                     true,
@@ -146,11 +154,16 @@ impl Rewrite for ast::Local {
                     std::cmp::min(shape.width, context.config.single_line_let_else_max_width());
 
                 // If available_space hits zero we know for sure this will be a multi-lined block
-                let available_space = max_width.saturating_sub(result.len());
+                let assign_str_with_else_kw = if context.config.version() == Version::Two {
+                    &result[let_kw_offset..]
+                } else {
+                    result.as_str()
+                };
+                let available_space = max_width.saturating_sub(assign_str_with_else_kw.len());
 
                 let allow_single_line = !force_newline_else
                     && available_space > 0
-                    && allow_single_line_let_else_block(&result, block);
+                    && allow_single_line_let_else_block(assign_str_with_else_kw, block);
 
                 let mut rw_else_block =
                     rewrite_let_else_block(block, allow_single_line, context, shape)?;
@@ -248,7 +261,6 @@ impl<'a> Item<'a> {
             abi: format_extern(
                 ast::Extern::from_abi(fm.abi, DUMMY_SP),
                 config.force_explicit_abi(),
-                true,
             ),
             vis: None,
             body: fm
@@ -306,22 +318,20 @@ impl<'a> FnSig<'a> {
         defaultness: ast::Defaultness,
     ) -> FnSig<'a> {
         match *fn_kind {
-            visit::FnKind::Fn(fn_ctxt, _, fn_sig, vis, generics, _) => match fn_ctxt {
-                visit::FnCtxt::Assoc(..) => {
-                    let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis);
-                    fn_sig.defaultness = defaultness;
-                    fn_sig
-                }
-                _ => FnSig {
-                    decl,
-                    generics,
-                    ext: fn_sig.header.ext,
-                    constness: fn_sig.header.constness,
-                    is_async: Cow::Borrowed(&fn_sig.header.asyncness),
-                    defaultness,
-                    unsafety: fn_sig.header.unsafety,
-                    visibility: vis,
-                },
+            visit::FnKind::Fn(visit::FnCtxt::Assoc(..), _, fn_sig, vis, generics, _) => {
+                let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis);
+                fn_sig.defaultness = defaultness;
+                fn_sig
+            }
+            visit::FnKind::Fn(_, _, fn_sig, vis, generics, _) => FnSig {
+                decl,
+                generics,
+                ext: fn_sig.header.ext,
+                constness: fn_sig.header.constness,
+                is_async: Cow::Borrowed(&fn_sig.header.asyncness),
+                defaultness,
+                unsafety: fn_sig.header.unsafety,
+                visibility: vis,
             },
             _ => unreachable!(),
         }
@@ -338,7 +348,6 @@ impl<'a> FnSig<'a> {
         result.push_str(&format_extern(
             self.ext,
             context.config.force_explicit_abi(),
-            false,
         ));
         result
     }
@@ -472,7 +481,7 @@ impl<'a> FmtVisitor<'a> {
             && self.block_indent.width() + fn_str.len() + 3 <= self.config.max_width()
             && !last_line_contains_single_line_comment(fn_str)
         {
-            return Some(format!("{} {{}}", fn_str));
+            return Some(format!("{fn_str} {{}}"));
         }
 
         if !self.config.fn_single_line() || !is_simple_block_stmt(&context, block, None) {
@@ -484,7 +493,7 @@ impl<'a> FmtVisitor<'a> {
 
         let width = self.block_indent.width() + fn_str.len() + res.len() + 5;
         if !res.contains('\n') && width <= self.config.max_width() {
-            Some(format!("{} {{ {} }}", fn_str, res))
+            Some(format!("{fn_str} {{ {res} }}"))
         } else {
             None
         }
@@ -666,7 +675,7 @@ impl<'a> FmtVisitor<'a> {
         };
 
         let variant_body = if let Some(ref expr) = field.disr_expr {
-            let lhs = format!("{:1$} =", variant_body, pad_discrim_ident_to);
+            let lhs = format!("{variant_body:pad_discrim_ident_to$} =");
             let ex = &*expr.value;
             rewrite_assign_rhs_with(
                 &context,
@@ -829,7 +838,7 @@ pub(crate) fn format_impl(
             if generics.where_clause.predicates.len() == 1 {
                 result.push(',');
             }
-            result.push_str(&format!("{}{{{}}}", sep, sep));
+            result.push_str(&format!("{sep}{{{sep}}}"));
         } else {
             result.push_str(" {}");
         }
@@ -1020,7 +1029,7 @@ fn rewrite_trait_ref(
     let shape = Shape::indented(offset + used_space, context.config);
     if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) {
         if !trait_ref_str.contains('\n') {
-            return Some(format!(" {}{}", polarity_str, trait_ref_str));
+            return Some(format!(" {polarity_str}{trait_ref_str}"));
         }
     }
     // We could not make enough space for trait_ref, so put it on new line.
@@ -1118,172 +1127,172 @@ pub(crate) fn format_trait(
     item: &ast::Item,
     offset: Indent,
 ) -> Option<String> {
-    if let ast::ItemKind::Trait(trait_kind) = &item.kind {
-        let ast::Trait {
-            is_auto,
-            unsafety,
-            ref generics,
-            ref bounds,
-            ref items,
-        } = **trait_kind;
-        let mut result = String::with_capacity(128);
-        let header = format!(
-            "{}{}{}trait ",
-            format_visibility(context, &item.vis),
-            format_unsafety(unsafety),
-            format_auto(is_auto),
-        );
-        result.push_str(&header);
+    let ast::ItemKind::Trait(trait_kind) = &item.kind else {
+        unreachable!();
+    };
+    let ast::Trait {
+        is_auto,
+        unsafety,
+        ref generics,
+        ref bounds,
+        ref items,
+    } = **trait_kind;
 
-        let body_lo = context.snippet_provider.span_after(item.span, "{");
+    let mut result = String::with_capacity(128);
+    let header = format!(
+        "{}{}{}trait ",
+        format_visibility(context, &item.vis),
+        format_unsafety(unsafety),
+        format_auto(is_auto),
+    );
+    result.push_str(&header);
 
-        let shape = Shape::indented(offset, context.config).offset_left(result.len())?;
-        let generics_str =
-            rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape)?;
-        result.push_str(&generics_str);
+    let body_lo = context.snippet_provider.span_after(item.span, "{");
 
-        // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
-        if !bounds.is_empty() {
-            let ident_hi = context
-                .snippet_provider
-                .span_after(item.span, item.ident.as_str());
-            let bound_hi = bounds.last().unwrap().span().hi();
-            let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
-            if contains_comment(snippet) {
-                return None;
-            }
+    let shape = Shape::indented(offset, context.config).offset_left(result.len())?;
+    let generics_str =
+        rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape)?;
+    result.push_str(&generics_str);
 
-            result = rewrite_assign_rhs_with(
-                context,
-                result + ":",
-                bounds,
-                shape,
-                &RhsAssignKind::Bounds,
-                RhsTactics::ForceNextLineWithoutIndent,
-            )?;
+    // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
+    if !bounds.is_empty() {
+        let ident_hi = context
+            .snippet_provider
+            .span_after(item.span, item.ident.as_str());
+        let bound_hi = bounds.last().unwrap().span().hi();
+        let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
+        if contains_comment(snippet) {
+            return None;
         }
 
-        // Rewrite where-clause.
-        if !generics.where_clause.predicates.is_empty() {
-            let where_on_new_line = context.config.indent_style() != IndentStyle::Block;
+        result = rewrite_assign_rhs_with(
+            context,
+            result + ":",
+            bounds,
+            shape,
+            &RhsAssignKind::Bounds,
+            RhsTactics::ForceNextLineWithoutIndent,
+        )?;
+    }
+
+    // Rewrite where-clause.
+    if !generics.where_clause.predicates.is_empty() {
+        let where_on_new_line = context.config.indent_style() != IndentStyle::Block;
 
-            let where_budget = context.budget(last_line_width(&result));
-            let pos_before_where = if bounds.is_empty() {
-                generics.where_clause.span.lo()
+        let where_budget = context.budget(last_line_width(&result));
+        let pos_before_where = if bounds.is_empty() {
+            generics.where_clause.span.lo()
+        } else {
+            bounds[bounds.len() - 1].span().hi()
+        };
+        let option = WhereClauseOption::snuggled(&generics_str);
+        let where_clause_str = rewrite_where_clause(
+            context,
+            &generics.where_clause.predicates,
+            generics.where_clause.span,
+            context.config.brace_style(),
+            Shape::legacy(where_budget, offset.block_only()),
+            where_on_new_line,
+            "{",
+            None,
+            pos_before_where,
+            option,
+        )?;
+        // If the where-clause cannot fit on the same line,
+        // put the where-clause on a new line
+        if !where_clause_str.contains('\n')
+            && last_line_width(&result) + where_clause_str.len() + offset.width()
+                > context.config.comment_width()
+        {
+            let width = offset.block_indent + context.config.tab_spaces() - 1;
+            let where_indent = Indent::new(0, width);
+            result.push_str(&where_indent.to_string_with_newline(context.config));
+        }
+        result.push_str(&where_clause_str);
+    } else {
+        let item_snippet = context.snippet(item.span);
+        if let Some(lo) = item_snippet.find('/') {
+            // 1 = `{`
+            let comment_hi = if generics.params.len() > 0 {
+                generics.span.lo() - BytePos(1)
             } else {
-                bounds[bounds.len() - 1].span().hi()
+                body_lo - BytePos(1)
             };
-            let option = WhereClauseOption::snuggled(&generics_str);
-            let where_clause_str = rewrite_where_clause(
-                context,
-                &generics.where_clause.predicates,
-                generics.where_clause.span,
-                context.config.brace_style(),
-                Shape::legacy(where_budget, offset.block_only()),
-                where_on_new_line,
-                "{",
-                None,
-                pos_before_where,
-                option,
-            )?;
-            // If the where-clause cannot fit on the same line,
-            // put the where-clause on a new line
-            if !where_clause_str.contains('\n')
-                && last_line_width(&result) + where_clause_str.len() + offset.width()
-                    > context.config.comment_width()
-            {
-                let width = offset.block_indent + context.config.tab_spaces() - 1;
-                let where_indent = Indent::new(0, width);
-                result.push_str(&where_indent.to_string_with_newline(context.config));
-            }
-            result.push_str(&where_clause_str);
-        } else {
-            let item_snippet = context.snippet(item.span);
-            if let Some(lo) = item_snippet.find('/') {
-                // 1 = `{`
-                let comment_hi = if generics.params.len() > 0 {
-                    generics.span.lo() - BytePos(1)
-                } else {
-                    body_lo - BytePos(1)
-                };
-                let comment_lo = item.span.lo() + BytePos(lo as u32);
-                if comment_lo < comment_hi {
-                    match recover_missing_comment_in_span(
-                        mk_sp(comment_lo, comment_hi),
-                        Shape::indented(offset, context.config),
-                        context,
-                        last_line_width(&result),
-                    ) {
-                        Some(ref missing_comment) if !missing_comment.is_empty() => {
-                            result.push_str(missing_comment);
-                        }
-                        _ => (),
+            let comment_lo = item.span.lo() + BytePos(lo as u32);
+            if comment_lo < comment_hi {
+                match recover_missing_comment_in_span(
+                    mk_sp(comment_lo, comment_hi),
+                    Shape::indented(offset, context.config),
+                    context,
+                    last_line_width(&result),
+                ) {
+                    Some(ref missing_comment) if !missing_comment.is_empty() => {
+                        result.push_str(missing_comment);
                     }
+                    _ => (),
                 }
             }
         }
+    }
 
-        let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi());
-        let snippet = context.snippet(block_span);
-        let open_pos = snippet.find_uncommented("{")? + 1;
+    let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi());
+    let snippet = context.snippet(block_span);
+    let open_pos = snippet.find_uncommented("{")? + 1;
 
-        match context.config.brace_style() {
-            _ if last_line_contains_single_line_comment(&result)
-                || last_line_width(&result) + 2 > context.budget(offset.width()) =>
-            {
-                result.push_str(&offset.to_string_with_newline(context.config));
-            }
-            _ if context.config.empty_item_single_line()
-                && items.is_empty()
-                && !result.contains('\n')
-                && !contains_comment(&snippet[open_pos..]) =>
+    match context.config.brace_style() {
+        _ if last_line_contains_single_line_comment(&result)
+            || last_line_width(&result) + 2 > context.budget(offset.width()) =>
+        {
+            result.push_str(&offset.to_string_with_newline(context.config));
+        }
+        _ if context.config.empty_item_single_line()
+            && items.is_empty()
+            && !result.contains('\n')
+            && !contains_comment(&snippet[open_pos..]) =>
+        {
+            result.push_str(" {}");
+            return Some(result);
+        }
+        BraceStyle::AlwaysNextLine => {
+            result.push_str(&offset.to_string_with_newline(context.config));
+        }
+        BraceStyle::PreferSameLine => result.push(' '),
+        BraceStyle::SameLineWhere => {
+            if result.contains('\n')
+                || (!generics.where_clause.predicates.is_empty() && !items.is_empty())
             {
-                result.push_str(" {}");
-                return Some(result);
-            }
-            BraceStyle::AlwaysNextLine => {
                 result.push_str(&offset.to_string_with_newline(context.config));
-            }
-            BraceStyle::PreferSameLine => result.push(' '),
-            BraceStyle::SameLineWhere => {
-                if result.contains('\n')
-                    || (!generics.where_clause.predicates.is_empty() && !items.is_empty())
-                {
-                    result.push_str(&offset.to_string_with_newline(context.config));
-                } else {
-                    result.push(' ');
-                }
+            } else {
+                result.push(' ');
             }
         }
-        result.push('{');
-
-        let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
+    }
+    result.push('{');
 
-        if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
-            let mut visitor = FmtVisitor::from_context(context);
-            visitor.block_indent = offset.block_only().block_indent(context.config);
-            visitor.last_pos = block_span.lo() + BytePos(open_pos as u32);
+    let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
 
-            for item in items {
-                visitor.visit_trait_item(item);
-            }
+    if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
+        let mut visitor = FmtVisitor::from_context(context);
+        visitor.block_indent = offset.block_only().block_indent(context.config);
+        visitor.last_pos = block_span.lo() + BytePos(open_pos as u32);
 
-            visitor.format_missing(item.span.hi() - BytePos(1));
+        for item in items {
+            visitor.visit_trait_item(item);
+        }
 
-            let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config);
+        visitor.format_missing(item.span.hi() - BytePos(1));
 
-            result.push_str(&inner_indent_str);
-            result.push_str(visitor.buffer.trim());
-            result.push_str(&outer_indent_str);
-        } else if result.contains('\n') {
-            result.push_str(&outer_indent_str);
-        }
+        let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config);
 
-        result.push('}');
-        Some(result)
-    } else {
-        unreachable!();
+        result.push_str(&inner_indent_str);
+        result.push_str(visitor.buffer.trim());
+        result.push_str(&outer_indent_str);
+    } else if result.contains('\n') {
+        result.push_str(&outer_indent_str);
     }
+
+    result.push('}');
+    Some(result)
 }
 
 pub(crate) struct TraitAliasBounds<'a> {
@@ -1322,7 +1331,7 @@ impl<'a> Rewrite for TraitAliasBounds<'a> {
             shape.indent.to_string_with_newline(context.config)
         };
 
-        Some(format!("{}{}{}", generic_bounds_str, space, where_str))
+        Some(format!("{generic_bounds_str}{space}{where_str}"))
     }
 }
 
@@ -1339,7 +1348,7 @@ pub(crate) fn format_trait_alias(
     let g_shape = shape.offset_left(6)?.sub_width(2)?;
     let generics_str = rewrite_generics(context, alias, generics, g_shape)?;
     let vis_str = format_visibility(context, vis);
-    let lhs = format!("{}trait {} =", vis_str, generics_str);
+    let lhs = format!("{vis_str}trait {generics_str} =");
     // 1 = ";"
     let trait_alias_bounds = TraitAliasBounds {
         generic_bounds,
@@ -1376,7 +1385,7 @@ fn format_unit_struct(
     } else {
         String::new()
     };
-    Some(format!("{}{};", header_str, generics_str))
+    Some(format!("{header_str}{generics_str};"))
 }
 
 pub(crate) fn format_struct_struct(
@@ -1466,7 +1475,7 @@ pub(crate) fn format_struct_struct(
         && items_str.len() <= one_line_budget
         && !last_line_contains_single_line_comment(&items_str)
     {
-        Some(format!("{} {} }}", result, items_str))
+        Some(format!("{result} {items_str} }}"))
     } else {
         Some(format!(
             "{}\n{}{}\n{}}}",
@@ -1696,7 +1705,7 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
                 rewrite_ty(rw_info, Some(bounds), ty_opt, vis)
             }?;
             match defaultness {
-                ast::Defaultness::Default(..) => Some(format!("default {}", result)),
+                ast::Defaultness::Default(..) => Some(format!("default {result}")),
                 _ => Some(result),
             }
         }
@@ -1803,14 +1812,14 @@ fn rewrite_ty<R: Rewrite>(
                     true,
                 )?
             }
-            _ => format!("{}=", result),
+            _ => format!("{result}="),
         };
 
         // 1 = `;`
         let shape = Shape::indented(indent, context.config).sub_width(1)?;
         rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape).map(|s| s + ";")
     } else {
-        Some(format!("{};", result))
+        Some(format!("{result};"))
     }
 }
 
@@ -2019,7 +2028,7 @@ fn rewrite_static(
         let expr_lo = expr.span.lo();
         let comments_span = mk_sp(comments_lo, expr_lo);
 
-        let lhs = format!("{}{} =", prefix, ty_str);
+        let lhs = format!("{prefix}{ty_str} =");
 
         // 1 = ;
         let remaining_width = context.budget(offset.block_indent + 1);
@@ -2036,7 +2045,7 @@ fn rewrite_static(
         .and_then(|res| recover_comment_removed(res, static_parts.span, context))
         .map(|s| if s.ends_with(';') { s } else { s + ";" })
     } else {
-        Some(format!("{}{};", prefix, ty_str))
+        Some(format!("{prefix}{ty_str};"))
     }
 }
 
@@ -2229,7 +2238,7 @@ fn rewrite_explicit_self(
                     Some(combine_strs_with_missing_comments(
                         context,
                         param_attrs,
-                        &format!("&{} {}self", lifetime_str, mut_str),
+                        &format!("&{lifetime_str} {mut_str}self"),
                         span,
                         shape,
                         !has_multiple_attr_lines,
@@ -2238,7 +2247,7 @@ fn rewrite_explicit_self(
                 None => Some(combine_strs_with_missing_comments(
                     context,
                     param_attrs,
-                    &format!("&{}self", mut_str),
+                    &format!("&{mut_str}self"),
                     span,
                     shape,
                     !has_multiple_attr_lines,
@@ -2909,7 +2918,7 @@ fn rewrite_where_clause_rfc_style(
             clause_shape.indent.to_string_with_newline(context.config)
         };
 
-    Some(format!("{}{}{}", where_keyword, clause_sep, preds_str))
+    Some(format!("{where_keyword}{clause_sep}{preds_str}"))
 }
 
 /// Rewrite `where` and comment around it.
@@ -2949,8 +2958,8 @@ fn rewrite_where_keyword(
     let newline_before_where = comment_separator(&comment_before, shape);
     let newline_after_where = comment_separator(&comment_after, clause_shape);
     let result = format!(
-        "{}{}{}where{}{}",
-        starting_newline, comment_before, newline_before_where, newline_after_where, comment_after
+        "{starting_newline}{comment_before}{newline_before_where}where\
+{newline_after_where}{comment_after}"
     );
     let allow_single_line = where_clause_option.allow_single_line
         && comment_before.is_empty()
@@ -3001,10 +3010,12 @@ fn rewrite_bounds_on_where_clause(
         DefinitiveListTactic::Vertical
     };
 
+    let preserve_newline = context.config.version() == Version::One;
+
     let fmt = ListFormatting::new(shape, context.config)
         .tactic(shape_tactic)
         .trailing_separator(comma_tactic)
-        .preserve_newline(true);
+        .preserve_newline(preserve_newline);
     write_list(&items.collect::<Vec<_>>(), &fmt)
 }
 
@@ -3105,7 +3116,7 @@ fn rewrite_where_clause(
             preds_str
         ))
     } else {
-        Some(format!(" where {}", preds_str))
+        Some(format!(" where {preds_str}"))
     }
 }
 
@@ -3234,7 +3245,7 @@ fn format_generics(
                     if brace_pos == BracePos::None {
                         span.hi()
                     } else {
-                        context.snippet_provider.span_before(span, "{")
+                        context.snippet_provider.span_before_last(span, "{")
                     },
                 ),
                 shape,