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