]> git.lizzy.rs Git - rust.git/blob - src/items.rs
Merge pull request #2519 from topecongiro/nested-parens
[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,
27            rewrite_call_inner, ExprType};
28 use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator};
29 use rewrite::{Rewrite, RewriteContext};
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         let one_line_width = context.config.width_heuristics().fn_call_width;
1313         result = rewrite_call_inner(context, &result, fields, span, shape, one_line_width, false)?;
1314     }
1315
1316     if !where_clause_str.is_empty() && !where_clause_str.contains('\n')
1317         && (result.contains('\n')
1318             || offset.block_indent + result.len() + where_clause_str.len() + 1
1319                 > context.config.max_width())
1320     {
1321         // We need to put the where clause on a new line, but we didn't
1322         // know that earlier, so the where clause will not be indented properly.
1323         result.push('\n');
1324         result
1325             .push_str(&(offset.block_only() + (context.config.tab_spaces() - 1))
1326                 .to_string(context.config));
1327     }
1328     result.push_str(&where_clause_str);
1329
1330     Some(result)
1331 }
1332
1333 pub fn rewrite_type_alias(
1334     context: &RewriteContext,
1335     indent: Indent,
1336     ident: ast::Ident,
1337     ty: &ast::Ty,
1338     generics: &ast::Generics,
1339     vis: &ast::Visibility,
1340     span: Span,
1341 ) -> Option<String> {
1342     let mut result = String::with_capacity(128);
1343
1344     result.push_str(&format_visibility(vis));
1345     result.push_str("type ");
1346     result.push_str(&ident.to_string());
1347
1348     // 2 = `= `
1349     let g_shape = Shape::indented(indent, context.config)
1350         .offset_left(result.len())?
1351         .sub_width(2)?;
1352     let g_span = mk_sp(
1353         context.snippet_provider.span_after(span, "type"),
1354         ty.span.lo(),
1355     );
1356     let generics_str = rewrite_generics(context, generics, g_shape, g_span)?;
1357     result.push_str(&generics_str);
1358
1359     let where_budget = context.budget(last_line_width(&result));
1360     let option = WhereClauseOption::snuggled(&result);
1361     let where_clause_str = rewrite_where_clause(
1362         context,
1363         &generics.where_clause,
1364         context.config.brace_style(),
1365         Shape::legacy(where_budget, indent),
1366         Density::Vertical,
1367         "=",
1368         Some(span.hi()),
1369         generics.span.hi(),
1370         option,
1371         false,
1372     )?;
1373     result.push_str(&where_clause_str);
1374     if where_clause_str.is_empty() {
1375         result.push_str(" =");
1376     } else {
1377         result.push_str(&format!(
1378             "{}=",
1379             indent.to_string_with_newline(context.config)
1380         ));
1381     }
1382
1383     // 1 = ";"
1384     let ty_shape = Shape::indented(indent, context.config).sub_width(1)?;
1385     rewrite_assign_rhs(context, result, ty, ty_shape).map(|s| s + ";")
1386 }
1387
1388 fn type_annotation_spacing(config: &Config) -> (&str, &str) {
1389     (
1390         if config.space_before_colon() { " " } else { "" },
1391         if config.space_after_colon() { " " } else { "" },
1392     )
1393 }
1394
1395 pub fn rewrite_struct_field_prefix(
1396     context: &RewriteContext,
1397     field: &ast::StructField,
1398 ) -> Option<String> {
1399     let vis = format_visibility(&field.vis);
1400     let type_annotation_spacing = type_annotation_spacing(context.config);
1401     Some(match field.ident {
1402         Some(name) => format!("{}{}{}:", vis, name, type_annotation_spacing.0),
1403         None => format!("{}", vis),
1404     })
1405 }
1406
1407 impl Rewrite for ast::StructField {
1408     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
1409         rewrite_struct_field(context, self, shape, 0)
1410     }
1411 }
1412
1413 pub fn rewrite_struct_field(
1414     context: &RewriteContext,
1415     field: &ast::StructField,
1416     shape: Shape,
1417     lhs_max_width: usize,
1418 ) -> Option<String> {
1419     if contains_skip(&field.attrs) {
1420         return Some(context.snippet(field.span()).to_owned());
1421     }
1422
1423     let type_annotation_spacing = type_annotation_spacing(context.config);
1424     let prefix = rewrite_struct_field_prefix(context, field)?;
1425
1426     let attrs_str = field.attrs.rewrite(context, shape)?;
1427     let attrs_extendable = field.ident.is_none() && is_attributes_extendable(&attrs_str);
1428     let missing_span = if field.attrs.is_empty() {
1429         mk_sp(field.span.lo(), field.span.lo())
1430     } else {
1431         mk_sp(field.attrs.last().unwrap().span.hi(), field.span.lo())
1432     };
1433     let mut spacing = String::from(if field.ident.is_some() {
1434         type_annotation_spacing.1
1435     } else {
1436         ""
1437     });
1438     // Try to put everything on a single line.
1439     let attr_prefix = combine_strs_with_missing_comments(
1440         context,
1441         &attrs_str,
1442         &prefix,
1443         missing_span,
1444         shape,
1445         attrs_extendable,
1446     )?;
1447     let overhead = last_line_width(&attr_prefix);
1448     let lhs_offset = lhs_max_width.checked_sub(overhead).unwrap_or(0);
1449     for _ in 0..lhs_offset {
1450         spacing.push(' ');
1451     }
1452     // In this extreme case we will be missing a space betweeen an attribute and a field.
1453     if prefix.is_empty() && !attrs_str.is_empty() && attrs_extendable && spacing.is_empty() {
1454         spacing.push(' ');
1455     }
1456     let orig_ty = shape
1457         .offset_left(overhead + spacing.len())
1458         .and_then(|ty_shape| field.ty.rewrite(context, ty_shape));
1459     if let Some(ref ty) = orig_ty {
1460         if !ty.contains('\n') {
1461             return Some(attr_prefix + &spacing + ty);
1462         }
1463     }
1464
1465     let is_prefix_empty = prefix.is_empty();
1466     // We must use multiline. We are going to put attributes and a field on different lines.
1467     let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, shape)?;
1468     // Remove a leading white-space from `rewrite_assign_rhs()` when rewriting a tuple struct.
1469     let field_str = if is_prefix_empty {
1470         field_str.trim_left()
1471     } else {
1472         &field_str
1473     };
1474     combine_strs_with_missing_comments(context, &attrs_str, field_str, missing_span, shape, false)
1475 }
1476
1477 pub struct StaticParts<'a> {
1478     prefix: &'a str,
1479     vis: &'a ast::Visibility,
1480     ident: ast::Ident,
1481     ty: &'a ast::Ty,
1482     mutability: ast::Mutability,
1483     expr_opt: Option<&'a ptr::P<ast::Expr>>,
1484     defaultness: Option<ast::Defaultness>,
1485     span: Span,
1486 }
1487
1488 impl<'a> StaticParts<'a> {
1489     pub fn from_item(item: &'a ast::Item) -> Self {
1490         let (prefix, ty, mutability, expr) = match item.node {
1491             ast::ItemKind::Static(ref ty, mutability, ref expr) => ("static", ty, mutability, expr),
1492             ast::ItemKind::Const(ref ty, ref expr) => {
1493                 ("const", ty, ast::Mutability::Immutable, expr)
1494             }
1495             _ => unreachable!(),
1496         };
1497         StaticParts {
1498             prefix,
1499             vis: &item.vis,
1500             ident: item.ident,
1501             ty,
1502             mutability,
1503             expr_opt: Some(expr),
1504             defaultness: None,
1505             span: item.span,
1506         }
1507     }
1508
1509     pub fn from_trait_item(ti: &'a ast::TraitItem) -> Self {
1510         let (ty, expr_opt) = match ti.node {
1511             ast::TraitItemKind::Const(ref ty, ref expr_opt) => (ty, expr_opt),
1512             _ => unreachable!(),
1513         };
1514         StaticParts {
1515             prefix: "const",
1516             vis: &DEFAULT_VISIBILITY,
1517             ident: ti.ident,
1518             ty,
1519             mutability: ast::Mutability::Immutable,
1520             expr_opt: expr_opt.as_ref(),
1521             defaultness: None,
1522             span: ti.span,
1523         }
1524     }
1525
1526     pub fn from_impl_item(ii: &'a ast::ImplItem) -> Self {
1527         let (ty, expr) = match ii.node {
1528             ast::ImplItemKind::Const(ref ty, ref expr) => (ty, expr),
1529             _ => unreachable!(),
1530         };
1531         StaticParts {
1532             prefix: "const",
1533             vis: &ii.vis,
1534             ident: ii.ident,
1535             ty,
1536             mutability: ast::Mutability::Immutable,
1537             expr_opt: Some(expr),
1538             defaultness: Some(ii.defaultness),
1539             span: ii.span,
1540         }
1541     }
1542 }
1543
1544 fn rewrite_static(
1545     context: &RewriteContext,
1546     static_parts: &StaticParts,
1547     offset: Indent,
1548 ) -> Option<String> {
1549     let colon = colon_spaces(
1550         context.config.space_before_colon(),
1551         context.config.space_after_colon(),
1552     );
1553     let mut prefix = format!(
1554         "{}{}{} {}{}{}",
1555         format_visibility(static_parts.vis),
1556         static_parts.defaultness.map_or("", format_defaultness),
1557         static_parts.prefix,
1558         format_mutability(static_parts.mutability),
1559         static_parts.ident,
1560         colon,
1561     );
1562     // 2 = " =".len()
1563     let ty_shape =
1564         Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2)?;
1565     let ty_str = match static_parts.ty.rewrite(context, ty_shape) {
1566         Some(ty_str) => ty_str,
1567         None => {
1568             if prefix.ends_with(' ') {
1569                 prefix.pop();
1570             }
1571             let nested_indent = offset.block_indent(context.config);
1572             let nested_shape = Shape::indented(nested_indent, context.config);
1573             let ty_str = static_parts.ty.rewrite(context, nested_shape)?;
1574             format!(
1575                 "{}{}",
1576                 nested_indent.to_string_with_newline(context.config),
1577                 ty_str
1578             )
1579         }
1580     };
1581
1582     if let Some(expr) = static_parts.expr_opt {
1583         let lhs = format!("{}{} =", prefix, ty_str);
1584         // 1 = ;
1585         let remaining_width = context.budget(offset.block_indent + 1);
1586         rewrite_assign_rhs(
1587             context,
1588             lhs,
1589             &**expr,
1590             Shape::legacy(remaining_width, offset.block_only()),
1591         ).and_then(|res| recover_comment_removed(res, static_parts.span, context))
1592             .map(|s| if s.ends_with(';') { s } else { s + ";" })
1593     } else {
1594         Some(format!("{}{};", prefix, ty_str))
1595     }
1596 }
1597
1598 pub fn rewrite_associated_type(
1599     ident: ast::Ident,
1600     ty_opt: Option<&ptr::P<ast::Ty>>,
1601     ty_param_bounds_opt: Option<&ast::TyParamBounds>,
1602     context: &RewriteContext,
1603     indent: Indent,
1604 ) -> Option<String> {
1605     let prefix = format!("type {}", ident);
1606
1607     let type_bounds_str = if let Some(bounds) = ty_param_bounds_opt {
1608         // 2 = ": ".len()
1609         let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?;
1610         let bound_str = bounds
1611             .iter()
1612             .map(|ty_bound| ty_bound.rewrite(context, shape))
1613             .collect::<Option<Vec<_>>>()?;
1614         if !bounds.is_empty() {
1615             format!(": {}", join_bounds(context, shape, &bound_str))
1616         } else {
1617             String::new()
1618         }
1619     } else {
1620         String::new()
1621     };
1622
1623     if let Some(ty) = ty_opt {
1624         // 1 = `;`
1625         let shape = Shape::indented(indent, context.config).sub_width(1)?;
1626         let lhs = format!("{}{} =", prefix, type_bounds_str);
1627         rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";")
1628     } else {
1629         Some(format!("{}{};", prefix, type_bounds_str))
1630     }
1631 }
1632
1633 pub fn rewrite_associated_impl_type(
1634     ident: ast::Ident,
1635     defaultness: ast::Defaultness,
1636     ty_opt: Option<&ptr::P<ast::Ty>>,
1637     ty_param_bounds_opt: Option<&ast::TyParamBounds>,
1638     context: &RewriteContext,
1639     indent: Indent,
1640 ) -> Option<String> {
1641     let result = rewrite_associated_type(ident, ty_opt, ty_param_bounds_opt, context, indent)?;
1642
1643     match defaultness {
1644         ast::Defaultness::Default => Some(format!("default {}", result)),
1645         _ => Some(result),
1646     }
1647 }
1648
1649 impl Rewrite for ast::FunctionRetTy {
1650     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
1651         match *self {
1652             ast::FunctionRetTy::Default(_) => Some(String::new()),
1653             ast::FunctionRetTy::Ty(ref ty) => {
1654                 let inner_width = shape.width.checked_sub(3)?;
1655                 ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3))
1656                     .map(|r| format!("-> {}", r))
1657             }
1658         }
1659     }
1660 }
1661
1662 fn is_empty_infer(context: &RewriteContext, ty: &ast::Ty) -> bool {
1663     match ty.node {
1664         ast::TyKind::Infer => {
1665             let original = context.snippet(ty.span);
1666             original != "_"
1667         }
1668         _ => false,
1669     }
1670 }
1671
1672 impl Rewrite for ast::Arg {
1673     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
1674         if is_named_arg(self) {
1675             let mut result = self.pat
1676                 .rewrite(context, Shape::legacy(shape.width, shape.indent))?;
1677
1678             if !is_empty_infer(context, &*self.ty) {
1679                 if context.config.space_before_colon() {
1680                     result.push_str(" ");
1681                 }
1682                 result.push_str(":");
1683                 if context.config.space_after_colon() {
1684                     result.push_str(" ");
1685                 }
1686                 let overhead = last_line_width(&result);
1687                 let max_width = shape.width.checked_sub(overhead)?;
1688                 let ty_str = self.ty
1689                     .rewrite(context, Shape::legacy(max_width, shape.indent))?;
1690                 result.push_str(&ty_str);
1691             }
1692
1693             Some(result)
1694         } else {
1695             self.ty.rewrite(context, shape)
1696         }
1697     }
1698 }
1699
1700 fn rewrite_explicit_self(
1701     explicit_self: &ast::ExplicitSelf,
1702     args: &[ast::Arg],
1703     context: &RewriteContext,
1704 ) -> Option<String> {
1705     match explicit_self.node {
1706         ast::SelfKind::Region(lt, m) => {
1707             let mut_str = format_mutability(m);
1708             match lt {
1709                 Some(ref l) => {
1710                     let lifetime_str = l.rewrite(
1711                         context,
1712                         Shape::legacy(context.config.max_width(), Indent::empty()),
1713                     )?;
1714                     Some(format!("&{} {}self", lifetime_str, mut_str))
1715                 }
1716                 None => Some(format!("&{}self", mut_str)),
1717             }
1718         }
1719         ast::SelfKind::Explicit(ref ty, _) => {
1720             assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty.");
1721
1722             let mutability = explicit_self_mutability(&args[0]);
1723             let type_str = ty.rewrite(
1724                 context,
1725                 Shape::legacy(context.config.max_width(), Indent::empty()),
1726             )?;
1727
1728             Some(format!(
1729                 "{}self: {}",
1730                 format_mutability(mutability),
1731                 type_str
1732             ))
1733         }
1734         ast::SelfKind::Value(_) => {
1735             assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty.");
1736
1737             let mutability = explicit_self_mutability(&args[0]);
1738
1739             Some(format!("{}self", format_mutability(mutability)))
1740         }
1741     }
1742 }
1743
1744 // Hacky solution caused by absence of `Mutability` in `SelfValue` and
1745 // `SelfExplicit` variants of `ast::ExplicitSelf_`.
1746 fn explicit_self_mutability(arg: &ast::Arg) -> ast::Mutability {
1747     if let ast::PatKind::Ident(ast::BindingMode::ByValue(mutability), _, _) = arg.pat.node {
1748         mutability
1749     } else {
1750         unreachable!()
1751     }
1752 }
1753
1754 pub fn span_lo_for_arg(arg: &ast::Arg) -> BytePos {
1755     if is_named_arg(arg) {
1756         arg.pat.span.lo()
1757     } else {
1758         arg.ty.span.lo()
1759     }
1760 }
1761
1762 pub fn span_hi_for_arg(context: &RewriteContext, arg: &ast::Arg) -> BytePos {
1763     match arg.ty.node {
1764         ast::TyKind::Infer if context.snippet(arg.ty.span) == "_" => arg.ty.span.hi(),
1765         ast::TyKind::Infer if is_named_arg(arg) => arg.pat.span.hi(),
1766         _ => arg.ty.span.hi(),
1767     }
1768 }
1769
1770 pub fn is_named_arg(arg: &ast::Arg) -> bool {
1771     if let ast::PatKind::Ident(_, ident, _) = arg.pat.node {
1772         ident.node != symbol::keywords::Invalid.ident()
1773     } else {
1774         true
1775     }
1776 }
1777
1778 // Return type is (result, force_new_line_for_brace)
1779 fn rewrite_fn_base(
1780     context: &RewriteContext,
1781     indent: Indent,
1782     ident: ast::Ident,
1783     fn_sig: &FnSig,
1784     span: Span,
1785     newline_brace: bool,
1786     has_body: bool,
1787 ) -> Option<(String, bool)> {
1788     let mut force_new_line_for_brace = false;
1789
1790     let where_clause = &fn_sig.generics.where_clause;
1791
1792     let mut result = String::with_capacity(1024);
1793     result.push_str(&fn_sig.to_str(context));
1794
1795     // fn foo
1796     result.push_str("fn ");
1797     result.push_str(&ident.to_string());
1798
1799     // Generics.
1800     let overhead = if has_body && !newline_brace {
1801         // 4 = `() {`
1802         4
1803     } else {
1804         // 2 = `()`
1805         2
1806     };
1807     let used_width = last_line_used_width(&result, indent.width());
1808     let one_line_budget = context.budget(used_width + overhead);
1809     let shape = Shape {
1810         width: one_line_budget,
1811         indent,
1812         offset: used_width,
1813     };
1814     let fd = fn_sig.decl;
1815     let g_span = mk_sp(span.lo(), fd.output.span().lo());
1816     let generics_str = rewrite_generics(context, fn_sig.generics, shape, g_span)?;
1817     result.push_str(&generics_str);
1818
1819     let snuggle_angle_bracket = generics_str
1820         .lines()
1821         .last()
1822         .map_or(false, |l| l.trim_left().len() == 1);
1823
1824     // Note that the width and indent don't really matter, we'll re-layout the
1825     // return type later anyway.
1826     let ret_str = fd.output
1827         .rewrite(context, Shape::indented(indent, context.config))?;
1828
1829     let multi_line_ret_str = ret_str.contains('\n');
1830     let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() };
1831
1832     // Args.
1833     let (one_line_budget, multi_line_budget, mut arg_indent) = compute_budgets_for_args(
1834         context,
1835         &result,
1836         indent,
1837         ret_str_len,
1838         newline_brace,
1839         has_body,
1840         multi_line_ret_str,
1841     )?;
1842
1843     debug!(
1844         "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}",
1845         one_line_budget, multi_line_budget, arg_indent
1846     );
1847
1848     // Check if vertical layout was forced.
1849     if one_line_budget == 0 {
1850         if snuggle_angle_bracket {
1851             result.push('(');
1852         } else {
1853             result.push_str("(");
1854             if context.config.indent_style() == IndentStyle::Visual {
1855                 result.push_str(&arg_indent.to_string_with_newline(context.config));
1856             }
1857         }
1858     } else {
1859         result.push('(');
1860     }
1861     if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty()
1862         && result.ends_with('(')
1863     {
1864         result.push(' ')
1865     }
1866
1867     // Skip `pub(crate)`.
1868     let lo_after_visibility = get_bytepos_after_visibility(&fn_sig.visibility, span);
1869     // A conservative estimation, to goal is to be over all parens in generics
1870     let args_start = fn_sig
1871         .generics
1872         .params
1873         .iter()
1874         .last()
1875         .map_or(lo_after_visibility, |param| param.span().hi());
1876     let args_end = if fd.inputs.is_empty() {
1877         context
1878             .snippet_provider
1879             .span_after(mk_sp(args_start, span.hi()), ")")
1880     } else {
1881         let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi(), span.hi());
1882         context.snippet_provider.span_after(last_span, ")")
1883     };
1884     let args_span = mk_sp(
1885         context
1886             .snippet_provider
1887             .span_after(mk_sp(args_start, span.hi()), "("),
1888         args_end,
1889     );
1890     let arg_str = rewrite_args(
1891         context,
1892         &fd.inputs,
1893         fd.get_self().as_ref(),
1894         one_line_budget,
1895         multi_line_budget,
1896         indent,
1897         arg_indent,
1898         args_span,
1899         fd.variadic,
1900         generics_str.contains('\n'),
1901     )?;
1902
1903     let put_args_in_block = match context.config.indent_style() {
1904         IndentStyle::Block => arg_str.contains('\n') || arg_str.len() > one_line_budget,
1905         _ => false,
1906     } && !fd.inputs.is_empty();
1907
1908     let mut args_last_line_contains_comment = false;
1909     if put_args_in_block {
1910         arg_indent = indent.block_indent(context.config);
1911         result.push_str(&arg_indent.to_string_with_newline(context.config));
1912         result.push_str(&arg_str);
1913         result.push_str(&indent.to_string_with_newline(context.config));
1914         result.push(')');
1915     } else {
1916         result.push_str(&arg_str);
1917         let used_width = last_line_used_width(&result, indent.width()) + first_line_width(&ret_str);
1918         // Put the closing brace on the next line if it overflows the max width.
1919         // 1 = `)`
1920         if fd.inputs.is_empty() && used_width + 1 > context.config.max_width() {
1921             result.push('\n');
1922         }
1923         if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() {
1924             result.push(' ')
1925         }
1926         // If the last line of args contains comment, we cannot put the closing paren
1927         // on the same line.
1928         if arg_str
1929             .lines()
1930             .last()
1931             .map_or(false, |last_line| last_line.contains("//"))
1932         {
1933             args_last_line_contains_comment = true;
1934             result.push_str(&arg_indent.to_string_with_newline(context.config));
1935         }
1936         result.push(')');
1937     }
1938
1939     // Return type.
1940     if let ast::FunctionRetTy::Ty(..) = fd.output {
1941         let ret_should_indent = match context.config.indent_style() {
1942             // If our args are block layout then we surely must have space.
1943             IndentStyle::Block if put_args_in_block || fd.inputs.is_empty() => false,
1944             _ if args_last_line_contains_comment => false,
1945             _ if result.contains('\n') || multi_line_ret_str => true,
1946             _ => {
1947                 // If the return type would push over the max width, then put the return type on
1948                 // a new line. With the +1 for the signature length an additional space between
1949                 // the closing parenthesis of the argument and the arrow '->' is considered.
1950                 let mut sig_length = result.len() + indent.width() + ret_str_len + 1;
1951
1952                 // If there is no where clause, take into account the space after the return type
1953                 // and the brace.
1954                 if where_clause.predicates.is_empty() {
1955                     sig_length += 2;
1956                 }
1957
1958                 sig_length > context.config.max_width()
1959             }
1960         };
1961         let ret_indent = if ret_should_indent {
1962             let indent = if arg_str.is_empty() {
1963                 // Aligning with non-existent args looks silly.
1964                 force_new_line_for_brace = true;
1965                 indent + 4
1966             } else {
1967                 // FIXME: we might want to check that using the arg indent
1968                 // doesn't blow our budget, and if it does, then fallback to
1969                 // the where clause indent.
1970                 arg_indent
1971             };
1972
1973             result.push_str(&indent.to_string_with_newline(context.config));
1974             indent
1975         } else {
1976             result.push(' ');
1977             Indent::new(indent.block_indent, last_line_width(&result))
1978         };
1979
1980         if multi_line_ret_str || ret_should_indent {
1981             // Now that we know the proper indent and width, we need to
1982             // re-layout the return type.
1983             let ret_str = fd.output
1984                 .rewrite(context, Shape::indented(ret_indent, context.config))?;
1985             result.push_str(&ret_str);
1986         } else {
1987             result.push_str(&ret_str);
1988         }
1989
1990         // Comment between return type and the end of the decl.
1991         let snippet_lo = fd.output.span().hi();
1992         if where_clause.predicates.is_empty() {
1993             let snippet_hi = span.hi();
1994             let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi));
1995             // Try to preserve the layout of the original snippet.
1996             let original_starts_with_newline = snippet
1997                 .find(|c| c != ' ')
1998                 .map_or(false, |i| starts_with_newline(&snippet[i..]));
1999             let original_ends_with_newline = snippet
2000                 .rfind(|c| c != ' ')
2001                 .map_or(false, |i| snippet[i..].ends_with('\n'));
2002             let snippet = snippet.trim();
2003             if !snippet.is_empty() {
2004                 result.push(if original_starts_with_newline {
2005                     '\n'
2006                 } else {
2007                     ' '
2008                 });
2009                 result.push_str(snippet);
2010                 if original_ends_with_newline {
2011                     force_new_line_for_brace = true;
2012                 }
2013             }
2014         }
2015     }
2016
2017     let pos_before_where = match fd.output {
2018         ast::FunctionRetTy::Default(..) => args_span.hi(),
2019         ast::FunctionRetTy::Ty(ref ty) => ty.span.hi(),
2020     };
2021
2022     let is_args_multi_lined = arg_str.contains('\n');
2023
2024     let option = WhereClauseOption::new(!has_body, put_args_in_block && ret_str.is_empty());
2025     let where_clause_str = rewrite_where_clause(
2026         context,
2027         where_clause,
2028         context.config.brace_style(),
2029         Shape::indented(indent, context.config),
2030         Density::Tall,
2031         "{",
2032         Some(span.hi()),
2033         pos_before_where,
2034         option,
2035         is_args_multi_lined,
2036     )?;
2037     // If there are neither where clause nor return type, we may be missing comments between
2038     // args and `{`.
2039     if where_clause_str.is_empty() {
2040         if let ast::FunctionRetTy::Default(ret_span) = fd.output {
2041             match recover_missing_comment_in_span(
2042                 mk_sp(args_span.hi(), ret_span.hi()),
2043                 shape,
2044                 context,
2045                 last_line_width(&result),
2046             ) {
2047                 Some(ref missing_comment) if !missing_comment.is_empty() => {
2048                     result.push_str(missing_comment);
2049                     force_new_line_for_brace = true;
2050                 }
2051                 _ => (),
2052             }
2053         }
2054     }
2055
2056     result.push_str(&where_clause_str);
2057
2058     force_new_line_for_brace |= last_line_contains_single_line_comment(&result);
2059     force_new_line_for_brace |= is_args_multi_lined && context.config.where_single_line();
2060     Some((result, force_new_line_for_brace))
2061 }
2062
2063 #[derive(Copy, Clone)]
2064 struct WhereClauseOption {
2065     suppress_comma: bool, // Force no trailing comma
2066     snuggle: bool,        // Do not insert newline before `where`
2067     compress_where: bool, // Try single line where clause instead of vertical layout
2068 }
2069
2070 impl WhereClauseOption {
2071     pub fn new(suppress_comma: bool, snuggle: bool) -> WhereClauseOption {
2072         WhereClauseOption {
2073             suppress_comma,
2074             snuggle,
2075             compress_where: false,
2076         }
2077     }
2078
2079     pub fn snuggled(current: &str) -> WhereClauseOption {
2080         WhereClauseOption {
2081             suppress_comma: false,
2082             snuggle: trimmed_last_line_width(current) == 1,
2083             compress_where: false,
2084         }
2085     }
2086 }
2087
2088 fn rewrite_args(
2089     context: &RewriteContext,
2090     args: &[ast::Arg],
2091     explicit_self: Option<&ast::ExplicitSelf>,
2092     one_line_budget: usize,
2093     multi_line_budget: usize,
2094     indent: Indent,
2095     arg_indent: Indent,
2096     span: Span,
2097     variadic: bool,
2098     generics_str_contains_newline: bool,
2099 ) -> Option<String> {
2100     let mut arg_item_strs = args.iter()
2101         .map(|arg| arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent)))
2102         .collect::<Option<Vec<_>>>()?;
2103
2104     // Account for sugary self.
2105     // FIXME: the comment for the self argument is dropped. This is blocked
2106     // on rust issue #27522.
2107     let min_args = explicit_self
2108         .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context))
2109         .map_or(1, |self_str| {
2110             arg_item_strs[0] = self_str;
2111             2
2112         });
2113
2114     // Comments between args.
2115     let mut arg_items = Vec::new();
2116     if min_args == 2 {
2117         arg_items.push(ListItem::from_str(""));
2118     }
2119
2120     // FIXME(#21): if there are no args, there might still be a comment, but
2121     // without spans for the comment or parens, there is no chance of
2122     // getting it right. You also don't get to put a comment on self, unless
2123     // it is explicit.
2124     if args.len() >= min_args || variadic {
2125         let comment_span_start = if min_args == 2 {
2126             let second_arg_start = if arg_has_pattern(&args[1]) {
2127                 args[1].pat.span.lo()
2128             } else {
2129                 args[1].ty.span.lo()
2130             };
2131             let reduced_span = mk_sp(span.lo(), second_arg_start);
2132
2133             context.snippet_provider.span_after_last(reduced_span, ",")
2134         } else {
2135             span.lo()
2136         };
2137
2138         enum ArgumentKind<'a> {
2139             Regular(&'a ast::Arg),
2140             Variadic(BytePos),
2141         }
2142
2143         let variadic_arg = if variadic {
2144             let variadic_span = mk_sp(args.last().unwrap().ty.span.hi(), span.hi());
2145             let variadic_start =
2146                 context.snippet_provider.span_after(variadic_span, "...") - BytePos(3);
2147             Some(ArgumentKind::Variadic(variadic_start))
2148         } else {
2149             None
2150         };
2151
2152         let more_items = itemize_list(
2153             context.snippet_provider,
2154             args[min_args - 1..]
2155                 .iter()
2156                 .map(ArgumentKind::Regular)
2157                 .chain(variadic_arg),
2158             ")",
2159             ",",
2160             |arg| match *arg {
2161                 ArgumentKind::Regular(arg) => span_lo_for_arg(arg),
2162                 ArgumentKind::Variadic(start) => start,
2163             },
2164             |arg| match *arg {
2165                 ArgumentKind::Regular(arg) => arg.ty.span.hi(),
2166                 ArgumentKind::Variadic(start) => start + BytePos(3),
2167             },
2168             |arg| match *arg {
2169                 ArgumentKind::Regular(..) => None,
2170                 ArgumentKind::Variadic(..) => Some("...".to_owned()),
2171             },
2172             comment_span_start,
2173             span.hi(),
2174             false,
2175         );
2176
2177         arg_items.extend(more_items);
2178     }
2179
2180     let fits_in_one_line = !generics_str_contains_newline
2181         && (arg_items.is_empty()
2182             || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget);
2183
2184     for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) {
2185         item.item = Some(arg);
2186     }
2187
2188     let last_line_ends_with_comment = arg_items
2189         .iter()
2190         .last()
2191         .and_then(|item| item.post_comment.as_ref())
2192         .map_or(false, |s| s.trim().starts_with("//"));
2193
2194     let (indent, trailing_comma) = match context.config.indent_style() {
2195         IndentStyle::Block if fits_in_one_line => {
2196             (indent.block_indent(context.config), SeparatorTactic::Never)
2197         }
2198         IndentStyle::Block => (
2199             indent.block_indent(context.config),
2200             context.config.trailing_comma(),
2201         ),
2202         IndentStyle::Visual if last_line_ends_with_comment => {
2203             (arg_indent, context.config.trailing_comma())
2204         }
2205         IndentStyle::Visual => (arg_indent, SeparatorTactic::Never),
2206     };
2207
2208     let tactic = definitive_tactic(
2209         &arg_items,
2210         context.config.fn_args_density().to_list_tactic(),
2211         Separator::Comma,
2212         one_line_budget,
2213     );
2214     let budget = match tactic {
2215         DefinitiveListTactic::Horizontal => one_line_budget,
2216         _ => multi_line_budget,
2217     };
2218
2219     debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic);
2220
2221     let fmt = ListFormatting {
2222         tactic,
2223         separator: ",",
2224         trailing_separator: if variadic {
2225             SeparatorTactic::Never
2226         } else {
2227             trailing_comma
2228         },
2229         separator_place: SeparatorPlace::Back,
2230         shape: Shape::legacy(budget, indent),
2231         ends_with_newline: tactic.ends_with_newline(context.config.indent_style()),
2232         preserve_newline: true,
2233         config: context.config,
2234     };
2235
2236     write_list(&arg_items, &fmt)
2237 }
2238
2239 fn arg_has_pattern(arg: &ast::Arg) -> bool {
2240     if let ast::PatKind::Ident(_, ident, _) = arg.pat.node {
2241         ident.node != symbol::keywords::Invalid.ident()
2242     } else {
2243         true
2244     }
2245 }
2246
2247 fn compute_budgets_for_args(
2248     context: &RewriteContext,
2249     result: &str,
2250     indent: Indent,
2251     ret_str_len: usize,
2252     newline_brace: bool,
2253     has_braces: bool,
2254     force_vertical_layout: bool,
2255 ) -> Option<((usize, usize, Indent))> {
2256     debug!(
2257         "compute_budgets_for_args {} {:?}, {}, {}",
2258         result.len(),
2259         indent,
2260         ret_str_len,
2261         newline_brace
2262     );
2263     // Try keeping everything on the same line.
2264     if !result.contains('\n') && !force_vertical_layout {
2265         // 2 = `()`, 3 = `() `, space is before ret_string.
2266         let overhead = if ret_str_len == 0 { 2 } else { 3 };
2267         let mut used_space = indent.width() + result.len() + ret_str_len + overhead;
2268         if has_braces {
2269             if !newline_brace {
2270                 // 2 = `{}`
2271                 used_space += 2;
2272             }
2273         } else {
2274             // 1 = `;`
2275             used_space += 1;
2276         }
2277         let one_line_budget = context.budget(used_space);
2278
2279         if one_line_budget > 0 {
2280             // 4 = "() {".len()
2281             let (indent, multi_line_budget) = match context.config.indent_style() {
2282                 IndentStyle::Block => {
2283                     let indent = indent.block_indent(context.config);
2284                     (indent, context.budget(indent.width() + 1))
2285                 }
2286                 IndentStyle::Visual => {
2287                     let indent = indent + result.len() + 1;
2288                     let multi_line_overhead = indent.width() + if newline_brace { 2 } else { 4 };
2289                     (indent, context.budget(multi_line_overhead))
2290                 }
2291             };
2292
2293             return Some((one_line_budget, multi_line_budget, indent));
2294         }
2295     }
2296
2297     // Didn't work. we must force vertical layout and put args on a newline.
2298     let new_indent = indent.block_indent(context.config);
2299     let used_space = match context.config.indent_style() {
2300         // 1 = `,`
2301         IndentStyle::Block => new_indent.width() + 1,
2302         // Account for `)` and possibly ` {`.
2303         IndentStyle::Visual => new_indent.width() + if ret_str_len == 0 { 1 } else { 3 },
2304     };
2305     Some((0, context.budget(used_space), new_indent))
2306 }
2307
2308 fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool {
2309     let predicate_count = where_clause.predicates.len();
2310
2311     if config.where_single_line() && predicate_count == 1 {
2312         return false;
2313     }
2314     let brace_style = config.brace_style();
2315
2316     brace_style == BraceStyle::AlwaysNextLine
2317         || (brace_style == BraceStyle::SameLineWhere && predicate_count > 0)
2318 }
2319
2320 fn rewrite_generics(
2321     context: &RewriteContext,
2322     generics: &ast::Generics,
2323     shape: Shape,
2324     span: Span,
2325 ) -> Option<String> {
2326     let g_shape = generics_shape_from_config(context.config, shape, 0)?;
2327     let one_line_width = shape.width.checked_sub(2).unwrap_or(0);
2328     rewrite_generics_inner(context, generics, g_shape, one_line_width, span)
2329         .or_else(|| rewrite_generics_inner(context, generics, g_shape, 0, span))
2330 }
2331
2332 fn rewrite_generics_inner(
2333     context: &RewriteContext,
2334     generics: &ast::Generics,
2335     shape: Shape,
2336     one_line_width: usize,
2337     span: Span,
2338 ) -> Option<String> {
2339     // FIXME: convert bounds to where clauses where they get too big or if
2340     // there is a where clause at all.
2341
2342     if generics.params.is_empty() {
2343         return Some(String::new());
2344     }
2345
2346     let items = itemize_list(
2347         context.snippet_provider,
2348         generics.params.iter(),
2349         ">",
2350         ",",
2351         |arg| arg.span().lo(),
2352         |arg| arg.span().hi(),
2353         |arg| arg.rewrite(context, shape),
2354         context.snippet_provider.span_after(span, "<"),
2355         span.hi(),
2356         false,
2357     );
2358     format_generics_item_list(context, items, shape, one_line_width)
2359 }
2360
2361 pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option<Shape> {
2362     match config.indent_style() {
2363         IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width(offset + 2),
2364         IndentStyle::Block => {
2365             // 1 = ","
2366             shape
2367                 .block()
2368                 .block_indent(config.tab_spaces())
2369                 .with_max_width(config)
2370                 .sub_width(1)
2371         }
2372     }
2373 }
2374
2375 pub fn format_generics_item_list<I>(
2376     context: &RewriteContext,
2377     items: I,
2378     shape: Shape,
2379     one_line_budget: usize,
2380 ) -> Option<String>
2381 where
2382     I: Iterator<Item = ListItem>,
2383 {
2384     let item_vec = items.collect::<Vec<_>>();
2385
2386     let tactic = definitive_tactic(
2387         &item_vec,
2388         ListTactic::HorizontalVertical,
2389         Separator::Comma,
2390         one_line_budget,
2391     );
2392     let fmt = ListFormatting {
2393         tactic,
2394         separator: ",",
2395         trailing_separator: if context.config.indent_style() == IndentStyle::Visual {
2396             SeparatorTactic::Never
2397         } else {
2398             context.config.trailing_comma()
2399         },
2400         separator_place: SeparatorPlace::Back,
2401         shape,
2402         ends_with_newline: tactic.ends_with_newline(context.config.indent_style()),
2403         preserve_newline: true,
2404         config: context.config,
2405     };
2406
2407     let list_str = write_list(&item_vec, &fmt)?;
2408
2409     Some(wrap_generics_with_angle_brackets(
2410         context,
2411         &list_str,
2412         shape.indent,
2413     ))
2414 }
2415
2416 pub fn wrap_generics_with_angle_brackets(
2417     context: &RewriteContext,
2418     list_str: &str,
2419     list_offset: Indent,
2420 ) -> String {
2421     if context.config.indent_style() == IndentStyle::Block
2422         && (list_str.contains('\n') || list_str.ends_with(','))
2423     {
2424         format!(
2425             "<\n{}{}\n{}>",
2426             list_offset.to_string(context.config),
2427             list_str,
2428             list_offset
2429                 .block_unindent(context.config)
2430                 .to_string(context.config)
2431         )
2432     } else if context.config.spaces_within_parens_and_brackets() {
2433         format!("< {} >", list_str)
2434     } else {
2435         format!("<{}>", list_str)
2436     }
2437 }
2438
2439 fn rewrite_trait_bounds(
2440     context: &RewriteContext,
2441     bounds: &[ast::TyParamBound],
2442     shape: Shape,
2443 ) -> Option<String> {
2444     if bounds.is_empty() {
2445         return Some(String::new());
2446     }
2447     let bound_str = bounds
2448         .iter()
2449         .map(|ty_bound| ty_bound.rewrite(context, shape))
2450         .collect::<Option<Vec<_>>>()?;
2451     Some(format!(": {}", join_bounds(context, shape, &bound_str)))
2452 }
2453
2454 fn rewrite_where_clause_rfc_style(
2455     context: &RewriteContext,
2456     where_clause: &ast::WhereClause,
2457     shape: Shape,
2458     terminator: &str,
2459     span_end: Option<BytePos>,
2460     span_end_before_where: BytePos,
2461     where_clause_option: WhereClauseOption,
2462     is_args_multi_line: bool,
2463 ) -> Option<String> {
2464     let block_shape = shape.block().with_max_width(context.config);
2465
2466     let (span_before, span_after) =
2467         missing_span_before_after_where(span_end_before_where, where_clause);
2468     let (comment_before, comment_after) =
2469         rewrite_comments_before_after_where(context, span_before, span_after, shape)?;
2470
2471     let starting_newline = if where_clause_option.snuggle && comment_before.is_empty() {
2472         Cow::from(" ")
2473     } else {
2474         block_shape.indent.to_string_with_newline(context.config)
2475     };
2476
2477     let clause_shape = block_shape.block_left(context.config.tab_spaces())?;
2478     // 1 = `,`
2479     let clause_shape = clause_shape.sub_width(1)?;
2480     // each clause on one line, trailing comma (except if suppress_comma)
2481     let span_start = where_clause.predicates[0].span().lo();
2482     // If we don't have the start of the next span, then use the end of the
2483     // predicates, but that means we miss comments.
2484     let len = where_clause.predicates.len();
2485     let end_of_preds = where_clause.predicates[len - 1].span().hi();
2486     let span_end = span_end.unwrap_or(end_of_preds);
2487     let items = itemize_list(
2488         context.snippet_provider,
2489         where_clause.predicates.iter(),
2490         terminator,
2491         ",",
2492         |pred| pred.span().lo(),
2493         |pred| pred.span().hi(),
2494         |pred| pred.rewrite(context, clause_shape),
2495         span_start,
2496         span_end,
2497         false,
2498     );
2499     let where_single_line = context.config.where_single_line() && len == 1 && !is_args_multi_line;
2500     let comma_tactic = if where_clause_option.suppress_comma || where_single_line {
2501         SeparatorTactic::Never
2502     } else {
2503         context.config.trailing_comma()
2504     };
2505
2506     // shape should be vertical only and only if we have `where_single_line` option enabled
2507     // and the number of items of the where clause is equal to 1
2508     let shape_tactic = if where_single_line {
2509         DefinitiveListTactic::Horizontal
2510     } else {
2511         DefinitiveListTactic::Vertical
2512     };
2513
2514     let fmt = ListFormatting {
2515         tactic: shape_tactic,
2516         separator: ",",
2517         trailing_separator: comma_tactic,
2518         separator_place: SeparatorPlace::Back,
2519         shape: clause_shape,
2520         ends_with_newline: true,
2521         preserve_newline: true,
2522         config: context.config,
2523     };
2524     let preds_str = write_list(&items.collect::<Vec<_>>(), &fmt)?;
2525
2526     let comment_separator = |comment: &str, shape: Shape| {
2527         if comment.is_empty() {
2528             Cow::from("")
2529         } else {
2530             shape.indent.to_string_with_newline(context.config)
2531         }
2532     };
2533     let newline_before_where = comment_separator(&comment_before, shape);
2534     let newline_after_where = comment_separator(&comment_after, clause_shape);
2535
2536     // 6 = `where `
2537     let clause_sep = if where_clause_option.compress_where && comment_before.is_empty()
2538         && comment_after.is_empty() && !preds_str.contains('\n')
2539         && 6 + preds_str.len() <= shape.width || where_single_line
2540     {
2541         Cow::from(" ")
2542     } else {
2543         clause_shape.indent.to_string_with_newline(context.config)
2544     };
2545     Some(format!(
2546         "{}{}{}where{}{}{}{}",
2547         starting_newline,
2548         comment_before,
2549         newline_before_where,
2550         newline_after_where,
2551         comment_after,
2552         clause_sep,
2553         preds_str
2554     ))
2555 }
2556
2557 fn rewrite_where_clause(
2558     context: &RewriteContext,
2559     where_clause: &ast::WhereClause,
2560     brace_style: BraceStyle,
2561     shape: Shape,
2562     density: Density,
2563     terminator: &str,
2564     span_end: Option<BytePos>,
2565     span_end_before_where: BytePos,
2566     where_clause_option: WhereClauseOption,
2567     is_args_multi_line: bool,
2568 ) -> Option<String> {
2569     if where_clause.predicates.is_empty() {
2570         return Some(String::new());
2571     }
2572
2573     if context.config.indent_style() == IndentStyle::Block {
2574         return rewrite_where_clause_rfc_style(
2575             context,
2576             where_clause,
2577             shape,
2578             terminator,
2579             span_end,
2580             span_end_before_where,
2581             where_clause_option,
2582             is_args_multi_line,
2583         );
2584     }
2585
2586     let extra_indent = Indent::new(context.config.tab_spaces(), 0);
2587
2588     let offset = match context.config.indent_style() {
2589         IndentStyle::Block => shape.indent + extra_indent.block_indent(context.config),
2590         // 6 = "where ".len()
2591         IndentStyle::Visual => shape.indent + extra_indent + 6,
2592     };
2593     // FIXME: if indent_style != Visual, then the budgets below might
2594     // be out by a char or two.
2595
2596     let budget = context.config.max_width() - offset.width();
2597     let span_start = where_clause.predicates[0].span().lo();
2598     // If we don't have the start of the next span, then use the end of the
2599     // predicates, but that means we miss comments.
2600     let len = where_clause.predicates.len();
2601     let end_of_preds = where_clause.predicates[len - 1].span().hi();
2602     let span_end = span_end.unwrap_or(end_of_preds);
2603     let items = itemize_list(
2604         context.snippet_provider,
2605         where_clause.predicates.iter(),
2606         terminator,
2607         ",",
2608         |pred| pred.span().lo(),
2609         |pred| pred.span().hi(),
2610         |pred| pred.rewrite(context, Shape::legacy(budget, offset)),
2611         span_start,
2612         span_end,
2613         false,
2614     );
2615     let item_vec = items.collect::<Vec<_>>();
2616     // FIXME: we don't need to collect here
2617     let tactic = definitive_tactic(&item_vec, ListTactic::Vertical, Separator::Comma, budget);
2618
2619     let mut comma_tactic = context.config.trailing_comma();
2620     // Kind of a hack because we don't usually have trailing commas in where clauses.
2621     if comma_tactic == SeparatorTactic::Vertical || where_clause_option.suppress_comma {
2622         comma_tactic = SeparatorTactic::Never;
2623     }
2624
2625     let fmt = ListFormatting {
2626         tactic,
2627         separator: ",",
2628         trailing_separator: comma_tactic,
2629         separator_place: SeparatorPlace::Back,
2630         shape: Shape::legacy(budget, offset),
2631         ends_with_newline: tactic.ends_with_newline(context.config.indent_style()),
2632         preserve_newline: true,
2633         config: context.config,
2634     };
2635     let preds_str = write_list(&item_vec, &fmt)?;
2636
2637     let end_length = if terminator == "{" {
2638         // If the brace is on the next line we don't need to count it otherwise it needs two
2639         // characters " {"
2640         match brace_style {
2641             BraceStyle::AlwaysNextLine | BraceStyle::SameLineWhere => 0,
2642             BraceStyle::PreferSameLine => 2,
2643         }
2644     } else if terminator == "=" {
2645         2
2646     } else {
2647         terminator.len()
2648     };
2649     if density == Density::Tall || preds_str.contains('\n')
2650         || shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width
2651     {
2652         Some(format!(
2653             "\n{}where {}",
2654             (shape.indent + extra_indent).to_string(context.config),
2655             preds_str
2656         ))
2657     } else {
2658         Some(format!(" where {}", preds_str))
2659     }
2660 }
2661
2662 fn missing_span_before_after_where(
2663     before_item_span_end: BytePos,
2664     where_clause: &ast::WhereClause,
2665 ) -> (Span, Span) {
2666     let missing_span_before = mk_sp(before_item_span_end, where_clause.span.lo());
2667     // 5 = `where`
2668     let pos_after_where = where_clause.span.lo() + BytePos(5);
2669     let missing_span_after = mk_sp(pos_after_where, where_clause.predicates[0].span().lo());
2670     (missing_span_before, missing_span_after)
2671 }
2672
2673 fn rewrite_comments_before_after_where(
2674     context: &RewriteContext,
2675     span_before_where: Span,
2676     span_after_where: Span,
2677     shape: Shape,
2678 ) -> Option<(String, String)> {
2679     let before_comment = rewrite_missing_comment(span_before_where, shape, context)?;
2680     let after_comment = rewrite_missing_comment(
2681         span_after_where,
2682         shape.block_indent(context.config.tab_spaces()),
2683         context,
2684     )?;
2685     Some((before_comment, after_comment))
2686 }
2687
2688 fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String {
2689     format!("{}{}{}", format_visibility(vis), item_name, ident)
2690 }
2691
2692 #[derive(PartialEq, Eq, Clone, Copy)]
2693 enum BracePos {
2694     None,
2695     Auto,
2696     ForceSameLine,
2697 }
2698
2699 fn format_generics(
2700     context: &RewriteContext,
2701     generics: &ast::Generics,
2702     brace_style: BraceStyle,
2703     brace_pos: BracePos,
2704     offset: Indent,
2705     span: Span,
2706     used_width: usize,
2707 ) -> Option<String> {
2708     let shape = Shape::legacy(context.budget(used_width + offset.width()), offset);
2709     let mut result = rewrite_generics(context, generics, shape, span)?;
2710
2711     let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') {
2712         let budget = context.budget(last_line_used_width(&result, offset.width()));
2713         let mut option = WhereClauseOption::snuggled(&result);
2714         if brace_pos == BracePos::None {
2715             option.suppress_comma = true;
2716         }
2717         // If the generics are not parameterized then generics.span.hi() == 0,
2718         // so we use span.lo(), which is the position after `struct Foo`.
2719         let span_end_before_where = if generics.is_parameterized() {
2720             generics.span.hi()
2721         } else {
2722             span.lo()
2723         };
2724         let where_clause_str = rewrite_where_clause(
2725             context,
2726             &generics.where_clause,
2727             brace_style,
2728             Shape::legacy(budget, offset.block_only()),
2729             Density::Tall,
2730             "{",
2731             Some(span.hi()),
2732             span_end_before_where,
2733             option,
2734             false,
2735         )?;
2736         result.push_str(&where_clause_str);
2737         brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine
2738             || (generics.where_clause.predicates.is_empty()
2739                 && trimmed_last_line_width(&result) == 1)
2740     } else {
2741         brace_pos == BracePos::ForceSameLine || trimmed_last_line_width(&result) == 1
2742             || brace_style != BraceStyle::AlwaysNextLine
2743     };
2744     if brace_pos == BracePos::None {
2745         return Some(result);
2746     }
2747     let total_used_width = last_line_used_width(&result, used_width);
2748     let remaining_budget = context.budget(total_used_width);
2749     // If the same line brace if forced, it indicates that we are rewriting an item with empty body,
2750     // and hence we take the closer into account as well for one line budget.
2751     // We assume that the closer has the same length as the opener.
2752     let overhead = if brace_pos == BracePos::ForceSameLine {
2753         // 3 = ` {}`
2754         3
2755     } else {
2756         // 2 = ` {`
2757         2
2758     };
2759     let forbid_same_line_brace = overhead > remaining_budget;
2760     if !forbid_same_line_brace && same_line_brace {
2761         result.push(' ');
2762     } else {
2763         result.push('\n');
2764         result.push_str(&offset.block_only().to_string(context.config));
2765     }
2766     result.push('{');
2767
2768     Some(result)
2769 }
2770
2771 impl Rewrite for ast::ForeignItem {
2772     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
2773         let attrs_str = self.attrs.rewrite(context, shape)?;
2774         // Drop semicolon or it will be interpreted as comment.
2775         // FIXME: this may be a faulty span from libsyntax.
2776         let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1));
2777
2778         let item_str = match self.node {
2779             ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => {
2780                 rewrite_fn_base(
2781                     context,
2782                     shape.indent,
2783                     self.ident,
2784                     &FnSig::new(fn_decl, generics, self.vis.clone()),
2785                     span,
2786                     false,
2787                     false,
2788                 ).map(|(s, _)| format!("{};", s))
2789             }
2790             ast::ForeignItemKind::Static(ref ty, is_mutable) => {
2791                 // FIXME(#21): we're dropping potential comments in between the
2792                 // function keywords here.
2793                 let vis = format_visibility(&self.vis);
2794                 let mut_str = if is_mutable { "mut " } else { "" };
2795                 let prefix = format!("{}static {}{}:", vis, mut_str, self.ident);
2796                 // 1 = ;
2797                 let shape = shape.sub_width(1)?;
2798                 ty.rewrite(context, shape).map(|ty_str| {
2799                     // 1 = space between prefix and type.
2800                     let sep = if prefix.len() + ty_str.len() + 1 <= shape.width {
2801                         Cow::from(" ")
2802                     } else {
2803                         let nested_indent = shape.indent.block_indent(context.config);
2804                         nested_indent.to_string_with_newline(context.config)
2805                     };
2806                     format!("{}{}{};", prefix, sep, ty_str)
2807                 })
2808             }
2809             ast::ForeignItemKind::Ty => {
2810                 let vis = format_visibility(&self.vis);
2811                 Some(format!("{}type {};", vis, self.ident))
2812             }
2813         }?;
2814
2815         let missing_span = if self.attrs.is_empty() {
2816             mk_sp(self.span.lo(), self.span.lo())
2817         } else {
2818             mk_sp(self.attrs[self.attrs.len() - 1].span.hi(), self.span.lo())
2819         };
2820         combine_strs_with_missing_comments(
2821             context,
2822             &attrs_str,
2823             &item_str,
2824             missing_span,
2825             shape,
2826             false,
2827         )
2828     }
2829 }
2830
2831 impl Rewrite for ast::GenericParam {
2832     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
2833         match *self {
2834             ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.rewrite(context, shape),
2835             ast::GenericParam::Type(ref ty) => ty.rewrite(context, shape),
2836         }
2837     }
2838 }
2839
2840 /// Rewrite an inline mod.
2841 pub fn rewrite_mod(item: &ast::Item) -> String {
2842     let mut result = String::with_capacity(32);
2843     result.push_str(&*format_visibility(&item.vis));
2844     result.push_str("mod ");
2845     result.push_str(&item.ident.to_string());
2846     result.push(';');
2847     result
2848 }
2849
2850 /// Rewrite `extern crate foo;` WITHOUT attributes.
2851 pub fn rewrite_extern_crate(context: &RewriteContext, item: &ast::Item) -> Option<String> {
2852     assert!(is_extern_crate(item));
2853     let new_str = context.snippet(item.span);
2854     Some(if contains_comment(new_str) {
2855         new_str.to_owned()
2856     } else {
2857         let no_whitespace = &new_str.split_whitespace().collect::<Vec<&str>>().join(" ");
2858         String::from(&*Regex::new(r"\s;").unwrap().replace(no_whitespace, ";"))
2859     })
2860 }
2861
2862 /// Returns true for `mod foo;`, false for `mod foo { .. }`.
2863 pub fn is_mod_decl(item: &ast::Item) -> bool {
2864     match item.node {
2865         ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(),
2866         _ => false,
2867     }
2868 }
2869
2870 pub fn is_use_item(item: &ast::Item) -> bool {
2871     match item.node {
2872         ast::ItemKind::Use(_) => true,
2873         _ => false,
2874     }
2875 }
2876
2877 pub fn is_extern_crate(item: &ast::Item) -> bool {
2878     match item.node {
2879         ast::ItemKind::ExternCrate(..) => true,
2880         _ => false,
2881     }
2882 }