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