]> git.lizzy.rs Git - rust.git/blob - src/items.rs
deps: bump rustc-ap* to v666
[rust.git] / src / items.rs
1 // Formatting top-level items - functions, structs, enums, traits, impls.
2
3 use std::borrow::Cow;
4 use std::cmp::{max, min, Ordering};
5
6 use regex::Regex;
7 use rustc_ast::visit;
8 use rustc_ast::{ast, ptr};
9 use rustc_span::{source_map, symbol, BytePos, Span, DUMMY_SP};
10
11 use crate::attr::filter_inline_attrs;
12 use crate::comment::{
13     combine_strs_with_missing_comments, contains_comment, is_last_comment_block,
14     recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment,
15     FindUncommented,
16 };
17 use crate::config::lists::*;
18 use crate::config::{BraceStyle, Config, IndentStyle, Version};
19 use crate::expr::{
20     is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, RhsTactics,
21 };
22 use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
23 use crate::macros::{rewrite_macro, MacroPosition};
24 use crate::overflow;
25 use crate::rewrite::{Rewrite, RewriteContext};
26 use crate::shape::{Indent, Shape};
27 use crate::source_map::{LineRangeUtils, SpanUtils};
28 use crate::spanned::Spanned;
29 use crate::stmt::Stmt;
30 use crate::utils::*;
31 use crate::vertical::rewrite_with_alignment;
32 use crate::visitor::FmtVisitor;
33
34 const DEFAULT_VISIBILITY: ast::Visibility = source_map::Spanned {
35     node: ast::VisibilityKind::Inherited,
36     span: DUMMY_SP,
37 };
38
39 fn type_annotation_separator(config: &Config) -> &str {
40     colon_spaces(config)
41 }
42
43 // Statements of the form
44 // let pat: ty = init;
45 impl Rewrite for ast::Local {
46     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
47         debug!(
48             "Local::rewrite {:?} {} {:?}",
49             self, shape.width, shape.indent
50         );
51
52         skip_out_of_file_lines_range!(context, self.span);
53
54         if contains_skip(&self.attrs) {
55             return None;
56         }
57
58         let attrs_str = self.attrs.rewrite(context, shape)?;
59         let mut result = if attrs_str.is_empty() {
60             "let ".to_owned()
61         } else {
62             combine_strs_with_missing_comments(
63                 context,
64                 &attrs_str,
65                 "let ",
66                 mk_sp(
67                     self.attrs.last().map(|a| a.span.hi()).unwrap(),
68                     self.span.lo(),
69                 ),
70                 shape,
71                 false,
72             )?
73         };
74
75         // 4 = "let ".len()
76         let pat_shape = shape.offset_left(4)?;
77         // 1 = ;
78         let pat_shape = pat_shape.sub_width(1)?;
79         let pat_str = self.pat.rewrite(context, pat_shape)?;
80         result.push_str(&pat_str);
81
82         // String that is placed within the assignment pattern and expression.
83         let infix = {
84             let mut infix = String::with_capacity(32);
85
86             if let Some(ref ty) = self.ty {
87                 let separator = type_annotation_separator(context.config);
88                 let ty_shape = if pat_str.contains('\n') {
89                     shape.with_max_width(context.config)
90                 } else {
91                     shape
92                 }
93                 .offset_left(last_line_width(&result) + separator.len())?
94                 // 2 = ` =`
95                 .sub_width(2)?;
96
97                 let rewrite = ty.rewrite(context, ty_shape)?;
98
99                 infix.push_str(separator);
100                 infix.push_str(&rewrite);
101             }
102
103             if self.init.is_some() {
104                 infix.push_str(" =");
105             }
106
107             infix
108         };
109
110         result.push_str(&infix);
111
112         if let Some(ref ex) = self.init {
113             // 1 = trailing semicolon;
114             let nested_shape = shape.sub_width(1)?;
115
116             result = rewrite_assign_rhs(context, result, &**ex, nested_shape)?;
117         }
118
119         result.push(';');
120         Some(result)
121     }
122 }
123
124 // FIXME convert to using rewrite style rather than visitor
125 // FIXME format modules in this style
126 #[allow(dead_code)]
127 struct Item<'a> {
128     keyword: &'static str,
129     abi: Cow<'static, str>,
130     vis: Option<&'a ast::Visibility>,
131     body: Vec<BodyElement<'a>>,
132     span: Span,
133 }
134
135 impl<'a> Item<'a> {
136     fn from_foreign_mod(fm: &'a ast::ForeignMod, span: Span, config: &Config) -> Item<'a> {
137         Item {
138             keyword: "",
139             abi: format_extern(
140                 ast::Extern::from_abi(fm.abi),
141                 config.force_explicit_abi(),
142                 true,
143             ),
144             vis: None,
145             body: fm
146                 .items
147                 .iter()
148                 .map(|i| BodyElement::ForeignItem(i))
149                 .collect(),
150             span,
151         }
152     }
153 }
154
155 enum BodyElement<'a> {
156     // Stmt(&'a ast::Stmt),
157     // Field(&'a ast::Field),
158     // Variant(&'a ast::Variant),
159     // Item(&'a ast::Item),
160     ForeignItem(&'a ast::ForeignItem),
161 }
162
163 /// Represents a fn's signature.
164 pub(crate) struct FnSig<'a> {
165     decl: &'a ast::FnDecl,
166     generics: &'a ast::Generics,
167     ext: ast::Extern,
168     is_async: Cow<'a, ast::Async>,
169     constness: ast::Const,
170     defaultness: ast::Defaultness,
171     unsafety: ast::Unsafe,
172     visibility: ast::Visibility,
173 }
174
175 impl<'a> FnSig<'a> {
176     pub(crate) fn new(
177         decl: &'a ast::FnDecl,
178         generics: &'a ast::Generics,
179         vis: ast::Visibility,
180     ) -> FnSig<'a> {
181         FnSig {
182             decl,
183             generics,
184             ext: ast::Extern::None,
185             is_async: Cow::Owned(ast::Async::No),
186             constness: ast::Const::No,
187             defaultness: ast::Defaultness::Final,
188             unsafety: ast::Unsafe::No,
189             visibility: vis,
190         }
191     }
192
193     pub(crate) fn from_method_sig(
194         method_sig: &'a ast::FnSig,
195         generics: &'a ast::Generics,
196     ) -> FnSig<'a> {
197         FnSig {
198             unsafety: method_sig.header.unsafety,
199             is_async: Cow::Borrowed(&method_sig.header.asyncness),
200             constness: method_sig.header.constness,
201             defaultness: ast::Defaultness::Final,
202             ext: method_sig.header.ext,
203             decl: &*method_sig.decl,
204             generics,
205             visibility: DEFAULT_VISIBILITY,
206         }
207     }
208
209     pub(crate) fn from_fn_kind(
210         fn_kind: &'a visit::FnKind<'_>,
211         generics: &'a ast::Generics,
212         decl: &'a ast::FnDecl,
213         defaultness: ast::Defaultness,
214     ) -> FnSig<'a> {
215         match *fn_kind {
216             visit::FnKind::Fn(fn_ctxt, _, fn_sig, vis, _) => match fn_ctxt {
217                 visit::FnCtxt::Assoc(..) => {
218                     let mut fn_sig = FnSig::from_method_sig(fn_sig, generics);
219                     fn_sig.defaultness = defaultness;
220                     fn_sig.visibility = vis.clone();
221                     fn_sig
222                 }
223                 _ => FnSig {
224                     decl,
225                     generics,
226                     ext: fn_sig.header.ext,
227                     constness: fn_sig.header.constness,
228                     is_async: Cow::Borrowed(&fn_sig.header.asyncness),
229                     defaultness,
230                     unsafety: fn_sig.header.unsafety,
231                     visibility: vis.clone(),
232                 },
233             },
234             _ => unreachable!(),
235         }
236     }
237
238     fn to_str(&self, context: &RewriteContext<'_>) -> String {
239         let mut result = String::with_capacity(128);
240         // Vis defaultness constness unsafety abi.
241         result.push_str(&*format_visibility(context, &self.visibility));
242         result.push_str(format_defaultness(self.defaultness));
243         result.push_str(format_constness(self.constness));
244         result.push_str(format_async(&self.is_async));
245         result.push_str(format_unsafety(self.unsafety));
246         result.push_str(&format_extern(
247             self.ext,
248             context.config.force_explicit_abi(),
249             false,
250         ));
251         result
252     }
253 }
254
255 impl<'a> FmtVisitor<'a> {
256     fn format_item(&mut self, item: &Item<'_>) {
257         self.buffer.push_str(&item.abi);
258
259         let snippet = self.snippet(item.span);
260         let brace_pos = snippet.find_uncommented("{").unwrap();
261
262         self.push_str("{");
263         if !item.body.is_empty() || contains_comment(&snippet[brace_pos..]) {
264             // FIXME: this skips comments between the extern keyword and the opening
265             // brace.
266             self.last_pos = item.span.lo() + BytePos(brace_pos as u32 + 1);
267             self.block_indent = self.block_indent.block_indent(self.config);
268
269             if item.body.is_empty() {
270                 self.format_missing_no_indent(item.span.hi() - BytePos(1));
271                 self.block_indent = self.block_indent.block_unindent(self.config);
272                 let indent_str = self.block_indent.to_string(self.config);
273                 self.push_str(&indent_str);
274             } else {
275                 for item in &item.body {
276                     self.format_body_element(item);
277                 }
278
279                 self.block_indent = self.block_indent.block_unindent(self.config);
280                 self.format_missing_with_indent(item.span.hi() - BytePos(1));
281             }
282         }
283
284         self.push_str("}");
285         self.last_pos = item.span.hi();
286     }
287
288     fn format_body_element(&mut self, element: &BodyElement<'_>) {
289         match *element {
290             BodyElement::ForeignItem(item) => self.format_foreign_item(item),
291         }
292     }
293
294     pub(crate) fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) {
295         let item = Item::from_foreign_mod(fm, span, self.config);
296         self.format_item(&item);
297     }
298
299     fn format_foreign_item(&mut self, item: &ast::ForeignItem) {
300         let rewrite = item.rewrite(&self.get_context(), self.shape());
301         let hi = item.span.hi();
302         let span = if item.attrs.is_empty() {
303             item.span
304         } else {
305             mk_sp(item.attrs[0].span.lo(), hi)
306         };
307         self.push_rewrite(span, rewrite);
308         self.last_pos = hi;
309     }
310
311     pub(crate) fn rewrite_fn_before_block(
312         &mut self,
313         indent: Indent,
314         ident: symbol::Ident,
315         fn_sig: &FnSig<'_>,
316         span: Span,
317     ) -> Option<(String, FnBraceStyle)> {
318         let context = self.get_context();
319
320         let mut fn_brace_style = newline_for_brace(self.config, &fn_sig.generics.where_clause);
321         let (result, force_newline_brace) =
322             rewrite_fn_base(&context, indent, ident, fn_sig, span, fn_brace_style)?;
323
324         // 2 = ` {`
325         if self.config.brace_style() == BraceStyle::AlwaysNextLine
326             || force_newline_brace
327             || last_line_width(&result) + 2 > self.shape().width
328         {
329             fn_brace_style = FnBraceStyle::NextLine
330         }
331
332         Some((result, fn_brace_style))
333     }
334
335     pub(crate) fn rewrite_required_fn(
336         &mut self,
337         indent: Indent,
338         ident: symbol::Ident,
339         sig: &ast::FnSig,
340         generics: &ast::Generics,
341         span: Span,
342     ) -> Option<String> {
343         // Drop semicolon or it will be interpreted as comment.
344         let span = mk_sp(span.lo(), span.hi() - BytePos(1));
345         let context = self.get_context();
346
347         let (mut result, _) = rewrite_fn_base(
348             &context,
349             indent,
350             ident,
351             &FnSig::from_method_sig(sig, generics),
352             span,
353             FnBraceStyle::None,
354         )?;
355
356         // Re-attach semicolon
357         result.push(';');
358
359         Some(result)
360     }
361
362     pub(crate) fn single_line_fn(
363         &self,
364         fn_str: &str,
365         block: &ast::Block,
366         inner_attrs: Option<&[ast::Attribute]>,
367     ) -> Option<String> {
368         if fn_str.contains('\n') || inner_attrs.map_or(false, |a| !a.is_empty()) {
369             return None;
370         }
371
372         let context = self.get_context();
373
374         if self.config.empty_item_single_line()
375             && is_empty_block(&context, block, None)
376             && self.block_indent.width() + fn_str.len() + 3 <= self.config.max_width()
377             && !last_line_contains_single_line_comment(fn_str)
378         {
379             return Some(format!("{} {{}}", fn_str));
380         }
381
382         if !self.config.fn_single_line() || !is_simple_block_stmt(&context, block, None) {
383             return None;
384         }
385
386         let res = Stmt::from_ast_node(block.stmts.first()?, true)
387             .rewrite(&self.get_context(), self.shape())?;
388
389         let width = self.block_indent.width() + fn_str.len() + res.len() + 5;
390         if !res.contains('\n') && width <= self.config.max_width() {
391             Some(format!("{} {{ {} }}", fn_str, res))
392         } else {
393             None
394         }
395     }
396
397     pub(crate) fn visit_static(&mut self, static_parts: &StaticParts<'_>) {
398         let rewrite = rewrite_static(&self.get_context(), static_parts, self.block_indent);
399         self.push_rewrite(static_parts.span, rewrite);
400     }
401
402     pub(crate) fn visit_struct(&mut self, struct_parts: &StructParts<'_>) {
403         let is_tuple = match struct_parts.def {
404             ast::VariantData::Tuple(..) => true,
405             _ => false,
406         };
407         let rewrite = format_struct(&self.get_context(), struct_parts, self.block_indent, None)
408             .map(|s| if is_tuple { s + ";" } else { s });
409         self.push_rewrite(struct_parts.span, rewrite);
410     }
411
412     pub(crate) fn visit_enum(
413         &mut self,
414         ident: symbol::Ident,
415         vis: &ast::Visibility,
416         enum_def: &ast::EnumDef,
417         generics: &ast::Generics,
418         span: Span,
419     ) {
420         let enum_header = format_header(&self.get_context(), "enum ", ident, vis);
421         self.push_str(&enum_header);
422
423         let enum_snippet = self.snippet(span);
424         let brace_pos = enum_snippet.find_uncommented("{").unwrap();
425         let body_start = span.lo() + BytePos(brace_pos as u32 + 1);
426         let generics_str = format_generics(
427             &self.get_context(),
428             generics,
429             self.config.brace_style(),
430             if enum_def.variants.is_empty() {
431                 BracePos::ForceSameLine
432             } else {
433                 BracePos::Auto
434             },
435             self.block_indent,
436             // make a span that starts right after `enum Foo`
437             mk_sp(ident.span.hi(), body_start),
438             last_line_width(&enum_header),
439         )
440         .unwrap();
441         self.push_str(&generics_str);
442
443         self.last_pos = body_start;
444
445         match self.format_variant_list(enum_def, body_start, span.hi()) {
446             Some(ref s) if enum_def.variants.is_empty() => self.push_str(s),
447             rw => {
448                 self.push_rewrite(mk_sp(body_start, span.hi()), rw);
449                 self.block_indent = self.block_indent.block_unindent(self.config);
450             }
451         }
452     }
453
454     // Format the body of an enum definition
455     fn format_variant_list(
456         &mut self,
457         enum_def: &ast::EnumDef,
458         body_lo: BytePos,
459         body_hi: BytePos,
460     ) -> Option<String> {
461         if enum_def.variants.is_empty() {
462             let mut buffer = String::with_capacity(128);
463             // 1 = "}"
464             let span = mk_sp(body_lo, body_hi - BytePos(1));
465             format_empty_struct_or_tuple(
466                 &self.get_context(),
467                 span,
468                 self.block_indent,
469                 &mut buffer,
470                 "",
471                 "}",
472             );
473             return Some(buffer);
474         }
475         let mut result = String::with_capacity(1024);
476         let original_offset = self.block_indent;
477         self.block_indent = self.block_indent.block_indent(self.config);
478
479         // If enum variants have discriminants, try to vertically align those,
480         // provided the discrims are not shifted too much  to the right
481         let align_threshold: usize = self.config.enum_discrim_align_threshold();
482         let discr_ident_lens: Vec<usize> = enum_def
483             .variants
484             .iter()
485             .filter(|var| var.disr_expr.is_some())
486             .map(|var| rewrite_ident(&self.get_context(), var.ident).len())
487             .collect();
488         // cut the list at the point of longest discrim shorter than the threshold
489         // All of the discrims under the threshold will get padded, and all above - left as is.
490         let pad_discrim_ident_to = *discr_ident_lens
491             .iter()
492             .filter(|&l| *l <= align_threshold)
493             .max()
494             .unwrap_or(&0);
495
496         let itemize_list_with = |one_line_width: usize| {
497             itemize_list(
498                 self.snippet_provider,
499                 enum_def.variants.iter(),
500                 "}",
501                 ",",
502                 |f| {
503                     if !f.attrs.is_empty() {
504                         f.attrs[0].span.lo()
505                     } else {
506                         f.span.lo()
507                     }
508                 },
509                 |f| f.span.hi(),
510                 |f| self.format_variant(f, one_line_width, pad_discrim_ident_to),
511                 body_lo,
512                 body_hi,
513                 false,
514             )
515             .collect()
516         };
517         let mut items: Vec<_> =
518             itemize_list_with(self.config.width_heuristics().struct_variant_width);
519         // If one of the variants use multiple lines, use multi-lined formatting for all variants.
520         let has_multiline_variant = items.iter().any(|item| item.inner_as_ref().contains('\n'));
521         let has_single_line_variant = items.iter().any(|item| !item.inner_as_ref().contains('\n'));
522         if has_multiline_variant && has_single_line_variant {
523             items = itemize_list_with(0);
524         }
525
526         let shape = self.shape().sub_width(2)?;
527         let fmt = ListFormatting::new(shape, self.config)
528             .trailing_separator(self.config.trailing_comma())
529             .preserve_newline(true);
530
531         let list = write_list(&items, &fmt)?;
532         result.push_str(&list);
533         result.push_str(&original_offset.to_string_with_newline(self.config));
534         result.push('}');
535         Some(result)
536     }
537
538     // Variant of an enum.
539     fn format_variant(
540         &self,
541         field: &ast::Variant,
542         one_line_width: usize,
543         pad_discrim_ident_to: usize,
544     ) -> Option<String> {
545         if contains_skip(&field.attrs) {
546             let lo = field.attrs[0].span.lo();
547             let span = mk_sp(lo, field.span.hi());
548             return Some(self.snippet(span).to_owned());
549         }
550
551         let context = self.get_context();
552         // 1 = ','
553         let shape = self.shape().sub_width(1)?;
554         let attrs_str = field.attrs.rewrite(&context, shape)?;
555         let lo = field
556             .attrs
557             .last()
558             .map_or(field.span.lo(), |attr| attr.span.hi());
559         let span = mk_sp(lo, field.span.lo());
560
561         let variant_body = match field.data {
562             ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => format_struct(
563                 &context,
564                 &StructParts::from_variant(field),
565                 self.block_indent,
566                 Some(one_line_width),
567             )?,
568             ast::VariantData::Unit(..) => rewrite_ident(&context, field.ident).to_owned(),
569         };
570
571         let variant_body = if let Some(ref expr) = field.disr_expr {
572             let lhs = format!("{:1$} =", variant_body, pad_discrim_ident_to);
573             rewrite_assign_rhs_with(
574                 &context,
575                 lhs,
576                 &*expr.value,
577                 shape,
578                 RhsTactics::AllowOverflow,
579             )?
580         } else {
581             variant_body
582         };
583
584         combine_strs_with_missing_comments(&context, &attrs_str, &variant_body, span, shape, false)
585     }
586
587     fn visit_impl_items(&mut self, items: &[ptr::P<ast::AssocItem>]) {
588         if self.get_context().config.reorder_impl_items() {
589             // Create visitor for each items, then reorder them.
590             let mut buffer = vec![];
591             for item in items {
592                 self.visit_impl_item(item);
593                 buffer.push((self.buffer.clone(), item.clone()));
594                 self.buffer.clear();
595             }
596
597             fn is_type(ty: &Option<rustc_ast::ptr::P<ast::Ty>>) -> bool {
598                 if let Some(lty) = ty {
599                     if let ast::TyKind::ImplTrait(..) = lty.kind {
600                         return false;
601                     }
602                 }
603                 true
604             }
605
606             fn is_opaque(ty: &Option<rustc_ast::ptr::P<ast::Ty>>) -> bool {
607                 !is_type(ty)
608             }
609
610             fn both_type(
611                 a: &Option<rustc_ast::ptr::P<ast::Ty>>,
612                 b: &Option<rustc_ast::ptr::P<ast::Ty>>,
613             ) -> bool {
614                 is_type(a) && is_type(b)
615             }
616
617             fn both_opaque(
618                 a: &Option<rustc_ast::ptr::P<ast::Ty>>,
619                 b: &Option<rustc_ast::ptr::P<ast::Ty>>,
620             ) -> bool {
621                 is_opaque(a) && is_opaque(b)
622             }
623
624             // In rustc-ap-v638 the `OpaqueTy` AssocItemKind variant was removed but
625             // we still need to differentiate to maintain sorting order.
626
627             // type -> opaque -> const -> macro -> method
628             use crate::ast::AssocItemKind::*;
629             fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool {
630                 match (a, b) {
631                     (TyAlias(_, _, _, ref lty), TyAlias(_, _, _, ref rty))
632                         if both_type(lty, rty) || both_opaque(lty, rty) =>
633                     {
634                         false
635                     }
636                     (Const(..), Const(..)) => false,
637                     _ => true,
638                 }
639             }
640
641             buffer.sort_by(|(_, a), (_, b)| match (&a.kind, &b.kind) {
642                 (TyAlias(_, _, _, ref lty), TyAlias(_, _, _, ref rty))
643                     if both_type(lty, rty) || both_opaque(lty, rty) =>
644                 {
645                     a.ident.as_str().cmp(&b.ident.as_str())
646                 }
647                 (Const(..), Const(..)) | (MacCall(..), MacCall(..)) => {
648                     a.ident.as_str().cmp(&b.ident.as_str())
649                 }
650                 (Fn(..), Fn(..)) => a.span.lo().cmp(&b.span.lo()),
651                 (TyAlias(_, _, _, ref ty), _) if is_type(ty) => Ordering::Less,
652                 (_, TyAlias(_, _, _, ref ty)) if is_type(ty) => Ordering::Greater,
653                 (TyAlias(..), _) => Ordering::Less,
654                 (_, TyAlias(..)) => Ordering::Greater,
655                 (Const(..), _) => Ordering::Less,
656                 (_, Const(..)) => Ordering::Greater,
657                 (MacCall(..), _) => Ordering::Less,
658                 (_, MacCall(..)) => Ordering::Greater,
659             });
660             let mut prev_kind = None;
661             for (buf, item) in buffer {
662                 // Make sure that there are at least a single empty line between
663                 // different impl items.
664                 if prev_kind
665                     .as_ref()
666                     .map_or(false, |prev_kind| need_empty_line(prev_kind, &item.kind))
667                 {
668                     self.push_str("\n");
669                 }
670                 let indent_str = self.block_indent.to_string_with_newline(self.config);
671                 self.push_str(&indent_str);
672                 self.push_str(buf.trim());
673                 prev_kind = Some(item.kind.clone());
674             }
675         } else {
676             for item in items {
677                 self.visit_impl_item(item);
678             }
679         }
680     }
681 }
682
683 pub(crate) fn format_impl(
684     context: &RewriteContext<'_>,
685     item: &ast::Item,
686     offset: Indent,
687 ) -> Option<String> {
688     if let ast::ItemKind::Impl {
689         ref generics,
690         ref self_ty,
691         ref items,
692         ..
693     } = item.kind
694     {
695         let mut result = String::with_capacity(128);
696         let ref_and_type = format_impl_ref_and_type(context, item, offset)?;
697         let sep = offset.to_string_with_newline(context.config);
698         result.push_str(&ref_and_type);
699
700         let where_budget = if result.contains('\n') {
701             context.config.max_width()
702         } else {
703             context.budget(last_line_width(&result))
704         };
705
706         let mut option = WhereClauseOption::snuggled(&ref_and_type);
707         let snippet = context.snippet(item.span);
708         let open_pos = snippet.find_uncommented("{")? + 1;
709         if !contains_comment(&snippet[open_pos..])
710             && items.is_empty()
711             && generics.where_clause.predicates.len() == 1
712             && !result.contains('\n')
713         {
714             option.suppress_comma();
715             option.snuggle();
716             option.allow_single_line();
717         }
718
719         let missing_span = mk_sp(self_ty.span.hi(), item.span.hi());
720         let where_span_end = context.snippet_provider.opt_span_before(missing_span, "{");
721         let where_clause_str = rewrite_where_clause(
722             context,
723             &generics.where_clause,
724             context.config.brace_style(),
725             Shape::legacy(where_budget, offset.block_only()),
726             false,
727             "{",
728             where_span_end,
729             self_ty.span.hi(),
730             option,
731         )?;
732
733         // If there is no where-clause, we may have missing comments between the trait name and
734         // the opening brace.
735         if generics.where_clause.predicates.is_empty() {
736             if let Some(hi) = where_span_end {
737                 match recover_missing_comment_in_span(
738                     mk_sp(self_ty.span.hi(), hi),
739                     Shape::indented(offset, context.config),
740                     context,
741                     last_line_width(&result),
742                 ) {
743                     Some(ref missing_comment) if !missing_comment.is_empty() => {
744                         result.push_str(missing_comment);
745                     }
746                     _ => (),
747                 }
748             }
749         }
750
751         if is_impl_single_line(context, items.as_slice(), &result, &where_clause_str, item)? {
752             result.push_str(&where_clause_str);
753             if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) {
754                 // if the where_clause contains extra comments AND
755                 // there is only one where-clause predicate
756                 // recover the suppressed comma in single line where_clause formatting
757                 if generics.where_clause.predicates.len() == 1 {
758                     result.push_str(",");
759                 }
760                 result.push_str(&format!("{}{{{}}}", sep, sep));
761             } else {
762                 result.push_str(" {}");
763             }
764             return Some(result);
765         }
766
767         result.push_str(&where_clause_str);
768
769         let need_newline = last_line_contains_single_line_comment(&result) || result.contains('\n');
770         match context.config.brace_style() {
771             _ if need_newline => result.push_str(&sep),
772             BraceStyle::AlwaysNextLine => result.push_str(&sep),
773             BraceStyle::PreferSameLine => result.push(' '),
774             BraceStyle::SameLineWhere => {
775                 if !where_clause_str.is_empty() {
776                     result.push_str(&sep);
777                 } else {
778                     result.push(' ');
779                 }
780             }
781         }
782
783         result.push('{');
784         // this is an impl body snippet(impl SampleImpl { /* here */ })
785         let lo = max(self_ty.span.hi(), generics.where_clause.span.hi());
786         let snippet = context.snippet(mk_sp(lo, item.span.hi()));
787         let open_pos = snippet.find_uncommented("{")? + 1;
788
789         if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
790             let mut visitor = FmtVisitor::from_context(context);
791             let item_indent = offset.block_only().block_indent(context.config);
792             visitor.block_indent = item_indent;
793             visitor.last_pos = lo + BytePos(open_pos as u32);
794
795             visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner);
796             visitor.visit_impl_items(items);
797
798             visitor.format_missing(item.span.hi() - BytePos(1));
799
800             let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config);
801             let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
802
803             result.push_str(&inner_indent_str);
804             result.push_str(visitor.buffer.trim());
805             result.push_str(&outer_indent_str);
806         } else if need_newline || !context.config.empty_item_single_line() {
807             result.push_str(&sep);
808         }
809
810         result.push('}');
811
812         Some(result)
813     } else {
814         unreachable!();
815     }
816 }
817
818 fn is_impl_single_line(
819     context: &RewriteContext<'_>,
820     items: &[ptr::P<ast::AssocItem>],
821     result: &str,
822     where_clause_str: &str,
823     item: &ast::Item,
824 ) -> Option<bool> {
825     let snippet = context.snippet(item.span);
826     let open_pos = snippet.find_uncommented("{")? + 1;
827
828     Some(
829         context.config.empty_item_single_line()
830             && items.is_empty()
831             && !result.contains('\n')
832             && result.len() + where_clause_str.len() <= context.config.max_width()
833             && !contains_comment(&snippet[open_pos..]),
834     )
835 }
836
837 fn format_impl_ref_and_type(
838     context: &RewriteContext<'_>,
839     item: &ast::Item,
840     offset: Indent,
841 ) -> Option<String> {
842     if let ast::ItemKind::Impl {
843         unsafety,
844         polarity,
845         defaultness,
846         ref generics,
847         of_trait: ref trait_ref,
848         ref self_ty,
849         ..
850     } = item.kind
851     {
852         let mut result = String::with_capacity(128);
853
854         result.push_str(&format_visibility(context, &item.vis));
855         result.push_str(format_defaultness(defaultness));
856         result.push_str(format_unsafety(unsafety));
857
858         let shape = if context.config.version() == Version::Two {
859             Shape::indented(offset + last_line_width(&result), context.config)
860         } else {
861             generics_shape_from_config(
862                 context.config,
863                 Shape::indented(offset + last_line_width(&result), context.config),
864                 0,
865             )?
866         };
867         let generics_str = rewrite_generics(context, "impl", generics, shape)?;
868         result.push_str(&generics_str);
869
870         let polarity_str = match polarity {
871             ast::ImplPolarity::Negative(_) => "!",
872             ast::ImplPolarity::Positive => "",
873         };
874
875         if let Some(ref trait_ref) = *trait_ref {
876             let result_len = last_line_width(&result);
877             result.push_str(&rewrite_trait_ref(
878                 context,
879                 trait_ref,
880                 offset,
881                 polarity_str,
882                 result_len,
883             )?);
884         }
885
886         // Try to put the self type in a single line.
887         // ` for`
888         let trait_ref_overhead = if trait_ref.is_some() { 4 } else { 0 };
889         let curly_brace_overhead = if generics.where_clause.predicates.is_empty() {
890             // If there is no where-clause adapt budget for type formatting to take space and curly
891             // brace into account.
892             match context.config.brace_style() {
893                 BraceStyle::AlwaysNextLine => 0,
894                 _ => 2,
895             }
896         } else {
897             0
898         };
899         let used_space = last_line_width(&result) + trait_ref_overhead + curly_brace_overhead;
900         // 1 = space before the type.
901         let budget = context.budget(used_space + 1);
902         if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) {
903             if !self_ty_str.contains('\n') {
904                 if trait_ref.is_some() {
905                     result.push_str(" for ");
906                 } else {
907                     result.push(' ');
908                 }
909                 result.push_str(&self_ty_str);
910                 return Some(result);
911             }
912         }
913
914         // Couldn't fit the self type on a single line, put it on a new line.
915         result.push('\n');
916         // Add indentation of one additional tab.
917         let new_line_offset = offset.block_indent(context.config);
918         result.push_str(&new_line_offset.to_string(context.config));
919         if trait_ref.is_some() {
920             result.push_str("for ");
921         }
922         let budget = context.budget(last_line_width(&result));
923         let type_offset = match context.config.indent_style() {
924             IndentStyle::Visual => new_line_offset + trait_ref_overhead,
925             IndentStyle::Block => new_line_offset,
926         };
927         result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?);
928         Some(result)
929     } else {
930         unreachable!();
931     }
932 }
933
934 fn rewrite_trait_ref(
935     context: &RewriteContext<'_>,
936     trait_ref: &ast::TraitRef,
937     offset: Indent,
938     polarity_str: &str,
939     result_len: usize,
940 ) -> Option<String> {
941     // 1 = space between generics and trait_ref
942     let used_space = 1 + polarity_str.len() + result_len;
943     let shape = Shape::indented(offset + used_space, context.config);
944     if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) {
945         if !trait_ref_str.contains('\n') {
946             return Some(format!(" {}{}", polarity_str, trait_ref_str));
947         }
948     }
949     // We could not make enough space for trait_ref, so put it on new line.
950     let offset = offset.block_indent(context.config);
951     let shape = Shape::indented(offset, context.config);
952     let trait_ref_str = trait_ref.rewrite(context, shape)?;
953     Some(format!(
954         "{}{}{}",
955         offset.to_string_with_newline(context.config),
956         polarity_str,
957         trait_ref_str
958     ))
959 }
960
961 pub(crate) struct StructParts<'a> {
962     prefix: &'a str,
963     ident: symbol::Ident,
964     vis: &'a ast::Visibility,
965     def: &'a ast::VariantData,
966     generics: Option<&'a ast::Generics>,
967     span: Span,
968 }
969
970 impl<'a> StructParts<'a> {
971     fn format_header(&self, context: &RewriteContext<'_>) -> String {
972         format_header(context, self.prefix, self.ident, self.vis)
973     }
974
975     fn from_variant(variant: &'a ast::Variant) -> Self {
976         StructParts {
977             prefix: "",
978             ident: variant.ident,
979             vis: &DEFAULT_VISIBILITY,
980             def: &variant.data,
981             generics: None,
982             span: variant.span,
983         }
984     }
985
986     pub(crate) fn from_item(item: &'a ast::Item) -> Self {
987         let (prefix, def, generics) = match item.kind {
988             ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics),
989             ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics),
990             _ => unreachable!(),
991         };
992         StructParts {
993             prefix,
994             ident: item.ident,
995             vis: &item.vis,
996             def,
997             generics: Some(generics),
998             span: item.span,
999         }
1000     }
1001 }
1002
1003 fn format_struct(
1004     context: &RewriteContext<'_>,
1005     struct_parts: &StructParts<'_>,
1006     offset: Indent,
1007     one_line_width: Option<usize>,
1008 ) -> Option<String> {
1009     match *struct_parts.def {
1010         ast::VariantData::Unit(..) => format_unit_struct(context, struct_parts, offset),
1011         ast::VariantData::Tuple(ref fields, _) => {
1012             format_tuple_struct(context, struct_parts, fields, offset)
1013         }
1014         ast::VariantData::Struct(ref fields, _) => {
1015             format_struct_struct(context, struct_parts, fields, offset, one_line_width)
1016         }
1017     }
1018 }
1019
1020 pub(crate) fn format_trait(
1021     context: &RewriteContext<'_>,
1022     item: &ast::Item,
1023     offset: Indent,
1024 ) -> Option<String> {
1025     if let ast::ItemKind::Trait(
1026         is_auto,
1027         unsafety,
1028         ref generics,
1029         ref generic_bounds,
1030         ref trait_items,
1031     ) = item.kind
1032     {
1033         let mut result = String::with_capacity(128);
1034         let header = format!(
1035             "{}{}{}trait ",
1036             format_visibility(context, &item.vis),
1037             format_unsafety(unsafety),
1038             format_auto(is_auto),
1039         );
1040         result.push_str(&header);
1041
1042         let body_lo = context.snippet_provider.span_after(item.span, "{");
1043
1044         let shape = Shape::indented(offset, context.config).offset_left(result.len())?;
1045         let generics_str =
1046             rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape)?;
1047         result.push_str(&generics_str);
1048
1049         // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
1050         if !generic_bounds.is_empty() {
1051             let ident_hi = context
1052                 .snippet_provider
1053                 .span_after(item.span, &item.ident.as_str());
1054             let bound_hi = generic_bounds.last().unwrap().span().hi();
1055             let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
1056             if contains_comment(snippet) {
1057                 return None;
1058             }
1059
1060             result = rewrite_assign_rhs_with(
1061                 context,
1062                 result + ":",
1063                 generic_bounds,
1064                 shape,
1065                 RhsTactics::ForceNextLineWithoutIndent,
1066             )?;
1067         }
1068
1069         // Rewrite where-clause.
1070         if !generics.where_clause.predicates.is_empty() {
1071             let where_on_new_line = context.config.indent_style() != IndentStyle::Block;
1072
1073             let where_budget = context.budget(last_line_width(&result));
1074             let pos_before_where = if generic_bounds.is_empty() {
1075                 generics.where_clause.span.lo()
1076             } else {
1077                 generic_bounds[generic_bounds.len() - 1].span().hi()
1078             };
1079             let option = WhereClauseOption::snuggled(&generics_str);
1080             let where_clause_str = rewrite_where_clause(
1081                 context,
1082                 &generics.where_clause,
1083                 context.config.brace_style(),
1084                 Shape::legacy(where_budget, offset.block_only()),
1085                 where_on_new_line,
1086                 "{",
1087                 None,
1088                 pos_before_where,
1089                 option,
1090             )?;
1091             // If the where-clause cannot fit on the same line,
1092             // put the where-clause on a new line
1093             if !where_clause_str.contains('\n')
1094                 && last_line_width(&result) + where_clause_str.len() + offset.width()
1095                     > context.config.comment_width()
1096             {
1097                 let width = offset.block_indent + context.config.tab_spaces() - 1;
1098                 let where_indent = Indent::new(0, width);
1099                 result.push_str(&where_indent.to_string_with_newline(context.config));
1100             }
1101             result.push_str(&where_clause_str);
1102         } else {
1103             let item_snippet = context.snippet(item.span);
1104             if let Some(lo) = item_snippet.find('/') {
1105                 // 1 = `{`
1106                 let comment_hi = body_lo - BytePos(1);
1107                 let comment_lo = item.span.lo() + BytePos(lo as u32);
1108                 if comment_lo < comment_hi {
1109                     match recover_missing_comment_in_span(
1110                         mk_sp(comment_lo, comment_hi),
1111                         Shape::indented(offset, context.config),
1112                         context,
1113                         last_line_width(&result),
1114                     ) {
1115                         Some(ref missing_comment) if !missing_comment.is_empty() => {
1116                             result.push_str(missing_comment);
1117                         }
1118                         _ => (),
1119                     }
1120                 }
1121             }
1122         }
1123
1124         match context.config.brace_style() {
1125             _ if last_line_contains_single_line_comment(&result)
1126                 || last_line_width(&result) + 2 > context.budget(offset.width()) =>
1127             {
1128                 result.push_str(&offset.to_string_with_newline(context.config));
1129             }
1130             BraceStyle::AlwaysNextLine => {
1131                 result.push_str(&offset.to_string_with_newline(context.config));
1132             }
1133             BraceStyle::PreferSameLine => result.push(' '),
1134             BraceStyle::SameLineWhere => {
1135                 if result.contains('\n')
1136                     || (!generics.where_clause.predicates.is_empty() && !trait_items.is_empty())
1137                 {
1138                     result.push_str(&offset.to_string_with_newline(context.config));
1139                 } else {
1140                     result.push(' ');
1141                 }
1142             }
1143         }
1144         result.push('{');
1145
1146         let snippet = context.snippet(item.span);
1147         let open_pos = snippet.find_uncommented("{")? + 1;
1148         let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
1149
1150         if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) {
1151             let mut visitor = FmtVisitor::from_context(context);
1152             visitor.block_indent = offset.block_only().block_indent(context.config);
1153             visitor.last_pos = item.span.lo() + BytePos(open_pos as u32);
1154
1155             for item in trait_items {
1156                 visitor.visit_trait_item(item);
1157             }
1158
1159             visitor.format_missing(item.span.hi() - BytePos(1));
1160
1161             let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config);
1162
1163             result.push_str(&inner_indent_str);
1164             result.push_str(visitor.buffer.trim());
1165             result.push_str(&outer_indent_str);
1166         } else if result.contains('\n') {
1167             result.push_str(&outer_indent_str);
1168         }
1169
1170         result.push('}');
1171         Some(result)
1172     } else {
1173         unreachable!();
1174     }
1175 }
1176
1177 struct OpaqueTypeBounds<'a> {
1178     generic_bounds: &'a ast::GenericBounds,
1179 }
1180
1181 impl<'a> Rewrite for OpaqueTypeBounds<'a> {
1182     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
1183         self.generic_bounds
1184             .rewrite(context, shape)
1185             .map(|s| format!("impl {}", s))
1186     }
1187 }
1188
1189 pub(crate) struct TraitAliasBounds<'a> {
1190     generic_bounds: &'a ast::GenericBounds,
1191     generics: &'a ast::Generics,
1192 }
1193
1194 impl<'a> Rewrite for TraitAliasBounds<'a> {
1195     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
1196         let generic_bounds_str = self.generic_bounds.rewrite(context, shape)?;
1197
1198         let mut option = WhereClauseOption::new(true, WhereClauseSpace::None);
1199         option.allow_single_line();
1200
1201         let where_str = rewrite_where_clause(
1202             context,
1203             &self.generics.where_clause,
1204             context.config.brace_style(),
1205             shape,
1206             false,
1207             ";",
1208             None,
1209             self.generics.where_clause.span.lo(),
1210             option,
1211         )?;
1212
1213         let fits_single_line = !generic_bounds_str.contains('\n')
1214             && !where_str.contains('\n')
1215             && generic_bounds_str.len() + where_str.len() + 1 <= shape.width;
1216         let space = if generic_bounds_str.is_empty() || where_str.is_empty() {
1217             Cow::from("")
1218         } else if fits_single_line {
1219             Cow::from(" ")
1220         } else {
1221             shape.indent.to_string_with_newline(&context.config)
1222         };
1223
1224         Some(format!("{}{}{}", generic_bounds_str, space, where_str))
1225     }
1226 }
1227
1228 pub(crate) fn format_trait_alias(
1229     context: &RewriteContext<'_>,
1230     ident: symbol::Ident,
1231     vis: &ast::Visibility,
1232     generics: &ast::Generics,
1233     generic_bounds: &ast::GenericBounds,
1234     shape: Shape,
1235 ) -> Option<String> {
1236     let alias = rewrite_ident(context, ident);
1237     // 6 = "trait ", 2 = " ="
1238     let g_shape = shape.offset_left(6)?.sub_width(2)?;
1239     let generics_str = rewrite_generics(context, &alias, generics, g_shape)?;
1240     let vis_str = format_visibility(context, vis);
1241     let lhs = format!("{}trait {} =", vis_str, generics_str);
1242     // 1 = ";"
1243     let trait_alias_bounds = TraitAliasBounds {
1244         generics,
1245         generic_bounds,
1246     };
1247     rewrite_assign_rhs(context, lhs, &trait_alias_bounds, shape.sub_width(1)?).map(|s| s + ";")
1248 }
1249
1250 fn format_unit_struct(
1251     context: &RewriteContext<'_>,
1252     p: &StructParts<'_>,
1253     offset: Indent,
1254 ) -> Option<String> {
1255     let header_str = format_header(context, p.prefix, p.ident, p.vis);
1256     let generics_str = if let Some(generics) = p.generics {
1257         let hi = context.snippet_provider.span_before(p.span, ";");
1258         format_generics(
1259             context,
1260             generics,
1261             context.config.brace_style(),
1262             BracePos::None,
1263             offset,
1264             // make a span that starts right after `struct Foo`
1265             mk_sp(p.ident.span.hi(), hi),
1266             last_line_width(&header_str),
1267         )?
1268     } else {
1269         String::new()
1270     };
1271     Some(format!("{}{};", header_str, generics_str))
1272 }
1273
1274 pub(crate) fn format_struct_struct(
1275     context: &RewriteContext<'_>,
1276     struct_parts: &StructParts<'_>,
1277     fields: &[ast::StructField],
1278     offset: Indent,
1279     one_line_width: Option<usize>,
1280 ) -> Option<String> {
1281     let mut result = String::with_capacity(1024);
1282     let span = struct_parts.span;
1283
1284     let header_str = struct_parts.format_header(context);
1285     result.push_str(&header_str);
1286
1287     let header_hi = struct_parts.ident.span.hi();
1288     let body_lo = context.snippet_provider.span_after(span, "{");
1289
1290     let generics_str = match struct_parts.generics {
1291         Some(g) => format_generics(
1292             context,
1293             g,
1294             context.config.brace_style(),
1295             if fields.is_empty() {
1296                 BracePos::ForceSameLine
1297             } else {
1298                 BracePos::Auto
1299             },
1300             offset,
1301             // make a span that starts right after `struct Foo`
1302             mk_sp(header_hi, body_lo),
1303             last_line_width(&result),
1304         )?,
1305         None => {
1306             // 3 = ` {}`, 2 = ` {`.
1307             let overhead = if fields.is_empty() { 3 } else { 2 };
1308             if (context.config.brace_style() == BraceStyle::AlwaysNextLine && !fields.is_empty())
1309                 || context.config.max_width() < overhead + result.len()
1310             {
1311                 format!("\n{}{{", offset.block_only().to_string(context.config))
1312             } else {
1313                 " {".to_owned()
1314             }
1315         }
1316     };
1317     // 1 = `}`
1318     let overhead = if fields.is_empty() { 1 } else { 0 };
1319     let total_width = result.len() + generics_str.len() + overhead;
1320     if !generics_str.is_empty()
1321         && !generics_str.contains('\n')
1322         && total_width > context.config.max_width()
1323     {
1324         result.push('\n');
1325         result.push_str(&offset.to_string(context.config));
1326         result.push_str(generics_str.trim_start());
1327     } else {
1328         result.push_str(&generics_str);
1329     }
1330
1331     if fields.is_empty() {
1332         let inner_span = mk_sp(body_lo, span.hi() - BytePos(1));
1333         format_empty_struct_or_tuple(context, inner_span, offset, &mut result, "", "}");
1334         return Some(result);
1335     }
1336
1337     // 3 = ` ` and ` }`
1338     let one_line_budget = context.budget(result.len() + 3 + offset.width());
1339     let one_line_budget =
1340         one_line_width.map_or(0, |one_line_width| min(one_line_width, one_line_budget));
1341
1342     let items_str = rewrite_with_alignment(
1343         fields,
1344         context,
1345         Shape::indented(offset.block_indent(context.config), context.config).sub_width(1)?,
1346         mk_sp(body_lo, span.hi()),
1347         one_line_budget,
1348     )?;
1349
1350     if !items_str.contains('\n')
1351         && !result.contains('\n')
1352         && items_str.len() <= one_line_budget
1353         && !last_line_contains_single_line_comment(&items_str)
1354     {
1355         Some(format!("{} {} }}", result, items_str))
1356     } else {
1357         Some(format!(
1358             "{}\n{}{}\n{}}}",
1359             result,
1360             offset
1361                 .block_indent(context.config)
1362                 .to_string(context.config),
1363             items_str,
1364             offset.to_string(context.config)
1365         ))
1366     }
1367 }
1368
1369 fn get_bytepos_after_visibility(vis: &ast::Visibility, default_span: Span) -> BytePos {
1370     match vis.node {
1371         ast::VisibilityKind::Crate(..) | ast::VisibilityKind::Restricted { .. } => vis.span.hi(),
1372         _ => default_span.lo(),
1373     }
1374 }
1375
1376 // Format tuple or struct without any fields. We need to make sure that the comments
1377 // inside the delimiters are preserved.
1378 fn format_empty_struct_or_tuple(
1379     context: &RewriteContext<'_>,
1380     span: Span,
1381     offset: Indent,
1382     result: &mut String,
1383     opener: &str,
1384     closer: &str,
1385 ) {
1386     // 3 = " {}" or "();"
1387     let used_width = last_line_used_width(&result, offset.width()) + 3;
1388     if used_width > context.config.max_width() {
1389         result.push_str(&offset.to_string_with_newline(context.config))
1390     }
1391     result.push_str(opener);
1392     match rewrite_missing_comment(span, Shape::indented(offset, context.config), context) {
1393         Some(ref s) if s.is_empty() => (),
1394         Some(ref s) => {
1395             if !is_single_line(s) || first_line_contains_single_line_comment(s) {
1396                 let nested_indent_str = offset
1397                     .block_indent(context.config)
1398                     .to_string_with_newline(context.config);
1399                 result.push_str(&nested_indent_str);
1400             }
1401             result.push_str(s);
1402             if last_line_contains_single_line_comment(s) {
1403                 result.push_str(&offset.to_string_with_newline(context.config));
1404             }
1405         }
1406         None => result.push_str(context.snippet(span)),
1407     }
1408     result.push_str(closer);
1409 }
1410
1411 fn format_tuple_struct(
1412     context: &RewriteContext<'_>,
1413     struct_parts: &StructParts<'_>,
1414     fields: &[ast::StructField],
1415     offset: Indent,
1416 ) -> Option<String> {
1417     let mut result = String::with_capacity(1024);
1418     let span = struct_parts.span;
1419
1420     let header_str = struct_parts.format_header(context);
1421     result.push_str(&header_str);
1422
1423     let body_lo = if fields.is_empty() {
1424         let lo = get_bytepos_after_visibility(struct_parts.vis, span);
1425         context
1426             .snippet_provider
1427             .span_after(mk_sp(lo, span.hi()), "(")
1428     } else {
1429         fields[0].span.lo()
1430     };
1431     let body_hi = if fields.is_empty() {
1432         context
1433             .snippet_provider
1434             .span_after(mk_sp(body_lo, span.hi()), ")")
1435     } else {
1436         // This is a dirty hack to work around a missing `)` from the span of the last field.
1437         let last_arg_span = fields[fields.len() - 1].span;
1438         context
1439             .snippet_provider
1440             .opt_span_after(mk_sp(last_arg_span.hi(), span.hi()), ")")
1441             .unwrap_or_else(|| last_arg_span.hi())
1442     };
1443
1444     let where_clause_str = match struct_parts.generics {
1445         Some(generics) => {
1446             let budget = context.budget(last_line_width(&header_str));
1447             let shape = Shape::legacy(budget, offset);
1448             let generics_str = rewrite_generics(context, "", generics, shape)?;
1449             result.push_str(&generics_str);
1450
1451             let where_budget = context.budget(last_line_width(&result));
1452             let option = WhereClauseOption::new(true, WhereClauseSpace::Newline);
1453             rewrite_where_clause(
1454                 context,
1455                 &generics.where_clause,
1456                 context.config.brace_style(),
1457                 Shape::legacy(where_budget, offset.block_only()),
1458                 false,
1459                 ";",
1460                 None,
1461                 body_hi,
1462                 option,
1463             )?
1464         }
1465         None => "".to_owned(),
1466     };
1467
1468     if fields.is_empty() {
1469         let body_hi = context
1470             .snippet_provider
1471             .span_before(mk_sp(body_lo, span.hi()), ")");
1472         let inner_span = mk_sp(body_lo, body_hi);
1473         format_empty_struct_or_tuple(context, inner_span, offset, &mut result, "(", ")");
1474     } else {
1475         let shape = Shape::indented(offset, context.config).sub_width(1)?;
1476         result = overflow::rewrite_with_parens(
1477             context,
1478             &result,
1479             fields.iter(),
1480             shape,
1481             span,
1482             context.config.width_heuristics().fn_call_width,
1483             None,
1484         )?;
1485     }
1486
1487     if !where_clause_str.is_empty()
1488         && !where_clause_str.contains('\n')
1489         && (result.contains('\n')
1490             || offset.block_indent + result.len() + where_clause_str.len() + 1
1491                 > context.config.max_width())
1492     {
1493         // We need to put the where-clause on a new line, but we didn't
1494         // know that earlier, so the where-clause will not be indented properly.
1495         result.push('\n');
1496         result.push_str(
1497             &(offset.block_only() + (context.config.tab_spaces() - 1)).to_string(context.config),
1498         );
1499     }
1500     result.push_str(&where_clause_str);
1501
1502     Some(result)
1503 }
1504
1505 fn rewrite_type_prefix(
1506     context: &RewriteContext<'_>,
1507     indent: Indent,
1508     prefix: &str,
1509     ident: symbol::Ident,
1510     generics: &ast::Generics,
1511 ) -> Option<String> {
1512     let mut result = String::with_capacity(128);
1513     result.push_str(prefix);
1514     let ident_str = rewrite_ident(context, ident);
1515
1516     // 2 = `= `
1517     if generics.params.is_empty() {
1518         result.push_str(ident_str)
1519     } else {
1520         let g_shape = Shape::indented(indent, context.config)
1521             .offset_left(result.len())?
1522             .sub_width(2)?;
1523         let generics_str = rewrite_generics(context, ident_str, generics, g_shape)?;
1524         result.push_str(&generics_str);
1525     }
1526
1527     let where_budget = context.budget(last_line_width(&result));
1528     let option = WhereClauseOption::snuggled(&result);
1529     let where_clause_str = rewrite_where_clause(
1530         context,
1531         &generics.where_clause,
1532         context.config.brace_style(),
1533         Shape::legacy(where_budget, indent),
1534         false,
1535         "=",
1536         None,
1537         generics.span.hi(),
1538         option,
1539     )?;
1540     result.push_str(&where_clause_str);
1541
1542     Some(result)
1543 }
1544
1545 fn rewrite_type_item<R: Rewrite>(
1546     context: &RewriteContext<'_>,
1547     indent: Indent,
1548     prefix: &str,
1549     suffix: &str,
1550     ident: symbol::Ident,
1551     rhs: &R,
1552     generics: &ast::Generics,
1553     vis: &ast::Visibility,
1554 ) -> Option<String> {
1555     let mut result = String::with_capacity(128);
1556     result.push_str(&rewrite_type_prefix(
1557         context,
1558         indent,
1559         &format!("{}{} ", format_visibility(context, vis), prefix),
1560         ident,
1561         generics,
1562     )?);
1563
1564     if generics.where_clause.predicates.is_empty() {
1565         result.push_str(suffix);
1566     } else {
1567         result.push_str(&indent.to_string_with_newline(context.config));
1568         result.push_str(suffix.trim_start());
1569     }
1570
1571     // 1 = ";"
1572     let rhs_shape = Shape::indented(indent, context.config).sub_width(1)?;
1573     rewrite_assign_rhs(context, result, rhs, rhs_shape).map(|s| s + ";")
1574 }
1575
1576 pub(crate) fn rewrite_type_alias(
1577     context: &RewriteContext<'_>,
1578     indent: Indent,
1579     ident: symbol::Ident,
1580     ty: &ast::Ty,
1581     generics: &ast::Generics,
1582     vis: &ast::Visibility,
1583 ) -> Option<String> {
1584     rewrite_type_item(context, indent, "type", " =", ident, ty, generics, vis)
1585 }
1586
1587 pub(crate) fn rewrite_opaque_type(
1588     context: &RewriteContext<'_>,
1589     indent: Indent,
1590     ident: symbol::Ident,
1591     generic_bounds: &ast::GenericBounds,
1592     generics: &ast::Generics,
1593     vis: &ast::Visibility,
1594 ) -> Option<String> {
1595     let opaque_type_bounds = OpaqueTypeBounds { generic_bounds };
1596     rewrite_type_item(
1597         context,
1598         indent,
1599         "type",
1600         " =",
1601         ident,
1602         &opaque_type_bounds,
1603         generics,
1604         vis,
1605     )
1606 }
1607
1608 fn type_annotation_spacing(config: &Config) -> (&str, &str) {
1609     (
1610         if config.space_before_colon() { " " } else { "" },
1611         if config.space_after_colon() { " " } else { "" },
1612     )
1613 }
1614
1615 pub(crate) fn rewrite_struct_field_prefix(
1616     context: &RewriteContext<'_>,
1617     field: &ast::StructField,
1618 ) -> Option<String> {
1619     let vis = format_visibility(context, &field.vis);
1620     let type_annotation_spacing = type_annotation_spacing(context.config);
1621     Some(match field.ident {
1622         Some(name) => format!(
1623             "{}{}{}:",
1624             vis,
1625             rewrite_ident(context, name),
1626             type_annotation_spacing.0
1627         ),
1628         None => vis.to_string(),
1629     })
1630 }
1631
1632 impl Rewrite for ast::StructField {
1633     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
1634         rewrite_struct_field(context, self, shape, 0)
1635     }
1636 }
1637
1638 pub(crate) fn rewrite_struct_field(
1639     context: &RewriteContext<'_>,
1640     field: &ast::StructField,
1641     shape: Shape,
1642     lhs_max_width: usize,
1643 ) -> Option<String> {
1644     if contains_skip(&field.attrs) {
1645         return Some(context.snippet(field.span()).to_owned());
1646     }
1647
1648     let type_annotation_spacing = type_annotation_spacing(context.config);
1649     let prefix = rewrite_struct_field_prefix(context, field)?;
1650
1651     let attrs_str = field.attrs.rewrite(context, shape)?;
1652     let attrs_extendable = field.ident.is_none() && is_attributes_extendable(&attrs_str);
1653     let missing_span = if field.attrs.is_empty() {
1654         mk_sp(field.span.lo(), field.span.lo())
1655     } else {
1656         mk_sp(field.attrs.last().unwrap().span.hi(), field.span.lo())
1657     };
1658     let mut spacing = String::from(if field.ident.is_some() {
1659         type_annotation_spacing.1
1660     } else {
1661         ""
1662     });
1663     // Try to put everything on a single line.
1664     let attr_prefix = combine_strs_with_missing_comments(
1665         context,
1666         &attrs_str,
1667         &prefix,
1668         missing_span,
1669         shape,
1670         attrs_extendable,
1671     )?;
1672     let overhead = trimmed_last_line_width(&attr_prefix);
1673     let lhs_offset = lhs_max_width.saturating_sub(overhead);
1674     for _ in 0..lhs_offset {
1675         spacing.push(' ');
1676     }
1677     // In this extreme case we will be missing a space between an attribute and a field.
1678     if prefix.is_empty() && !attrs_str.is_empty() && attrs_extendable && spacing.is_empty() {
1679         spacing.push(' ');
1680     }
1681     let orig_ty = shape
1682         .offset_left(overhead + spacing.len())
1683         .and_then(|ty_shape| field.ty.rewrite(context, ty_shape));
1684     if let Some(ref ty) = orig_ty {
1685         if !ty.contains('\n') {
1686             return Some(attr_prefix + &spacing + ty);
1687         }
1688     }
1689
1690     let is_prefix_empty = prefix.is_empty();
1691     // We must use multiline. We are going to put attributes and a field on different lines.
1692     let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, shape)?;
1693     // Remove a leading white-space from `rewrite_assign_rhs()` when rewriting a tuple struct.
1694     let field_str = if is_prefix_empty {
1695         field_str.trim_start()
1696     } else {
1697         &field_str
1698     };
1699     combine_strs_with_missing_comments(context, &attrs_str, field_str, missing_span, shape, false)
1700 }
1701
1702 pub(crate) struct StaticParts<'a> {
1703     prefix: &'a str,
1704     vis: &'a ast::Visibility,
1705     ident: symbol::Ident,
1706     ty: &'a ast::Ty,
1707     mutability: ast::Mutability,
1708     expr_opt: Option<&'a ptr::P<ast::Expr>>,
1709     defaultness: Option<ast::Defaultness>,
1710     span: Span,
1711 }
1712
1713 impl<'a> StaticParts<'a> {
1714     pub(crate) fn from_item(item: &'a ast::Item) -> Self {
1715         let (defaultness, prefix, ty, mutability, expr) = match item.kind {
1716             ast::ItemKind::Static(ref ty, mutability, ref expr) => {
1717                 (None, "static", ty, mutability, expr)
1718             }
1719             ast::ItemKind::Const(defaultness, ref ty, ref expr) => {
1720                 (Some(defaultness), "const", ty, ast::Mutability::Not, expr)
1721             }
1722             _ => unreachable!(),
1723         };
1724         StaticParts {
1725             prefix,
1726             vis: &item.vis,
1727             ident: item.ident,
1728             ty,
1729             mutability,
1730             expr_opt: expr.as_ref(),
1731             defaultness,
1732             span: item.span,
1733         }
1734     }
1735
1736     pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self {
1737         let (defaultness, ty, expr_opt) = match ti.kind {
1738             ast::AssocItemKind::Const(defaultness, ref ty, ref expr_opt) => {
1739                 (defaultness, ty, expr_opt)
1740             }
1741             _ => unreachable!(),
1742         };
1743         StaticParts {
1744             prefix: "const",
1745             vis: &DEFAULT_VISIBILITY,
1746             ident: ti.ident,
1747             ty,
1748             mutability: ast::Mutability::Not,
1749             expr_opt: expr_opt.as_ref(),
1750             defaultness: Some(defaultness),
1751             span: ti.span,
1752         }
1753     }
1754
1755     pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self {
1756         let (defaultness, ty, expr) = match ii.kind {
1757             ast::AssocItemKind::Const(defaultness, ref ty, ref expr) => (defaultness, ty, expr),
1758             _ => unreachable!(),
1759         };
1760         StaticParts {
1761             prefix: "const",
1762             vis: &ii.vis,
1763             ident: ii.ident,
1764             ty,
1765             mutability: ast::Mutability::Not,
1766             expr_opt: expr.as_ref(),
1767             defaultness: Some(defaultness),
1768             span: ii.span,
1769         }
1770     }
1771 }
1772
1773 fn rewrite_static(
1774     context: &RewriteContext<'_>,
1775     static_parts: &StaticParts<'_>,
1776     offset: Indent,
1777 ) -> Option<String> {
1778     let colon = colon_spaces(context.config);
1779     let mut prefix = format!(
1780         "{}{}{} {}{}{}",
1781         format_visibility(context, static_parts.vis),
1782         static_parts.defaultness.map_or("", format_defaultness),
1783         static_parts.prefix,
1784         format_mutability(static_parts.mutability),
1785         rewrite_ident(context, static_parts.ident),
1786         colon,
1787     );
1788     // 2 = " =".len()
1789     let ty_shape =
1790         Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2)?;
1791     let ty_str = match static_parts.ty.rewrite(context, ty_shape) {
1792         Some(ty_str) => ty_str,
1793         None => {
1794             if prefix.ends_with(' ') {
1795                 prefix.pop();
1796             }
1797             let nested_indent = offset.block_indent(context.config);
1798             let nested_shape = Shape::indented(nested_indent, context.config);
1799             let ty_str = static_parts.ty.rewrite(context, nested_shape)?;
1800             format!(
1801                 "{}{}",
1802                 nested_indent.to_string_with_newline(context.config),
1803                 ty_str
1804             )
1805         }
1806     };
1807
1808     if let Some(expr) = static_parts.expr_opt {
1809         let lhs = format!("{}{} =", prefix, ty_str);
1810         // 1 = ;
1811         let remaining_width = context.budget(offset.block_indent + 1);
1812         rewrite_assign_rhs(
1813             context,
1814             lhs,
1815             &**expr,
1816             Shape::legacy(remaining_width, offset.block_only()),
1817         )
1818         .and_then(|res| recover_comment_removed(res, static_parts.span, context))
1819         .map(|s| if s.ends_with(';') { s } else { s + ";" })
1820     } else {
1821         Some(format!("{}{};", prefix, ty_str))
1822     }
1823 }
1824
1825 pub(crate) fn rewrite_associated_type(
1826     ident: symbol::Ident,
1827     ty_opt: Option<&ptr::P<ast::Ty>>,
1828     generics: &ast::Generics,
1829     generic_bounds_opt: Option<&ast::GenericBounds>,
1830     context: &RewriteContext<'_>,
1831     indent: Indent,
1832 ) -> Option<String> {
1833     let ident_str = rewrite_ident(context, ident);
1834     // 5 = "type "
1835     let generics_shape = Shape::indented(indent, context.config).offset_left(5)?;
1836     let generics_str = rewrite_generics(context, ident_str, generics, generics_shape)?;
1837     let prefix = format!("type {}", generics_str);
1838
1839     let type_bounds_str = if let Some(bounds) = generic_bounds_opt {
1840         if bounds.is_empty() {
1841             String::new()
1842         } else {
1843             // 2 = ": ".len()
1844             let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?;
1845             bounds.rewrite(context, shape).map(|s| format!(": {}", s))?
1846         }
1847     } else {
1848         String::new()
1849     };
1850
1851     if let Some(ty) = ty_opt {
1852         // 1 = `;`
1853         let shape = Shape::indented(indent, context.config).sub_width(1)?;
1854         let lhs = format!("{}{} =", prefix, type_bounds_str);
1855         rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";")
1856     } else {
1857         Some(format!("{}{};", prefix, type_bounds_str))
1858     }
1859 }
1860
1861 struct OpaqueType<'a> {
1862     bounds: &'a ast::GenericBounds,
1863 }
1864
1865 impl<'a> Rewrite for OpaqueType<'a> {
1866     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
1867         let shape = shape.offset_left(5)?; // `impl `
1868         self.bounds
1869             .rewrite(context, shape)
1870             .map(|s| format!("impl {}", s))
1871     }
1872 }
1873
1874 pub(crate) fn rewrite_opaque_impl_type(
1875     context: &RewriteContext<'_>,
1876     ident: symbol::Ident,
1877     generics: &ast::Generics,
1878     generic_bounds: &ast::GenericBounds,
1879     indent: Indent,
1880 ) -> Option<String> {
1881     let ident_str = rewrite_ident(context, ident);
1882     // 5 = "type "
1883     let generics_shape = Shape::indented(indent, context.config).offset_left(5)?;
1884     let generics_str = rewrite_generics(context, ident_str, generics, generics_shape)?;
1885     let prefix = format!("type {} =", generics_str);
1886     let rhs = OpaqueType {
1887         bounds: generic_bounds,
1888     };
1889
1890     rewrite_assign_rhs(
1891         context,
1892         &prefix,
1893         &rhs,
1894         Shape::indented(indent, context.config).sub_width(1)?,
1895     )
1896     .map(|s| s + ";")
1897 }
1898
1899 pub(crate) fn rewrite_associated_impl_type(
1900     ident: symbol::Ident,
1901     defaultness: ast::Defaultness,
1902     ty_opt: Option<&ptr::P<ast::Ty>>,
1903     generics: &ast::Generics,
1904     context: &RewriteContext<'_>,
1905     indent: Indent,
1906 ) -> Option<String> {
1907     let result = rewrite_associated_type(ident, ty_opt, generics, None, context, indent)?;
1908
1909     match defaultness {
1910         ast::Defaultness::Default(..) => Some(format!("default {}", result)),
1911         _ => Some(result),
1912     }
1913 }
1914
1915 impl Rewrite for ast::FnRetTy {
1916     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
1917         match *self {
1918             ast::FnRetTy::Default(_) => Some(String::new()),
1919             ast::FnRetTy::Ty(ref ty) => {
1920                 if context.config.version() == Version::One
1921                     || context.config.indent_style() == IndentStyle::Visual
1922                 {
1923                     let inner_width = shape.width.checked_sub(3)?;
1924                     return ty
1925                         .rewrite(context, Shape::legacy(inner_width, shape.indent + 3))
1926                         .map(|r| format!("-> {}", r));
1927                 }
1928
1929                 ty.rewrite(context, shape.offset_left(3)?)
1930                     .map(|s| format!("-> {}", s))
1931             }
1932         }
1933     }
1934 }
1935
1936 fn is_empty_infer(ty: &ast::Ty, pat_span: Span) -> bool {
1937     match ty.kind {
1938         ast::TyKind::Infer => ty.span.hi() == pat_span.hi(),
1939         _ => false,
1940     }
1941 }
1942
1943 /// Recover any missing comments between the param and the type.
1944 ///
1945 /// # Returns
1946 ///
1947 /// A 2-len tuple with the comment before the colon in first position, and the comment after the
1948 /// colon in second position.
1949 fn get_missing_param_comments(
1950     context: &RewriteContext<'_>,
1951     pat_span: Span,
1952     ty_span: Span,
1953     shape: Shape,
1954 ) -> (String, String) {
1955     let missing_comment_span = mk_sp(pat_span.hi(), ty_span.lo());
1956
1957     let span_before_colon = {
1958         let missing_comment_span_hi = context
1959             .snippet_provider
1960             .span_before(missing_comment_span, ":");
1961         mk_sp(pat_span.hi(), missing_comment_span_hi)
1962     };
1963     let span_after_colon = {
1964         let missing_comment_span_lo = context
1965             .snippet_provider
1966             .span_after(missing_comment_span, ":");
1967         mk_sp(missing_comment_span_lo, ty_span.lo())
1968     };
1969
1970     let comment_before_colon = rewrite_missing_comment(span_before_colon, shape, context)
1971         .filter(|comment| !comment.is_empty())
1972         .map_or(String::new(), |comment| format!(" {}", comment));
1973     let comment_after_colon = rewrite_missing_comment(span_after_colon, shape, context)
1974         .filter(|comment| !comment.is_empty())
1975         .map_or(String::new(), |comment| format!("{} ", comment));
1976     (comment_before_colon, comment_after_colon)
1977 }
1978
1979 impl Rewrite for ast::Param {
1980     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
1981         let param_attrs_result = self
1982             .attrs
1983             .rewrite(context, Shape::legacy(shape.width, shape.indent))?;
1984         let (span, has_multiple_attr_lines) = if !self.attrs.is_empty() {
1985             let num_attrs = self.attrs.len();
1986             (
1987                 mk_sp(self.attrs[num_attrs - 1].span.hi(), self.pat.span.lo()),
1988                 param_attrs_result.contains("\n"),
1989             )
1990         } else {
1991             (mk_sp(self.span.lo(), self.span.lo()), false)
1992         };
1993
1994         if let Some(ref explicit_self) = self.to_self() {
1995             rewrite_explicit_self(
1996                 context,
1997                 explicit_self,
1998                 &param_attrs_result,
1999                 span,
2000                 shape,
2001                 has_multiple_attr_lines,
2002             )
2003         } else if is_named_param(self) {
2004             let mut result = combine_strs_with_missing_comments(
2005                 context,
2006                 &param_attrs_result,
2007                 &self
2008                     .pat
2009                     .rewrite(context, Shape::legacy(shape.width, shape.indent))?,
2010                 span,
2011                 shape,
2012                 !has_multiple_attr_lines,
2013             )?;
2014
2015             if !is_empty_infer(&*self.ty, self.pat.span) {
2016                 let (before_comment, after_comment) =
2017                     get_missing_param_comments(context, self.pat.span, self.ty.span, shape);
2018                 result.push_str(&before_comment);
2019                 result.push_str(colon_spaces(context.config));
2020                 result.push_str(&after_comment);
2021                 let overhead = last_line_width(&result);
2022                 let max_width = shape.width.checked_sub(overhead)?;
2023                 let ty_str = self
2024                     .ty
2025                     .rewrite(context, Shape::legacy(max_width, shape.indent))?;
2026                 result.push_str(&ty_str);
2027             }
2028
2029             Some(result)
2030         } else {
2031             self.ty.rewrite(context, shape)
2032         }
2033     }
2034 }
2035
2036 fn rewrite_explicit_self(
2037     context: &RewriteContext<'_>,
2038     explicit_self: &ast::ExplicitSelf,
2039     param_attrs: &str,
2040     span: Span,
2041     shape: Shape,
2042     has_multiple_attr_lines: bool,
2043 ) -> Option<String> {
2044     match explicit_self.node {
2045         ast::SelfKind::Region(lt, m) => {
2046             let mut_str = format_mutability(m);
2047             match lt {
2048                 Some(ref l) => {
2049                     let lifetime_str = l.rewrite(
2050                         context,
2051                         Shape::legacy(context.config.max_width(), Indent::empty()),
2052                     )?;
2053                     Some(combine_strs_with_missing_comments(
2054                         context,
2055                         &param_attrs,
2056                         &format!("&{} {}self", lifetime_str, mut_str),
2057                         span,
2058                         shape,
2059                         !has_multiple_attr_lines,
2060                     )?)
2061                 }
2062                 None => Some(combine_strs_with_missing_comments(
2063                     context,
2064                     &param_attrs,
2065                     &format!("&{}self", mut_str),
2066                     span,
2067                     shape,
2068                     !has_multiple_attr_lines,
2069                 )?),
2070             }
2071         }
2072         ast::SelfKind::Explicit(ref ty, mutability) => {
2073             let type_str = ty.rewrite(
2074                 context,
2075                 Shape::legacy(context.config.max_width(), Indent::empty()),
2076             )?;
2077
2078             Some(combine_strs_with_missing_comments(
2079                 context,
2080                 &param_attrs,
2081                 &format!("{}self: {}", format_mutability(mutability), type_str),
2082                 span,
2083                 shape,
2084                 !has_multiple_attr_lines,
2085             )?)
2086         }
2087         ast::SelfKind::Value(mutability) => Some(combine_strs_with_missing_comments(
2088             context,
2089             &param_attrs,
2090             &format!("{}self", format_mutability(mutability)),
2091             span,
2092             shape,
2093             !has_multiple_attr_lines,
2094         )?),
2095     }
2096 }
2097
2098 pub(crate) fn span_lo_for_param(param: &ast::Param) -> BytePos {
2099     if param.attrs.is_empty() {
2100         if is_named_param(param) {
2101             param.pat.span.lo()
2102         } else {
2103             param.ty.span.lo()
2104         }
2105     } else {
2106         param.attrs[0].span.lo()
2107     }
2108 }
2109
2110 pub(crate) fn span_hi_for_param(context: &RewriteContext<'_>, param: &ast::Param) -> BytePos {
2111     match param.ty.kind {
2112         ast::TyKind::Infer if context.snippet(param.ty.span) == "_" => param.ty.span.hi(),
2113         ast::TyKind::Infer if is_named_param(param) => param.pat.span.hi(),
2114         _ => param.ty.span.hi(),
2115     }
2116 }
2117
2118 pub(crate) fn is_named_param(param: &ast::Param) -> bool {
2119     if let ast::PatKind::Ident(_, ident, _) = param.pat.kind {
2120         ident.name != symbol::kw::Invalid
2121     } else {
2122         true
2123     }
2124 }
2125
2126 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
2127 pub(crate) enum FnBraceStyle {
2128     SameLine,
2129     NextLine,
2130     None,
2131 }
2132
2133 // Return type is (result, force_new_line_for_brace)
2134 fn rewrite_fn_base(
2135     context: &RewriteContext<'_>,
2136     indent: Indent,
2137     ident: symbol::Ident,
2138     fn_sig: &FnSig<'_>,
2139     span: Span,
2140     fn_brace_style: FnBraceStyle,
2141 ) -> Option<(String, bool)> {
2142     let mut force_new_line_for_brace = false;
2143
2144     let where_clause = &fn_sig.generics.where_clause;
2145
2146     let mut result = String::with_capacity(1024);
2147     result.push_str(&fn_sig.to_str(context));
2148
2149     // fn foo
2150     result.push_str("fn ");
2151
2152     // Generics.
2153     let overhead = if let FnBraceStyle::SameLine = fn_brace_style {
2154         // 4 = `() {`
2155         4
2156     } else {
2157         // 2 = `()`
2158         2
2159     };
2160     let used_width = last_line_used_width(&result, indent.width());
2161     let one_line_budget = context.budget(used_width + overhead);
2162     let shape = Shape {
2163         width: one_line_budget,
2164         indent,
2165         offset: used_width,
2166     };
2167     let fd = fn_sig.decl;
2168     let generics_str = rewrite_generics(
2169         context,
2170         rewrite_ident(context, ident),
2171         fn_sig.generics,
2172         shape,
2173     )?;
2174     result.push_str(&generics_str);
2175
2176     let snuggle_angle_bracket = generics_str
2177         .lines()
2178         .last()
2179         .map_or(false, |l| l.trim_start().len() == 1);
2180
2181     // Note that the width and indent don't really matter, we'll re-layout the
2182     // return type later anyway.
2183     let ret_str = fd
2184         .output
2185         .rewrite(context, Shape::indented(indent, context.config))?;
2186
2187     let multi_line_ret_str = ret_str.contains('\n');
2188     let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() };
2189
2190     // Params.
2191     let (one_line_budget, multi_line_budget, mut param_indent) = compute_budgets_for_params(
2192         context,
2193         &result,
2194         indent,
2195         ret_str_len,
2196         fn_brace_style,
2197         multi_line_ret_str,
2198     )?;
2199
2200     debug!(
2201         "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, param_indent: {:?}",
2202         one_line_budget, multi_line_budget, param_indent
2203     );
2204
2205     result.push('(');
2206     // Check if vertical layout was forced.
2207     if one_line_budget == 0
2208         && !snuggle_angle_bracket
2209         && context.config.indent_style() == IndentStyle::Visual
2210     {
2211         result.push_str(&param_indent.to_string_with_newline(context.config));
2212     }
2213
2214     // Skip `pub(crate)`.
2215     let lo_after_visibility = get_bytepos_after_visibility(&fn_sig.visibility, span);
2216     // A conservative estimation, to goal is to be over all parens in generics
2217     let params_start = fn_sig
2218         .generics
2219         .params
2220         .iter()
2221         .last()
2222         .map_or(lo_after_visibility, |param| param.span().hi());
2223     let params_end = if fd.inputs.is_empty() {
2224         context
2225             .snippet_provider
2226             .span_after(mk_sp(params_start, span.hi()), ")")
2227     } else {
2228         let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi(), span.hi());
2229         context.snippet_provider.span_after(last_span, ")")
2230     };
2231     let params_span = mk_sp(
2232         context
2233             .snippet_provider
2234             .span_after(mk_sp(params_start, span.hi()), "("),
2235         params_end,
2236     );
2237     let param_str = rewrite_params(
2238         context,
2239         &fd.inputs,
2240         one_line_budget,
2241         multi_line_budget,
2242         indent,
2243         param_indent,
2244         params_span,
2245         fd.c_variadic(),
2246     )?;
2247
2248     let put_params_in_block = match context.config.indent_style() {
2249         IndentStyle::Block => param_str.contains('\n') || param_str.len() > one_line_budget,
2250         _ => false,
2251     } && !fd.inputs.is_empty();
2252
2253     let mut params_last_line_contains_comment = false;
2254     let mut no_params_and_over_max_width = false;
2255
2256     if put_params_in_block {
2257         param_indent = indent.block_indent(context.config);
2258         result.push_str(&param_indent.to_string_with_newline(context.config));
2259         result.push_str(&param_str);
2260         result.push_str(&indent.to_string_with_newline(context.config));
2261         result.push(')');
2262     } else {
2263         result.push_str(&param_str);
2264         let used_width = last_line_used_width(&result, indent.width()) + first_line_width(&ret_str);
2265         // Put the closing brace on the next line if it overflows the max width.
2266         // 1 = `)`
2267         let closing_paren_overflow_max_width =
2268             fd.inputs.is_empty() && used_width + 1 > context.config.max_width();
2269         // If the last line of params contains comment, we cannot put the closing paren
2270         // on the same line.
2271         params_last_line_contains_comment = param_str
2272             .lines()
2273             .last()
2274             .map_or(false, |last_line| last_line.contains("//"));
2275
2276         if context.config.version() == Version::Two {
2277             if closing_paren_overflow_max_width {
2278                 result.push(')');
2279                 result.push_str(&indent.to_string_with_newline(context.config));
2280                 no_params_and_over_max_width = true;
2281             } else if params_last_line_contains_comment {
2282                 result.push_str(&indent.to_string_with_newline(context.config));
2283                 result.push(')');
2284                 no_params_and_over_max_width = true;
2285             } else {
2286                 result.push(')');
2287             }
2288         } else {
2289             if closing_paren_overflow_max_width || params_last_line_contains_comment {
2290                 result.push_str(&indent.to_string_with_newline(context.config));
2291             }
2292             result.push(')');
2293         }
2294     }
2295
2296     // Return type.
2297     if let ast::FnRetTy::Ty(..) = fd.output {
2298         let ret_should_indent = match context.config.indent_style() {
2299             // If our params are block layout then we surely must have space.
2300             IndentStyle::Block if put_params_in_block || fd.inputs.is_empty() => false,
2301             _ if params_last_line_contains_comment => false,
2302             _ if result.contains('\n') || multi_line_ret_str => true,
2303             _ => {
2304                 // If the return type would push over the max width, then put the return type on
2305                 // a new line. With the +1 for the signature length an additional space between
2306                 // the closing parenthesis of the param and the arrow '->' is considered.
2307                 let mut sig_length = result.len() + indent.width() + ret_str_len + 1;
2308
2309                 // If there is no where-clause, take into account the space after the return type
2310                 // and the brace.
2311                 if where_clause.predicates.is_empty() {
2312                     sig_length += 2;
2313                 }
2314
2315                 sig_length > context.config.max_width()
2316             }
2317         };
2318         let ret_shape = if ret_should_indent {
2319             if context.config.version() == Version::One
2320                 || context.config.indent_style() == IndentStyle::Visual
2321             {
2322                 let indent = if param_str.is_empty() {
2323                     // Aligning with non-existent params looks silly.
2324                     force_new_line_for_brace = true;
2325                     indent + 4
2326                 } else {
2327                     // FIXME: we might want to check that using the param indent
2328                     // doesn't blow our budget, and if it does, then fallback to
2329                     // the where-clause indent.
2330                     param_indent
2331                 };
2332
2333                 result.push_str(&indent.to_string_with_newline(context.config));
2334                 Shape::indented(indent, context.config)
2335             } else {
2336                 let mut ret_shape = Shape::indented(indent, context.config);
2337                 if param_str.is_empty() {
2338                     // Aligning with non-existent params looks silly.
2339                     force_new_line_for_brace = true;
2340                     ret_shape = if context.use_block_indent() {
2341                         ret_shape.offset_left(4).unwrap_or(ret_shape)
2342                     } else {
2343                         ret_shape.indent = ret_shape.indent + 4;
2344                         ret_shape
2345                     };
2346                 }
2347
2348                 result.push_str(&ret_shape.indent.to_string_with_newline(context.config));
2349                 ret_shape
2350             }
2351         } else {
2352             if context.config.version() == Version::Two {
2353                 if !param_str.is_empty() || !no_params_and_over_max_width {
2354                     result.push(' ');
2355                 }
2356             } else {
2357                 result.push(' ');
2358             }
2359
2360             let ret_shape = Shape::indented(indent, context.config);
2361             ret_shape
2362                 .offset_left(last_line_width(&result))
2363                 .unwrap_or(ret_shape)
2364         };
2365
2366         if multi_line_ret_str || ret_should_indent {
2367             // Now that we know the proper indent and width, we need to
2368             // re-layout the return type.
2369             let ret_str = fd.output.rewrite(context, ret_shape)?;
2370             result.push_str(&ret_str);
2371         } else {
2372             result.push_str(&ret_str);
2373         }
2374
2375         // Comment between return type and the end of the decl.
2376         let snippet_lo = fd.output.span().hi();
2377         if where_clause.predicates.is_empty() {
2378             let snippet_hi = span.hi();
2379             let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi));
2380             // Try to preserve the layout of the original snippet.
2381             let original_starts_with_newline = snippet
2382                 .find(|c| c != ' ')
2383                 .map_or(false, |i| starts_with_newline(&snippet[i..]));
2384             let original_ends_with_newline = snippet
2385                 .rfind(|c| c != ' ')
2386                 .map_or(false, |i| snippet[i..].ends_with('\n'));
2387             let snippet = snippet.trim();
2388             if !snippet.is_empty() {
2389                 result.push(if original_starts_with_newline {
2390                     '\n'
2391                 } else {
2392                     ' '
2393                 });
2394                 result.push_str(snippet);
2395                 if original_ends_with_newline {
2396                     force_new_line_for_brace = true;
2397                 }
2398             }
2399         }
2400     }
2401
2402     let pos_before_where = match fd.output {
2403         ast::FnRetTy::Default(..) => params_span.hi(),
2404         ast::FnRetTy::Ty(ref ty) => ty.span.hi(),
2405     };
2406
2407     let is_params_multi_lined = param_str.contains('\n');
2408
2409     let space = if put_params_in_block && ret_str.is_empty() {
2410         WhereClauseSpace::Space
2411     } else {
2412         WhereClauseSpace::Newline
2413     };
2414     let mut option = WhereClauseOption::new(fn_brace_style == FnBraceStyle::None, space);
2415     if is_params_multi_lined {
2416         option.veto_single_line();
2417     }
2418     let where_clause_str = rewrite_where_clause(
2419         context,
2420         where_clause,
2421         context.config.brace_style(),
2422         Shape::indented(indent, context.config),
2423         true,
2424         "{",
2425         Some(span.hi()),
2426         pos_before_where,
2427         option,
2428     )?;
2429     // If there are neither where-clause nor return type, we may be missing comments between
2430     // params and `{`.
2431     if where_clause_str.is_empty() {
2432         if let ast::FnRetTy::Default(ret_span) = fd.output {
2433             match recover_missing_comment_in_span(
2434                 mk_sp(params_span.hi(), ret_span.hi()),
2435                 shape,
2436                 context,
2437                 last_line_width(&result),
2438             ) {
2439                 Some(ref missing_comment) if !missing_comment.is_empty() => {
2440                     result.push_str(missing_comment);
2441                     force_new_line_for_brace = true;
2442                 }
2443                 _ => (),
2444             }
2445         }
2446     }
2447
2448     result.push_str(&where_clause_str);
2449
2450     force_new_line_for_brace |= last_line_contains_single_line_comment(&result);
2451     force_new_line_for_brace |= is_params_multi_lined && context.config.where_single_line();
2452     Some((result, force_new_line_for_brace))
2453 }
2454
2455 /// Kind of spaces to put before `where`.
2456 #[derive(Copy, Clone)]
2457 enum WhereClauseSpace {
2458     /// A single space.
2459     Space,
2460     /// A new line.
2461     Newline,
2462     /// Nothing.
2463     None,
2464 }
2465
2466 #[derive(Copy, Clone)]
2467 struct WhereClauseOption {
2468     suppress_comma: bool, // Force no trailing comma
2469     snuggle: WhereClauseSpace,
2470     allow_single_line: bool, // Try single line where-clause instead of vertical layout
2471     veto_single_line: bool,  // Disallow a single-line where-clause.
2472 }
2473
2474 impl WhereClauseOption {
2475     fn new(suppress_comma: bool, snuggle: WhereClauseSpace) -> WhereClauseOption {
2476         WhereClauseOption {
2477             suppress_comma,
2478             snuggle,
2479             allow_single_line: false,
2480             veto_single_line: false,
2481         }
2482     }
2483
2484     fn snuggled(current: &str) -> WhereClauseOption {
2485         WhereClauseOption {
2486             suppress_comma: false,
2487             snuggle: if last_line_width(current) == 1 {
2488                 WhereClauseSpace::Space
2489             } else {
2490                 WhereClauseSpace::Newline
2491             },
2492             allow_single_line: false,
2493             veto_single_line: false,
2494         }
2495     }
2496
2497     fn suppress_comma(&mut self) {
2498         self.suppress_comma = true
2499     }
2500
2501     fn allow_single_line(&mut self) {
2502         self.allow_single_line = true
2503     }
2504
2505     fn snuggle(&mut self) {
2506         self.snuggle = WhereClauseSpace::Space
2507     }
2508
2509     fn veto_single_line(&mut self) {
2510         self.veto_single_line = true;
2511     }
2512 }
2513
2514 fn rewrite_params(
2515     context: &RewriteContext<'_>,
2516     params: &[ast::Param],
2517     one_line_budget: usize,
2518     multi_line_budget: usize,
2519     indent: Indent,
2520     param_indent: Indent,
2521     span: Span,
2522     variadic: bool,
2523 ) -> Option<String> {
2524     if params.is_empty() {
2525         let comment = context
2526             .snippet(mk_sp(
2527                 span.lo(),
2528                 // to remove ')'
2529                 span.hi() - BytePos(1),
2530             ))
2531             .trim();
2532         return Some(comment.to_owned());
2533     }
2534     let param_items: Vec<_> = itemize_list(
2535         context.snippet_provider,
2536         params.iter(),
2537         ")",
2538         ",",
2539         |param| span_lo_for_param(param),
2540         |param| param.ty.span.hi(),
2541         |param| {
2542             param
2543                 .rewrite(context, Shape::legacy(multi_line_budget, param_indent))
2544                 .or_else(|| Some(context.snippet(param.span()).to_owned()))
2545         },
2546         span.lo(),
2547         span.hi(),
2548         false,
2549     )
2550     .collect();
2551
2552     let tactic = definitive_tactic(
2553         &param_items,
2554         context
2555             .config
2556             .fn_args_layout()
2557             .to_list_tactic(param_items.len()),
2558         Separator::Comma,
2559         one_line_budget,
2560     );
2561     let budget = match tactic {
2562         DefinitiveListTactic::Horizontal => one_line_budget,
2563         _ => multi_line_budget,
2564     };
2565     let indent = match context.config.indent_style() {
2566         IndentStyle::Block => indent.block_indent(context.config),
2567         IndentStyle::Visual => param_indent,
2568     };
2569     let trailing_separator = if variadic {
2570         SeparatorTactic::Never
2571     } else {
2572         match context.config.indent_style() {
2573             IndentStyle::Block => context.config.trailing_comma(),
2574             IndentStyle::Visual => SeparatorTactic::Never,
2575         }
2576     };
2577     let fmt = ListFormatting::new(Shape::legacy(budget, indent), context.config)
2578         .tactic(tactic)
2579         .trailing_separator(trailing_separator)
2580         .ends_with_newline(tactic.ends_with_newline(context.config.indent_style()))
2581         .preserve_newline(true);
2582     write_list(&param_items, &fmt)
2583 }
2584
2585 fn compute_budgets_for_params(
2586     context: &RewriteContext<'_>,
2587     result: &str,
2588     indent: Indent,
2589     ret_str_len: usize,
2590     fn_brace_style: FnBraceStyle,
2591     force_vertical_layout: bool,
2592 ) -> Option<(usize, usize, Indent)> {
2593     debug!(
2594         "compute_budgets_for_params {} {:?}, {}, {:?}",
2595         result.len(),
2596         indent,
2597         ret_str_len,
2598         fn_brace_style,
2599     );
2600     // Try keeping everything on the same line.
2601     if !result.contains('\n') && !force_vertical_layout {
2602         // 2 = `()`, 3 = `() `, space is before ret_string.
2603         let overhead = if ret_str_len == 0 { 2 } else { 3 };
2604         let mut used_space = indent.width() + result.len() + ret_str_len + overhead;
2605         match fn_brace_style {
2606             FnBraceStyle::None => used_space += 1,     // 1 = `;`
2607             FnBraceStyle::SameLine => used_space += 2, // 2 = `{}`
2608             FnBraceStyle::NextLine => (),
2609         }
2610         let one_line_budget = context.budget(used_space);
2611
2612         if one_line_budget > 0 {
2613             // 4 = "() {".len()
2614             let (indent, multi_line_budget) = match context.config.indent_style() {
2615                 IndentStyle::Block => {
2616                     let indent = indent.block_indent(context.config);
2617                     (indent, context.budget(indent.width() + 1))
2618                 }
2619                 IndentStyle::Visual => {
2620                     let indent = indent + result.len() + 1;
2621                     let multi_line_overhead = match fn_brace_style {
2622                         FnBraceStyle::SameLine => 4,
2623                         _ => 2,
2624                     } + indent.width();
2625                     (indent, context.budget(multi_line_overhead))
2626                 }
2627             };
2628
2629             return Some((one_line_budget, multi_line_budget, indent));
2630         }
2631     }
2632
2633     // Didn't work. we must force vertical layout and put params on a newline.
2634     let new_indent = indent.block_indent(context.config);
2635     let used_space = match context.config.indent_style() {
2636         // 1 = `,`
2637         IndentStyle::Block => new_indent.width() + 1,
2638         // Account for `)` and possibly ` {`.
2639         IndentStyle::Visual => new_indent.width() + if ret_str_len == 0 { 1 } else { 3 },
2640     };
2641     Some((0, context.budget(used_space), new_indent))
2642 }
2643
2644 fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> FnBraceStyle {
2645     let predicate_count = where_clause.predicates.len();
2646
2647     if config.where_single_line() && predicate_count == 1 {
2648         return FnBraceStyle::SameLine;
2649     }
2650     let brace_style = config.brace_style();
2651
2652     let use_next_line = brace_style == BraceStyle::AlwaysNextLine
2653         || (brace_style == BraceStyle::SameLineWhere && predicate_count > 0);
2654     if use_next_line {
2655         FnBraceStyle::NextLine
2656     } else {
2657         FnBraceStyle::SameLine
2658     }
2659 }
2660
2661 fn rewrite_generics(
2662     context: &RewriteContext<'_>,
2663     ident: &str,
2664     generics: &ast::Generics,
2665     shape: Shape,
2666 ) -> Option<String> {
2667     // FIXME: convert bounds to where-clauses where they get too big or if
2668     // there is a where-clause at all.
2669
2670     if generics.params.is_empty() {
2671         return Some(ident.to_owned());
2672     }
2673
2674     let params = generics.params.iter();
2675     overflow::rewrite_with_angle_brackets(context, ident, params, shape, generics.span)
2676 }
2677
2678 fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option<Shape> {
2679     match config.indent_style() {
2680         IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width(offset + 2),
2681         IndentStyle::Block => {
2682             // 1 = ","
2683             shape
2684                 .block()
2685                 .block_indent(config.tab_spaces())
2686                 .with_max_width(config)
2687                 .sub_width(1)
2688         }
2689     }
2690 }
2691
2692 fn rewrite_where_clause_rfc_style(
2693     context: &RewriteContext<'_>,
2694     where_clause: &ast::WhereClause,
2695     shape: Shape,
2696     terminator: &str,
2697     span_end: Option<BytePos>,
2698     span_end_before_where: BytePos,
2699     where_clause_option: WhereClauseOption,
2700 ) -> Option<String> {
2701     let (where_keyword, allow_single_line) = rewrite_where_keyword(
2702         context,
2703         where_clause,
2704         shape,
2705         span_end_before_where,
2706         where_clause_option,
2707     )?;
2708
2709     // 1 = `,`
2710     let clause_shape = shape
2711         .block()
2712         .with_max_width(context.config)
2713         .block_left(context.config.tab_spaces())?
2714         .sub_width(1)?;
2715     let force_single_line = context.config.where_single_line()
2716         && where_clause.predicates.len() == 1
2717         && !where_clause_option.veto_single_line;
2718
2719     let preds_str = rewrite_bounds_on_where_clause(
2720         context,
2721         where_clause,
2722         clause_shape,
2723         terminator,
2724         span_end,
2725         where_clause_option,
2726         force_single_line,
2727     )?;
2728
2729     // 6 = `where `
2730     let clause_sep =
2731         if allow_single_line && !preds_str.contains('\n') && 6 + preds_str.len() <= shape.width
2732             || force_single_line
2733         {
2734             Cow::from(" ")
2735         } else {
2736             clause_shape.indent.to_string_with_newline(context.config)
2737         };
2738
2739     Some(format!("{}{}{}", where_keyword, clause_sep, preds_str))
2740 }
2741
2742 /// Rewrite `where` and comment around it.
2743 fn rewrite_where_keyword(
2744     context: &RewriteContext<'_>,
2745     where_clause: &ast::WhereClause,
2746     shape: Shape,
2747     span_end_before_where: BytePos,
2748     where_clause_option: WhereClauseOption,
2749 ) -> Option<(String, bool)> {
2750     let block_shape = shape.block().with_max_width(context.config);
2751     // 1 = `,`
2752     let clause_shape = block_shape
2753         .block_left(context.config.tab_spaces())?
2754         .sub_width(1)?;
2755
2756     let comment_separator = |comment: &str, shape: Shape| {
2757         if comment.is_empty() {
2758             Cow::from("")
2759         } else {
2760             shape.indent.to_string_with_newline(context.config)
2761         }
2762     };
2763
2764     let (span_before, span_after) =
2765         missing_span_before_after_where(span_end_before_where, where_clause);
2766     let (comment_before, comment_after) =
2767         rewrite_comments_before_after_where(context, span_before, span_after, shape)?;
2768
2769     let starting_newline = match where_clause_option.snuggle {
2770         WhereClauseSpace::Space if comment_before.is_empty() => Cow::from(" "),
2771         WhereClauseSpace::None => Cow::from(""),
2772         _ => block_shape.indent.to_string_with_newline(context.config),
2773     };
2774
2775     let newline_before_where = comment_separator(&comment_before, shape);
2776     let newline_after_where = comment_separator(&comment_after, clause_shape);
2777     let result = format!(
2778         "{}{}{}where{}{}",
2779         starting_newline, comment_before, newline_before_where, newline_after_where, comment_after
2780     );
2781     let allow_single_line = where_clause_option.allow_single_line
2782         && comment_before.is_empty()
2783         && comment_after.is_empty();
2784
2785     Some((result, allow_single_line))
2786 }
2787
2788 /// Rewrite bounds on a where clause.
2789 fn rewrite_bounds_on_where_clause(
2790     context: &RewriteContext<'_>,
2791     where_clause: &ast::WhereClause,
2792     shape: Shape,
2793     terminator: &str,
2794     span_end: Option<BytePos>,
2795     where_clause_option: WhereClauseOption,
2796     force_single_line: bool,
2797 ) -> Option<String> {
2798     let span_start = where_clause.predicates[0].span().lo();
2799     // If we don't have the start of the next span, then use the end of the
2800     // predicates, but that means we miss comments.
2801     let len = where_clause.predicates.len();
2802     let end_of_preds = where_clause.predicates[len - 1].span().hi();
2803     let span_end = span_end.unwrap_or(end_of_preds);
2804     let items = itemize_list(
2805         context.snippet_provider,
2806         where_clause.predicates.iter(),
2807         terminator,
2808         ",",
2809         |pred| pred.span().lo(),
2810         |pred| pred.span().hi(),
2811         |pred| pred.rewrite(context, shape),
2812         span_start,
2813         span_end,
2814         false,
2815     );
2816     let comma_tactic = if where_clause_option.suppress_comma || force_single_line {
2817         SeparatorTactic::Never
2818     } else {
2819         context.config.trailing_comma()
2820     };
2821
2822     // shape should be vertical only and only if we have `force_single_line` option enabled
2823     // and the number of items of the where-clause is equal to 1
2824     let shape_tactic = if force_single_line {
2825         DefinitiveListTactic::Horizontal
2826     } else {
2827         DefinitiveListTactic::Vertical
2828     };
2829
2830     let fmt = ListFormatting::new(shape, context.config)
2831         .tactic(shape_tactic)
2832         .trailing_separator(comma_tactic)
2833         .preserve_newline(true);
2834     write_list(&items.collect::<Vec<_>>(), &fmt)
2835 }
2836
2837 fn rewrite_where_clause(
2838     context: &RewriteContext<'_>,
2839     where_clause: &ast::WhereClause,
2840     brace_style: BraceStyle,
2841     shape: Shape,
2842     on_new_line: bool,
2843     terminator: &str,
2844     span_end: Option<BytePos>,
2845     span_end_before_where: BytePos,
2846     where_clause_option: WhereClauseOption,
2847 ) -> Option<String> {
2848     if where_clause.predicates.is_empty() {
2849         return Some(String::new());
2850     }
2851
2852     if context.config.indent_style() == IndentStyle::Block {
2853         return rewrite_where_clause_rfc_style(
2854             context,
2855             where_clause,
2856             shape,
2857             terminator,
2858             span_end,
2859             span_end_before_where,
2860             where_clause_option,
2861         );
2862     }
2863
2864     let extra_indent = Indent::new(context.config.tab_spaces(), 0);
2865
2866     let offset = match context.config.indent_style() {
2867         IndentStyle::Block => shape.indent + extra_indent.block_indent(context.config),
2868         // 6 = "where ".len()
2869         IndentStyle::Visual => shape.indent + extra_indent + 6,
2870     };
2871     // FIXME: if indent_style != Visual, then the budgets below might
2872     // be out by a char or two.
2873
2874     let budget = context.config.max_width() - offset.width();
2875     let span_start = where_clause.predicates[0].span().lo();
2876     // If we don't have the start of the next span, then use the end of the
2877     // predicates, but that means we miss comments.
2878     let len = where_clause.predicates.len();
2879     let end_of_preds = where_clause.predicates[len - 1].span().hi();
2880     let span_end = span_end.unwrap_or(end_of_preds);
2881     let items = itemize_list(
2882         context.snippet_provider,
2883         where_clause.predicates.iter(),
2884         terminator,
2885         ",",
2886         |pred| pred.span().lo(),
2887         |pred| pred.span().hi(),
2888         |pred| pred.rewrite(context, Shape::legacy(budget, offset)),
2889         span_start,
2890         span_end,
2891         false,
2892     );
2893     let item_vec = items.collect::<Vec<_>>();
2894     // FIXME: we don't need to collect here
2895     let tactic = definitive_tactic(&item_vec, ListTactic::Vertical, Separator::Comma, budget);
2896
2897     let mut comma_tactic = context.config.trailing_comma();
2898     // Kind of a hack because we don't usually have trailing commas in where-clauses.
2899     if comma_tactic == SeparatorTactic::Vertical || where_clause_option.suppress_comma {
2900         comma_tactic = SeparatorTactic::Never;
2901     }
2902
2903     let fmt = ListFormatting::new(Shape::legacy(budget, offset), context.config)
2904         .tactic(tactic)
2905         .trailing_separator(comma_tactic)
2906         .ends_with_newline(tactic.ends_with_newline(context.config.indent_style()))
2907         .preserve_newline(true);
2908     let preds_str = write_list(&item_vec, &fmt)?;
2909
2910     let end_length = if terminator == "{" {
2911         // If the brace is on the next line we don't need to count it otherwise it needs two
2912         // characters " {"
2913         match brace_style {
2914             BraceStyle::AlwaysNextLine | BraceStyle::SameLineWhere => 0,
2915             BraceStyle::PreferSameLine => 2,
2916         }
2917     } else if terminator == "=" {
2918         2
2919     } else {
2920         terminator.len()
2921     };
2922     if on_new_line
2923         || preds_str.contains('\n')
2924         || shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width
2925     {
2926         Some(format!(
2927             "\n{}where {}",
2928             (shape.indent + extra_indent).to_string(context.config),
2929             preds_str
2930         ))
2931     } else {
2932         Some(format!(" where {}", preds_str))
2933     }
2934 }
2935
2936 fn missing_span_before_after_where(
2937     before_item_span_end: BytePos,
2938     where_clause: &ast::WhereClause,
2939 ) -> (Span, Span) {
2940     let missing_span_before = mk_sp(before_item_span_end, where_clause.span.lo());
2941     // 5 = `where`
2942     let pos_after_where = where_clause.span.lo() + BytePos(5);
2943     let missing_span_after = mk_sp(pos_after_where, where_clause.predicates[0].span().lo());
2944     (missing_span_before, missing_span_after)
2945 }
2946
2947 fn rewrite_comments_before_after_where(
2948     context: &RewriteContext<'_>,
2949     span_before_where: Span,
2950     span_after_where: Span,
2951     shape: Shape,
2952 ) -> Option<(String, String)> {
2953     let before_comment = rewrite_missing_comment(span_before_where, shape, context)?;
2954     let after_comment = rewrite_missing_comment(
2955         span_after_where,
2956         shape.block_indent(context.config.tab_spaces()),
2957         context,
2958     )?;
2959     Some((before_comment, after_comment))
2960 }
2961
2962 fn format_header(
2963     context: &RewriteContext<'_>,
2964     item_name: &str,
2965     ident: symbol::Ident,
2966     vis: &ast::Visibility,
2967 ) -> String {
2968     format!(
2969         "{}{}{}",
2970         format_visibility(context, vis),
2971         item_name,
2972         rewrite_ident(context, ident)
2973     )
2974 }
2975
2976 #[derive(PartialEq, Eq, Clone, Copy)]
2977 enum BracePos {
2978     None,
2979     Auto,
2980     ForceSameLine,
2981 }
2982
2983 fn format_generics(
2984     context: &RewriteContext<'_>,
2985     generics: &ast::Generics,
2986     brace_style: BraceStyle,
2987     brace_pos: BracePos,
2988     offset: Indent,
2989     span: Span,
2990     used_width: usize,
2991 ) -> Option<String> {
2992     let shape = Shape::legacy(context.budget(used_width + offset.width()), offset);
2993     let mut result = rewrite_generics(context, "", generics, shape)?;
2994
2995     // If the generics are not parameterized then generics.span.hi() == 0,
2996     // so we use span.lo(), which is the position after `struct Foo`.
2997     let span_end_before_where = if !generics.params.is_empty() {
2998         generics.span.hi()
2999     } else {
3000         span.lo()
3001     };
3002     let (same_line_brace, missed_comments) = if !generics.where_clause.predicates.is_empty() {
3003         let budget = context.budget(last_line_used_width(&result, offset.width()));
3004         let mut option = WhereClauseOption::snuggled(&result);
3005         if brace_pos == BracePos::None {
3006             option.suppress_comma = true;
3007         }
3008         let where_clause_str = rewrite_where_clause(
3009             context,
3010             &generics.where_clause,
3011             brace_style,
3012             Shape::legacy(budget, offset.block_only()),
3013             true,
3014             "{",
3015             Some(span.hi()),
3016             span_end_before_where,
3017             option,
3018         )?;
3019         result.push_str(&where_clause_str);
3020         (
3021             brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine,
3022             // missed comments are taken care of in #rewrite_where_clause
3023             None,
3024         )
3025     } else {
3026         (
3027             brace_pos == BracePos::ForceSameLine
3028                 || (result.contains('\n') && brace_style == BraceStyle::PreferSameLine
3029                     || brace_style != BraceStyle::AlwaysNextLine)
3030                 || trimmed_last_line_width(&result) == 1,
3031             rewrite_missing_comment(
3032                 mk_sp(
3033                     span_end_before_where,
3034                     if brace_pos == BracePos::None {
3035                         span.hi()
3036                     } else {
3037                         context.snippet_provider.span_before(span, "{")
3038                     },
3039                 ),
3040                 shape,
3041                 context,
3042             ),
3043         )
3044     };
3045     // add missing comments
3046     let missed_line_comments = missed_comments
3047         .filter(|missed_comments| !missed_comments.is_empty())
3048         .map_or(false, |missed_comments| {
3049             let is_block = is_last_comment_block(&missed_comments);
3050             let sep = if is_block { " " } else { "\n" };
3051             result.push_str(sep);
3052             result.push_str(&missed_comments);
3053             !is_block
3054         });
3055     if brace_pos == BracePos::None {
3056         return Some(result);
3057     }
3058     let total_used_width = last_line_used_width(&result, used_width);
3059     let remaining_budget = context.budget(total_used_width);
3060     // If the same line brace if forced, it indicates that we are rewriting an item with empty body,
3061     // and hence we take the closer into account as well for one line budget.
3062     // We assume that the closer has the same length as the opener.
3063     let overhead = if brace_pos == BracePos::ForceSameLine {
3064         // 3 = ` {}`
3065         3
3066     } else {
3067         // 2 = ` {`
3068         2
3069     };
3070     let forbid_same_line_brace = missed_line_comments || overhead > remaining_budget;
3071     if !forbid_same_line_brace && same_line_brace {
3072         result.push(' ');
3073     } else {
3074         result.push('\n');
3075         result.push_str(&offset.block_only().to_string(context.config));
3076     }
3077     result.push('{');
3078
3079     Some(result)
3080 }
3081
3082 impl Rewrite for ast::ForeignItem {
3083     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
3084         let attrs_str = self.attrs.rewrite(context, shape)?;
3085         // Drop semicolon or it will be interpreted as comment.
3086         // FIXME: this may be a faulty span from libsyntax.
3087         let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1));
3088
3089         let item_str = match self.kind {
3090             ast::ForeignItemKind::Fn(_, ref fn_sig, ref generics, _) => rewrite_fn_base(
3091                 context,
3092                 shape.indent,
3093                 self.ident,
3094                 &FnSig::new(&fn_sig.decl, generics, self.vis.clone()),
3095                 span,
3096                 FnBraceStyle::None,
3097             )
3098             .map(|(s, _)| format!("{};", s)),
3099             ast::ForeignItemKind::Static(ref ty, mutability, _) => {
3100                 // FIXME(#21): we're dropping potential comments in between the
3101                 // function kw here.
3102                 let vis = format_visibility(context, &self.vis);
3103                 let mut_str = format_mutability(mutability);
3104                 let prefix = format!(
3105                     "{}static {}{}:",
3106                     vis,
3107                     mut_str,
3108                     rewrite_ident(context, self.ident)
3109                 );
3110                 // 1 = ;
3111                 rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";")
3112             }
3113             ast::ForeignItemKind::TyAlias(..) => {
3114                 let vis = format_visibility(context, &self.vis);
3115                 Some(format!(
3116                     "{}type {};",
3117                     vis,
3118                     rewrite_ident(context, self.ident)
3119                 ))
3120             }
3121             ast::ForeignItemKind::MacCall(ref mac) => {
3122                 rewrite_macro(mac, None, context, shape, MacroPosition::Item)
3123             }
3124         }?;
3125
3126         let missing_span = if self.attrs.is_empty() {
3127             mk_sp(self.span.lo(), self.span.lo())
3128         } else {
3129             mk_sp(self.attrs[self.attrs.len() - 1].span.hi(), self.span.lo())
3130         };
3131         combine_strs_with_missing_comments(
3132             context,
3133             &attrs_str,
3134             &item_str,
3135             missing_span,
3136             shape,
3137             false,
3138         )
3139     }
3140 }
3141
3142 /// Rewrite the attributes of an item.
3143 fn rewrite_attrs(
3144     context: &RewriteContext<'_>,
3145     item: &ast::Item,
3146     item_str: &str,
3147     shape: Shape,
3148 ) -> Option<String> {
3149     let attrs = filter_inline_attrs(&item.attrs, item.span());
3150     let attrs_str = attrs.rewrite(context, shape)?;
3151
3152     let missed_span = if attrs.is_empty() {
3153         mk_sp(item.span.lo(), item.span.lo())
3154     } else {
3155         mk_sp(attrs[attrs.len() - 1].span.hi(), item.span.lo())
3156     };
3157
3158     let allow_extend = if attrs.len() == 1 {
3159         let line_len = attrs_str.len() + 1 + item_str.len();
3160         !attrs.first().unwrap().is_doc_comment()
3161             && context.config.inline_attribute_width() >= line_len
3162     } else {
3163         false
3164     };
3165
3166     combine_strs_with_missing_comments(
3167         context,
3168         &attrs_str,
3169         &item_str,
3170         missed_span,
3171         shape,
3172         allow_extend,
3173     )
3174 }
3175
3176 /// Rewrite an inline mod.
3177 /// The given shape is used to format the mod's attributes.
3178 pub(crate) fn rewrite_mod(
3179     context: &RewriteContext<'_>,
3180     item: &ast::Item,
3181     attrs_shape: Shape,
3182 ) -> Option<String> {
3183     let mut result = String::with_capacity(32);
3184     result.push_str(&*format_visibility(context, &item.vis));
3185     result.push_str("mod ");
3186     result.push_str(rewrite_ident(context, item.ident));
3187     result.push(';');
3188     rewrite_attrs(context, item, &result, attrs_shape)
3189 }
3190
3191 /// Rewrite `extern crate foo;`.
3192 /// The given shape is used to format the extern crate's attributes.
3193 pub(crate) fn rewrite_extern_crate(
3194     context: &RewriteContext<'_>,
3195     item: &ast::Item,
3196     attrs_shape: Shape,
3197 ) -> Option<String> {
3198     assert!(is_extern_crate(item));
3199     let new_str = context.snippet(item.span);
3200     let item_str = if contains_comment(new_str) {
3201         new_str.to_owned()
3202     } else {
3203         let no_whitespace = &new_str.split_whitespace().collect::<Vec<&str>>().join(" ");
3204         String::from(&*Regex::new(r"\s;").unwrap().replace(no_whitespace, ";"))
3205     };
3206     rewrite_attrs(context, item, &item_str, attrs_shape)
3207 }
3208
3209 /// Returns `true` for `mod foo;`, false for `mod foo { .. }`.
3210 pub(crate) fn is_mod_decl(item: &ast::Item) -> bool {
3211     match item.kind {
3212         ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(),
3213         _ => false,
3214     }
3215 }
3216
3217 pub(crate) fn is_use_item(item: &ast::Item) -> bool {
3218     match item.kind {
3219         ast::ItemKind::Use(_) => true,
3220         _ => false,
3221     }
3222 }
3223
3224 pub(crate) fn is_extern_crate(item: &ast::Item) -> bool {
3225     match item.kind {
3226         ast::ItemKind::ExternCrate(..) => true,
3227         _ => false,
3228     }
3229 }