]> git.lizzy.rs Git - rust.git/blob - src/items.rs
ce1bc1ae3182eaf72264aae8c55fe66b0d756590
[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_extendable, last_line_used_width, last_line_width, mk_sp,
37             semicolon_for_expr, starts_with_newline, 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_extendable(&result)
635             && (last_line_contains_single_line_comment(&result) || result.contains('\n'));
636         match context.config.brace_style() {
637             _ if need_newline => result.push_str(&sep),
638             BraceStyle::AlwaysNextLine => result.push_str(&sep),
639             BraceStyle::PreferSameLine => result.push(' '),
640             BraceStyle::SameLineWhere => {
641                 if !where_clause_str.is_empty() {
642                     result.push_str(&sep);
643                 } else {
644                     result.push(' ');
645                 }
646             }
647         }
648
649         result.push('{');
650
651         let snippet = context.snippet(item.span);
652         let open_pos = snippet.find_uncommented("{")? + 1;
653
654         if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
655             let mut visitor = FmtVisitor::from_context(context);
656             visitor.block_indent = offset.block_only().block_indent(context.config);
657             visitor.last_pos = item.span.lo() + BytePos(open_pos as u32);
658
659             visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner);
660             for item in items {
661                 visitor.visit_impl_item(item);
662             }
663
664             visitor.format_missing(item.span.hi() - BytePos(1));
665
666             let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config);
667             let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
668
669             result.push_str(&inner_indent_str);
670             result.push_str(visitor.buffer.to_string().trim());
671             result.push_str(&outer_indent_str);
672         }
673
674         if result.ends_with('{') {
675             result.push_str(&sep);
676         }
677         result.push('}');
678
679         Some(result)
680     } else {
681         unreachable!();
682     }
683 }
684
685 fn is_impl_single_line(
686     context: &RewriteContext,
687     items: &[ast::ImplItem],
688     result: &str,
689     where_clause_str: &str,
690     item: &ast::Item,
691 ) -> Option<bool> {
692     let snippet = context.snippet(item.span);
693     let open_pos = snippet.find_uncommented("{")? + 1;
694
695     Some(
696         context.config.empty_item_single_line() && items.is_empty() && !result.contains('\n')
697             && result.len() + where_clause_str.len() <= context.config.max_width()
698             && !contains_comment(&snippet[open_pos..]),
699     )
700 }
701
702 fn format_impl_ref_and_type(
703     context: &RewriteContext,
704     item: &ast::Item,
705     offset: Indent,
706 ) -> Option<String> {
707     if let ast::ItemKind::Impl(
708         unsafety,
709         polarity,
710         defaultness,
711         ref generics,
712         ref trait_ref,
713         ref self_ty,
714         _,
715     ) = item.node
716     {
717         let mut result = String::with_capacity(128);
718
719         result.push_str(&format_visibility(&item.vis));
720         result.push_str(format_defaultness(defaultness));
721         result.push_str(format_unsafety(unsafety));
722         result.push_str("impl");
723
724         let lo = context.snippet_provider.span_after(item.span, "impl");
725         let hi = match *trait_ref {
726             Some(ref tr) => tr.path.span.lo(),
727             None => self_ty.span.lo(),
728         };
729         let shape = generics_shape_from_config(
730             context.config,
731             Shape::indented(offset + last_line_width(&result), context.config),
732             0,
733         )?;
734         let one_line_budget = shape.width.checked_sub(last_line_width(&result) + 2)?;
735         let generics_str =
736             rewrite_generics_inner(context, generics, shape, one_line_budget, mk_sp(lo, hi))?;
737
738         let polarity_str = if polarity == ast::ImplPolarity::Negative {
739             "!"
740         } else {
741             ""
742         };
743
744         if let Some(ref trait_ref) = *trait_ref {
745             let result_len = result.len();
746             if let Some(trait_ref_str) = rewrite_trait_ref(
747                 context,
748                 trait_ref,
749                 offset,
750                 &generics_str,
751                 true,
752                 polarity_str,
753                 result_len,
754             ) {
755                 result.push_str(&trait_ref_str);
756             } else {
757                 let generics_str =
758                     rewrite_generics_inner(context, generics, shape, 0, mk_sp(lo, hi))?;
759                 result.push_str(&rewrite_trait_ref(
760                     context,
761                     trait_ref,
762                     offset,
763                     &generics_str,
764                     false,
765                     polarity_str,
766                     result_len,
767                 )?);
768             }
769         } else {
770             result.push_str(&generics_str);
771         }
772
773         // Try to put the self type in a single line.
774         // ` for`
775         let trait_ref_overhead = if trait_ref.is_some() { 4 } else { 0 };
776         let curly_brace_overhead = if generics.where_clause.predicates.is_empty() {
777             // If there is no where clause adapt budget for type formatting to take space and curly
778             // brace into account.
779             match context.config.brace_style() {
780                 BraceStyle::AlwaysNextLine => 0,
781                 _ => 2,
782             }
783         } else {
784             0
785         };
786         let used_space = last_line_width(&result) + trait_ref_overhead + curly_brace_overhead;
787         // 1 = space before the type.
788         let budget = context.budget(used_space + 1);
789         if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) {
790             if !self_ty_str.contains('\n') {
791                 if trait_ref.is_some() {
792                     result.push_str(" for ");
793                 } else {
794                     result.push(' ');
795                 }
796                 result.push_str(&self_ty_str);
797                 return Some(result);
798             }
799         }
800
801         // Couldn't fit the self type on a single line, put it on a new line.
802         result.push('\n');
803         // Add indentation of one additional tab.
804         let new_line_offset = offset.block_indent(context.config);
805         result.push_str(&new_line_offset.to_string(context.config));
806         if trait_ref.is_some() {
807             result.push_str("for ");
808         }
809         let budget = context.budget(last_line_width(&result));
810         let type_offset = match context.config.indent_style() {
811             IndentStyle::Visual => new_line_offset + trait_ref_overhead,
812             IndentStyle::Block => new_line_offset,
813         };
814         result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?);
815         Some(result)
816     } else {
817         unreachable!();
818     }
819 }
820
821 fn rewrite_trait_ref(
822     context: &RewriteContext,
823     trait_ref: &ast::TraitRef,
824     offset: Indent,
825     generics_str: &str,
826     retry: bool,
827     polarity_str: &str,
828     result_len: usize,
829 ) -> Option<String> {
830     // 1 = space between generics and trait_ref
831     let used_space = 1 + polarity_str.len() + last_line_used_width(generics_str, result_len);
832     let shape = Shape::indented(offset + used_space, context.config);
833     if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) {
834         if !(retry && trait_ref_str.contains('\n')) {
835             return Some(format!(
836                 "{} {}{}",
837                 generics_str, polarity_str, &trait_ref_str
838             ));
839         }
840     }
841     // We could not make enough space for trait_ref, so put it on new line.
842     if !retry {
843         let offset = offset.block_indent(context.config);
844         let shape = Shape::indented(offset, context.config);
845         let trait_ref_str = trait_ref.rewrite(context, shape)?;
846         Some(format!(
847             "{}\n{}{}{}",
848             generics_str,
849             &offset.to_string(context.config),
850             polarity_str,
851             &trait_ref_str
852         ))
853     } else {
854         None
855     }
856 }
857
858 pub struct StructParts<'a> {
859     prefix: &'a str,
860     ident: ast::Ident,
861     vis: &'a ast::Visibility,
862     def: &'a ast::VariantData,
863     generics: Option<&'a ast::Generics>,
864     span: Span,
865 }
866
867 impl<'a> StructParts<'a> {
868     fn format_header(&self) -> String {
869         format_header(self.prefix, self.ident, self.vis)
870     }
871
872     fn from_variant(variant: &'a ast::Variant) -> Self {
873         StructParts {
874             prefix: "",
875             ident: variant.node.name,
876             vis: &DEFAULT_VISIBILITY,
877             def: &variant.node.data,
878             generics: None,
879             span: variant.span,
880         }
881     }
882
883     pub fn from_item(item: &'a ast::Item) -> Self {
884         let (prefix, def, generics) = match item.node {
885             ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics),
886             ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics),
887             _ => unreachable!(),
888         };
889         StructParts {
890             prefix,
891             ident: item.ident,
892             vis: &item.vis,
893             def,
894             generics: Some(generics),
895             span: item.span,
896         }
897     }
898 }
899
900 fn format_struct(
901     context: &RewriteContext,
902     struct_parts: &StructParts,
903     offset: Indent,
904     one_line_width: Option<usize>,
905 ) -> Option<String> {
906     match *struct_parts.def {
907         ast::VariantData::Unit(..) => format_unit_struct(context, struct_parts, offset),
908         ast::VariantData::Tuple(ref fields, _) => {
909             format_tuple_struct(context, struct_parts, fields, offset)
910         }
911         ast::VariantData::Struct(ref fields, _) => {
912             format_struct_struct(context, struct_parts, fields, offset, one_line_width)
913         }
914     }
915 }
916
917 pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option<String> {
918     if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) =
919         item.node
920     {
921         let mut result = String::with_capacity(128);
922         let header = format!(
923             "{}{}trait {}",
924             format_visibility(&item.vis),
925             format_unsafety(unsafety),
926             item.ident
927         );
928
929         result.push_str(&header);
930
931         let body_lo = context.snippet_provider.span_after(item.span, "{");
932
933         let shape = Shape::indented(offset, context.config).offset_left(result.len())?;
934         let generics_str =
935             rewrite_generics(context, generics, shape, mk_sp(item.span.lo(), body_lo))?;
936         result.push_str(&generics_str);
937
938         // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
939         if !type_param_bounds.is_empty() {
940             let ident_hi = context
941                 .snippet_provider
942                 .span_after(item.span, &format!("{}", item.ident));
943             let bound_hi = type_param_bounds.last().unwrap().span().hi();
944             let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
945             if contains_comment(snippet) {
946                 return None;
947             }
948         }
949         let trait_bound_str = rewrite_trait_bounds(
950             context,
951             type_param_bounds,
952             Shape::indented(offset, context.config),
953         )?;
954         // If the trait, generics, and trait bound cannot fit on the same line,
955         // put the trait bounds on an indented new line
956         if offset.width() + last_line_width(&result) + trait_bound_str.len()
957             > context.config.comment_width()
958         {
959             let trait_indent = offset.block_only().block_indent(context.config);
960             result.push_str(&trait_indent.to_string_with_newline(context.config));
961         }
962         result.push_str(&trait_bound_str);
963
964         let where_density =
965             if context.config.indent_style() == IndentStyle::Block && result.is_empty() {
966                 Density::Compressed
967             } else {
968                 Density::Tall
969             };
970
971         let where_budget = context.budget(last_line_width(&result));
972         let pos_before_where = if type_param_bounds.is_empty() {
973             generics.where_clause.span.lo()
974         } else {
975             type_param_bounds[type_param_bounds.len() - 1].span().hi()
976         };
977         let option = WhereClauseOption::snuggled(&generics_str);
978         let where_clause_str = rewrite_where_clause(
979             context,
980             &generics.where_clause,
981             context.config.brace_style(),
982             Shape::legacy(where_budget, offset.block_only()),
983             where_density,
984             "{",
985             None,
986             pos_before_where,
987             option,
988             false,
989         )?;
990         // If the where clause cannot fit on the same line,
991         // put the where clause on a new line
992         if !where_clause_str.contains('\n')
993             && last_line_width(&result) + where_clause_str.len() + offset.width()
994                 > context.config.comment_width()
995         {
996             let width = offset.block_indent + context.config.tab_spaces() - 1;
997             let where_indent = Indent::new(0, width);
998             result.push_str(&where_indent.to_string_with_newline(context.config));
999         }
1000         result.push_str(&where_clause_str);
1001
1002         if generics.where_clause.predicates.is_empty() {
1003             let item_snippet = context.snippet(item.span);
1004             if let Some(lo) = item_snippet.chars().position(|c| c == '/') {
1005                 // 1 = `{`
1006                 let comment_hi = body_lo - BytePos(1);
1007                 let comment_lo = item.span.lo() + BytePos(lo as u32);
1008                 if comment_lo < comment_hi {
1009                     match recover_missing_comment_in_span(
1010                         mk_sp(comment_lo, comment_hi),
1011                         Shape::indented(offset, context.config),
1012                         context,
1013                         last_line_width(&result),
1014                     ) {
1015                         Some(ref missing_comment) if !missing_comment.is_empty() => {
1016                             result.push_str(missing_comment);
1017                         }
1018                         _ => (),
1019                     }
1020                 }
1021             }
1022         }
1023
1024         match context.config.brace_style() {
1025             _ if last_line_contains_single_line_comment(&result) => {
1026                 result.push_str(&offset.to_string_with_newline(context.config));
1027             }
1028             BraceStyle::AlwaysNextLine => {
1029                 result.push_str(&offset.to_string_with_newline(context.config));
1030             }
1031             BraceStyle::PreferSameLine => result.push(' '),
1032             BraceStyle::SameLineWhere => {
1033                 if !where_clause_str.is_empty()
1034                     && (!trait_items.is_empty() || result.contains('\n'))
1035                 {
1036                     result.push_str(&offset.to_string_with_newline(context.config));
1037                 } else {
1038                     result.push(' ');
1039                 }
1040             }
1041         }
1042         result.push('{');
1043
1044         let snippet = context.snippet(item.span);
1045         let open_pos = snippet.find_uncommented("{")? + 1;
1046
1047         if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) {
1048             let mut visitor = FmtVisitor::from_context(context);
1049             visitor.block_indent = offset.block_only().block_indent(context.config);
1050             visitor.last_pos = item.span.lo() + BytePos(open_pos as u32);
1051
1052             for item in trait_items {
1053                 visitor.visit_trait_item(item);
1054             }
1055
1056             visitor.format_missing(item.span.hi() - BytePos(1));
1057
1058             let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config);
1059             let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
1060
1061             result.push_str(&inner_indent_str);
1062             result.push_str(visitor.buffer.to_string().trim());
1063             result.push_str(&outer_indent_str);
1064         } else if result.contains('\n') {
1065             result.push('\n');
1066         }
1067
1068         result.push('}');
1069         Some(result)
1070     } else {
1071         unreachable!();
1072     }
1073 }
1074
1075 pub fn format_trait_alias(
1076     context: &RewriteContext,
1077     ident: ast::Ident,
1078     generics: &ast::Generics,
1079     ty_param_bounds: &ast::TyParamBounds,
1080     shape: Shape,
1081 ) -> Option<String> {
1082     let alias = ident.name.as_str();
1083     // 6 = "trait ", 2 = " ="
1084     let g_shape = shape.offset_left(6 + alias.len())?.sub_width(2)?;
1085     let generics_str = rewrite_generics(context, generics, g_shape, generics.span)?;
1086     let lhs = format!("trait {}{} =", alias, generics_str);
1087     // 1 = ";"
1088     rewrite_assign_rhs(context, lhs, ty_param_bounds, shape.sub_width(1)?).map(|s| s + ";")
1089 }
1090
1091 fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) -> Option<String> {
1092     let header_str = format_header(p.prefix, p.ident, p.vis);
1093     let generics_str = if let Some(generics) = p.generics {
1094         let hi = if generics.where_clause.predicates.is_empty() {
1095             generics.span.hi()
1096         } else {
1097             generics.where_clause.span.hi()
1098         };
1099         format_generics(
1100             context,
1101             generics,
1102             context.config.brace_style(),
1103             BracePos::None,
1104             offset,
1105             mk_sp(generics.span.lo(), hi),
1106             last_line_width(&header_str),
1107         )?
1108     } else {
1109         String::new()
1110     };
1111     Some(format!("{}{};", header_str, generics_str))
1112 }
1113
1114 pub fn format_struct_struct(
1115     context: &RewriteContext,
1116     struct_parts: &StructParts,
1117     fields: &[ast::StructField],
1118     offset: Indent,
1119     one_line_width: Option<usize>,
1120 ) -> Option<String> {
1121     let mut result = String::with_capacity(1024);
1122     let span = struct_parts.span;
1123
1124     let header_str = struct_parts.format_header();
1125     result.push_str(&header_str);
1126
1127     let header_hi = span.lo() + BytePos(header_str.len() as u32);
1128     let body_lo = context.snippet_provider.span_after(span, "{");
1129
1130     let generics_str = match struct_parts.generics {
1131         Some(g) => format_generics(
1132             context,
1133             g,
1134             context.config.brace_style(),
1135             if fields.is_empty() {
1136                 BracePos::ForceSameLine
1137             } else {
1138                 BracePos::Auto
1139             },
1140             offset,
1141             mk_sp(header_hi, body_lo),
1142             last_line_width(&result),
1143         )?,
1144         None => {
1145             // 3 = ` {}`, 2 = ` {`.
1146             let overhead = if fields.is_empty() { 3 } else { 2 };
1147             if (context.config.brace_style() == BraceStyle::AlwaysNextLine && !fields.is_empty())
1148                 || context.config.max_width() < overhead + result.len()
1149             {
1150                 format!("\n{}{{", offset.block_only().to_string(context.config))
1151             } else {
1152                 " {".to_owned()
1153             }
1154         }
1155     };
1156     // 1 = `}`
1157     let overhead = if fields.is_empty() { 1 } else { 0 };
1158     let total_width = result.len() + generics_str.len() + overhead;
1159     if !generics_str.is_empty() && !generics_str.contains('\n')
1160         && total_width > context.config.max_width()
1161     {
1162         result.push('\n');
1163         result.push_str(&offset.to_string(context.config));
1164         result.push_str(generics_str.trim_left());
1165     } else {
1166         result.push_str(&generics_str);
1167     }
1168
1169     if fields.is_empty() {
1170         let snippet = context.snippet(mk_sp(body_lo, span.hi() - BytePos(1)));
1171         if snippet.trim().is_empty() {
1172             // `struct S {}`
1173         } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') {
1174             // fix indent
1175             result.push_str(snippet.trim_right());
1176             result.push('\n');
1177             result.push_str(&offset.to_string(context.config));
1178         } else {
1179             result.push_str(snippet);
1180         }
1181         result.push('}');
1182         return Some(result);
1183     }
1184
1185     // 3 = ` ` and ` }`
1186     let one_line_budget = context.budget(result.len() + 3 + offset.width());
1187     let one_line_budget =
1188         one_line_width.map_or(0, |one_line_width| min(one_line_width, one_line_budget));
1189
1190     let items_str = rewrite_with_alignment(
1191         fields,
1192         context,
1193         Shape::indented(offset, context.config).sub_width(1)?,
1194         mk_sp(body_lo, span.hi()),
1195         one_line_budget,
1196     )?;
1197
1198     if !items_str.contains('\n') && !result.contains('\n') && items_str.len() <= one_line_budget
1199         && !last_line_contains_single_line_comment(&items_str)
1200     {
1201         Some(format!("{} {} }}", result, items_str))
1202     } else {
1203         Some(format!(
1204             "{}\n{}{}\n{}}}",
1205             result,
1206             offset
1207                 .block_indent(context.config)
1208                 .to_string(context.config),
1209             items_str,
1210             offset.to_string(context.config)
1211         ))
1212     }
1213 }
1214
1215 fn get_bytepos_after_visibility(vis: &ast::Visibility, default_span: Span) -> BytePos {
1216     match vis.node {
1217         ast::VisibilityKind::Crate(..) | ast::VisibilityKind::Restricted { .. } => vis.span.hi(),
1218         _ => default_span.lo(),
1219     }
1220 }
1221
1222 fn format_tuple_struct(
1223     context: &RewriteContext,
1224     struct_parts: &StructParts,
1225     fields: &[ast::StructField],
1226     offset: Indent,
1227 ) -> Option<String> {
1228     let mut result = String::with_capacity(1024);
1229     let span = struct_parts.span;
1230
1231     let header_str = struct_parts.format_header();
1232     result.push_str(&header_str);
1233
1234     let body_lo = if fields.is_empty() {
1235         let lo = get_bytepos_after_visibility(struct_parts.vis, span);
1236         context
1237             .snippet_provider
1238             .span_after(mk_sp(lo, span.hi()), "(")
1239     } else {
1240         fields[0].span.lo()
1241     };
1242     let body_hi = if fields.is_empty() {
1243         context
1244             .snippet_provider
1245             .span_after(mk_sp(body_lo, span.hi()), ")")
1246     } else {
1247         // This is a dirty hack to work around a missing `)` from the span of the last field.
1248         let last_arg_span = fields[fields.len() - 1].span;
1249         if context.snippet(last_arg_span).ends_with(')') {
1250             last_arg_span.hi()
1251         } else {
1252             context
1253                 .snippet_provider
1254                 .span_after(mk_sp(last_arg_span.hi(), span.hi()), ")")
1255         }
1256     };
1257
1258     let where_clause_str = match struct_parts.generics {
1259         Some(generics) => {
1260             let budget = context.budget(last_line_width(&header_str));
1261             let shape = Shape::legacy(budget, offset);
1262             let g_span = mk_sp(span.lo(), body_lo);
1263             let generics_str = rewrite_generics(context, generics, shape, g_span)?;
1264             result.push_str(&generics_str);
1265
1266             let where_budget = context.budget(last_line_width(&result));
1267             let option = WhereClauseOption::new(true, false);
1268             rewrite_where_clause(
1269                 context,
1270                 &generics.where_clause,
1271                 context.config.brace_style(),
1272                 Shape::legacy(where_budget, offset.block_only()),
1273                 Density::Compressed,
1274                 ";",
1275                 None,
1276                 body_hi,
1277                 option,
1278                 false,
1279             )?
1280         }
1281         None => "".to_owned(),
1282     };
1283
1284     if fields.is_empty() {
1285         // 3 = `();`
1286         let used_width = last_line_used_width(&result, offset.width()) + 3;
1287         if used_width > context.config.max_width() {
1288             result.push('\n');
1289             result.push_str(&offset
1290                 .block_indent(context.config)
1291                 .to_string(context.config))
1292         }
1293         result.push('(');
1294         let snippet = context.snippet(mk_sp(
1295             body_lo,
1296             context
1297                 .snippet_provider
1298                 .span_before(mk_sp(body_lo, span.hi()), ")"),
1299         ));
1300         if snippet.is_empty() {
1301             // `struct S ()`
1302         } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') {
1303             result.push_str(snippet.trim_right());
1304             result.push('\n');
1305             result.push_str(&offset.to_string(context.config));
1306         } else {
1307             result.push_str(snippet);
1308         }
1309         result.push(')');
1310     } else {
1311         let shape = Shape::indented(offset, context.config).sub_width(1)?;
1312         let fields = &fields.iter().collect::<Vec<_>>()[..];
1313         let one_line_width = context.config.width_heuristics().fn_call_width;
1314         result = rewrite_call_inner(context, &result, fields, span, shape, one_line_width, false)?;
1315     }
1316
1317     if !where_clause_str.is_empty() && !where_clause_str.contains('\n')
1318         && (result.contains('\n')
1319             || offset.block_indent + result.len() + where_clause_str.len() + 1
1320                 > context.config.max_width())
1321     {
1322         // We need to put the where clause on a new line, but we didn't
1323         // know that earlier, so the where clause will not be indented properly.
1324         result.push('\n');
1325         result
1326             .push_str(&(offset.block_only() + (context.config.tab_spaces() - 1))
1327                 .to_string(context.config));
1328     }
1329     result.push_str(&where_clause_str);
1330
1331     Some(result)
1332 }
1333
1334 pub fn rewrite_type_alias(
1335     context: &RewriteContext,
1336     indent: Indent,
1337     ident: ast::Ident,
1338     ty: &ast::Ty,
1339     generics: &ast::Generics,
1340     vis: &ast::Visibility,
1341     span: Span,
1342 ) -> Option<String> {
1343     let mut result = String::with_capacity(128);
1344
1345     result.push_str(&format_visibility(vis));
1346     result.push_str("type ");
1347     result.push_str(&ident.to_string());
1348
1349     // 2 = `= `
1350     let g_shape = Shape::indented(indent, context.config)
1351         .offset_left(result.len())?
1352         .sub_width(2)?;
1353     let g_span = mk_sp(
1354         context.snippet_provider.span_after(span, "type"),
1355         ty.span.lo(),
1356     );
1357     let generics_str = rewrite_generics(context, generics, g_shape, g_span)?;
1358     result.push_str(&generics_str);
1359
1360     let where_budget = context.budget(last_line_width(&result));
1361     let option = WhereClauseOption::snuggled(&result);
1362     let where_clause_str = rewrite_where_clause(
1363         context,
1364         &generics.where_clause,
1365         context.config.brace_style(),
1366         Shape::legacy(where_budget, indent),
1367         Density::Vertical,
1368         "=",
1369         Some(span.hi()),
1370         generics.span.hi(),
1371         option,
1372         false,
1373     )?;
1374     result.push_str(&where_clause_str);
1375     if where_clause_str.is_empty() {
1376         result.push_str(" =");
1377     } else {
1378         result.push_str(&format!(
1379             "{}=",
1380             indent.to_string_with_newline(context.config)
1381         ));
1382     }
1383
1384     // 1 = ";"
1385     let ty_shape = Shape::indented(indent, context.config).sub_width(1)?;
1386     rewrite_assign_rhs(context, result, ty, ty_shape).map(|s| s + ";")
1387 }
1388
1389 fn type_annotation_spacing(config: &Config) -> (&str, &str) {
1390     (
1391         if config.space_before_colon() { " " } else { "" },
1392         if config.space_after_colon() { " " } else { "" },
1393     )
1394 }
1395
1396 pub fn rewrite_struct_field_prefix(
1397     context: &RewriteContext,
1398     field: &ast::StructField,
1399 ) -> Option<String> {
1400     let vis = format_visibility(&field.vis);
1401     let type_annotation_spacing = type_annotation_spacing(context.config);
1402     Some(match field.ident {
1403         Some(name) => format!("{}{}{}:", vis, name, type_annotation_spacing.0),
1404         None => format!("{}", vis),
1405     })
1406 }
1407
1408 impl Rewrite for ast::StructField {
1409     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
1410         rewrite_struct_field(context, self, shape, 0)
1411     }
1412 }
1413
1414 pub fn rewrite_struct_field(
1415     context: &RewriteContext,
1416     field: &ast::StructField,
1417     shape: Shape,
1418     lhs_max_width: usize,
1419 ) -> Option<String> {
1420     if contains_skip(&field.attrs) {
1421         return Some(context.snippet(field.span()).to_owned());
1422     }
1423
1424     let type_annotation_spacing = type_annotation_spacing(context.config);
1425     let prefix = rewrite_struct_field_prefix(context, field)?;
1426
1427     let attrs_str = field.attrs.rewrite(context, shape)?;
1428     let attrs_extendable = field.ident.is_none() && is_attributes_extendable(&attrs_str);
1429     let missing_span = if field.attrs.is_empty() {
1430         mk_sp(field.span.lo(), field.span.lo())
1431     } else {
1432         mk_sp(field.attrs.last().unwrap().span.hi(), field.span.lo())
1433     };
1434     let mut spacing = String::from(if field.ident.is_some() {
1435         type_annotation_spacing.1
1436     } else {
1437         ""
1438     });
1439     // Try to put everything on a single line.
1440     let attr_prefix = combine_strs_with_missing_comments(
1441         context,
1442         &attrs_str,
1443         &prefix,
1444         missing_span,
1445         shape,
1446         attrs_extendable,
1447     )?;
1448     let overhead = last_line_width(&attr_prefix);
1449     let lhs_offset = lhs_max_width.checked_sub(overhead).unwrap_or(0);
1450     for _ in 0..lhs_offset {
1451         spacing.push(' ');
1452     }
1453     // In this extreme case we will be missing a space betweeen an attribute and a field.
1454     if prefix.is_empty() && !attrs_str.is_empty() && attrs_extendable && spacing.is_empty() {
1455         spacing.push(' ');
1456     }
1457     let orig_ty = shape
1458         .offset_left(overhead + spacing.len())
1459         .and_then(|ty_shape| field.ty.rewrite(context, ty_shape));
1460     if let Some(ref ty) = orig_ty {
1461         if !ty.contains('\n') {
1462             return Some(attr_prefix + &spacing + ty);
1463         }
1464     }
1465
1466     let is_prefix_empty = prefix.is_empty();
1467     // We must use multiline. We are going to put attributes and a field on different lines.
1468     let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, shape)?;
1469     // Remove a leading white-space from `rewrite_assign_rhs()` when rewriting a tuple struct.
1470     let field_str = if is_prefix_empty {
1471         field_str.trim_left()
1472     } else {
1473         &field_str
1474     };
1475     combine_strs_with_missing_comments(context, &attrs_str, field_str, missing_span, shape, false)
1476 }
1477
1478 pub struct StaticParts<'a> {
1479     prefix: &'a str,
1480     vis: &'a ast::Visibility,
1481     ident: ast::Ident,
1482     ty: &'a ast::Ty,
1483     mutability: ast::Mutability,
1484     expr_opt: Option<&'a ptr::P<ast::Expr>>,
1485     defaultness: Option<ast::Defaultness>,
1486     span: Span,
1487 }
1488
1489 impl<'a> StaticParts<'a> {
1490     pub fn from_item(item: &'a ast::Item) -> Self {
1491         let (prefix, ty, mutability, expr) = match item.node {
1492             ast::ItemKind::Static(ref ty, mutability, ref expr) => ("static", ty, mutability, expr),
1493             ast::ItemKind::Const(ref ty, ref expr) => {
1494                 ("const", ty, ast::Mutability::Immutable, expr)
1495             }
1496             _ => unreachable!(),
1497         };
1498         StaticParts {
1499             prefix,
1500             vis: &item.vis,
1501             ident: item.ident,
1502             ty,
1503             mutability,
1504             expr_opt: Some(expr),
1505             defaultness: None,
1506             span: item.span,
1507         }
1508     }
1509
1510     pub fn from_trait_item(ti: &'a ast::TraitItem) -> Self {
1511         let (ty, expr_opt) = match ti.node {
1512             ast::TraitItemKind::Const(ref ty, ref expr_opt) => (ty, expr_opt),
1513             _ => unreachable!(),
1514         };
1515         StaticParts {
1516             prefix: "const",
1517             vis: &DEFAULT_VISIBILITY,
1518             ident: ti.ident,
1519             ty,
1520             mutability: ast::Mutability::Immutable,
1521             expr_opt: expr_opt.as_ref(),
1522             defaultness: None,
1523             span: ti.span,
1524         }
1525     }
1526
1527     pub fn from_impl_item(ii: &'a ast::ImplItem) -> Self {
1528         let (ty, expr) = match ii.node {
1529             ast::ImplItemKind::Const(ref ty, ref expr) => (ty, expr),
1530             _ => unreachable!(),
1531         };
1532         StaticParts {
1533             prefix: "const",
1534             vis: &ii.vis,
1535             ident: ii.ident,
1536             ty,
1537             mutability: ast::Mutability::Immutable,
1538             expr_opt: Some(expr),
1539             defaultness: Some(ii.defaultness),
1540             span: ii.span,
1541         }
1542     }
1543 }
1544
1545 fn rewrite_static(
1546     context: &RewriteContext,
1547     static_parts: &StaticParts,
1548     offset: Indent,
1549 ) -> Option<String> {
1550     let colon = colon_spaces(
1551         context.config.space_before_colon(),
1552         context.config.space_after_colon(),
1553     );
1554     let mut prefix = format!(
1555         "{}{}{} {}{}{}",
1556         format_visibility(static_parts.vis),
1557         static_parts.defaultness.map_or("", format_defaultness),
1558         static_parts.prefix,
1559         format_mutability(static_parts.mutability),
1560         static_parts.ident,
1561         colon,
1562     );
1563     // 2 = " =".len()
1564     let ty_shape =
1565         Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2)?;
1566     let ty_str = match static_parts.ty.rewrite(context, ty_shape) {
1567         Some(ty_str) => ty_str,
1568         None => {
1569             if prefix.ends_with(' ') {
1570                 prefix.pop();
1571             }
1572             let nested_indent = offset.block_indent(context.config);
1573             let nested_shape = Shape::indented(nested_indent, context.config);
1574             let ty_str = static_parts.ty.rewrite(context, nested_shape)?;
1575             format!(
1576                 "{}{}",
1577                 nested_indent.to_string_with_newline(context.config),
1578                 ty_str
1579             )
1580         }
1581     };
1582
1583     if let Some(expr) = static_parts.expr_opt {
1584         let lhs = format!("{}{} =", prefix, ty_str);
1585         // 1 = ;
1586         let remaining_width = context.budget(offset.block_indent + 1);
1587         rewrite_assign_rhs(
1588             context,
1589             lhs,
1590             &**expr,
1591             Shape::legacy(remaining_width, offset.block_only()),
1592         ).and_then(|res| recover_comment_removed(res, static_parts.span, context))
1593             .map(|s| if s.ends_with(';') { s } else { s + ";" })
1594     } else {
1595         Some(format!("{}{};", prefix, ty_str))
1596     }
1597 }
1598
1599 pub fn rewrite_associated_type(
1600     ident: ast::Ident,
1601     ty_opt: Option<&ptr::P<ast::Ty>>,
1602     ty_param_bounds_opt: Option<&ast::TyParamBounds>,
1603     context: &RewriteContext,
1604     indent: Indent,
1605 ) -> Option<String> {
1606     let prefix = format!("type {}", ident);
1607
1608     let type_bounds_str = if let Some(bounds) = ty_param_bounds_opt {
1609         // 2 = ": ".len()
1610         let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?;
1611         let bound_str = bounds
1612             .iter()
1613             .map(|ty_bound| ty_bound.rewrite(context, shape))
1614             .collect::<Option<Vec<_>>>()?;
1615         if !bounds.is_empty() {
1616             format!(": {}", join_bounds(context, shape, &bound_str))
1617         } else {
1618             String::new()
1619         }
1620     } else {
1621         String::new()
1622     };
1623
1624     if let Some(ty) = ty_opt {
1625         // 1 = `;`
1626         let shape = Shape::indented(indent, context.config).sub_width(1)?;
1627         let lhs = format!("{}{} =", prefix, type_bounds_str);
1628         rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";")
1629     } else {
1630         Some(format!("{}{};", prefix, type_bounds_str))
1631     }
1632 }
1633
1634 pub fn rewrite_associated_impl_type(
1635     ident: ast::Ident,
1636     defaultness: ast::Defaultness,
1637     ty_opt: Option<&ptr::P<ast::Ty>>,
1638     ty_param_bounds_opt: Option<&ast::TyParamBounds>,
1639     context: &RewriteContext,
1640     indent: Indent,
1641 ) -> Option<String> {
1642     let result = rewrite_associated_type(ident, ty_opt, ty_param_bounds_opt, context, indent)?;
1643
1644     match defaultness {
1645         ast::Defaultness::Default => Some(format!("default {}", result)),
1646         _ => Some(result),
1647     }
1648 }
1649
1650 impl Rewrite for ast::FunctionRetTy {
1651     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
1652         match *self {
1653             ast::FunctionRetTy::Default(_) => Some(String::new()),
1654             ast::FunctionRetTy::Ty(ref ty) => {
1655                 let inner_width = shape.width.checked_sub(3)?;
1656                 ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3))
1657                     .map(|r| format!("-> {}", r))
1658             }
1659         }
1660     }
1661 }
1662
1663 fn is_empty_infer(context: &RewriteContext, ty: &ast::Ty) -> bool {
1664     match ty.node {
1665         ast::TyKind::Infer => {
1666             let original = context.snippet(ty.span);
1667             original != "_"
1668         }
1669         _ => false,
1670     }
1671 }
1672
1673 impl Rewrite for ast::Arg {
1674     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
1675         if is_named_arg(self) {
1676             let mut result = self.pat
1677                 .rewrite(context, Shape::legacy(shape.width, shape.indent))?;
1678
1679             if !is_empty_infer(context, &*self.ty) {
1680                 if context.config.space_before_colon() {
1681                     result.push_str(" ");
1682                 }
1683                 result.push_str(":");
1684                 if context.config.space_after_colon() {
1685                     result.push_str(" ");
1686                 }
1687                 let overhead = last_line_width(&result);
1688                 let max_width = shape.width.checked_sub(overhead)?;
1689                 let ty_str = self.ty
1690                     .rewrite(context, Shape::legacy(max_width, shape.indent))?;
1691                 result.push_str(&ty_str);
1692             }
1693
1694             Some(result)
1695         } else {
1696             self.ty.rewrite(context, shape)
1697         }
1698     }
1699 }
1700
1701 fn rewrite_explicit_self(
1702     explicit_self: &ast::ExplicitSelf,
1703     args: &[ast::Arg],
1704     context: &RewriteContext,
1705 ) -> Option<String> {
1706     match explicit_self.node {
1707         ast::SelfKind::Region(lt, m) => {
1708             let mut_str = format_mutability(m);
1709             match lt {
1710                 Some(ref l) => {
1711                     let lifetime_str = l.rewrite(
1712                         context,
1713                         Shape::legacy(context.config.max_width(), Indent::empty()),
1714                     )?;
1715                     Some(format!("&{} {}self", lifetime_str, mut_str))
1716                 }
1717                 None => Some(format!("&{}self", mut_str)),
1718             }
1719         }
1720         ast::SelfKind::Explicit(ref ty, _) => {
1721             assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty.");
1722
1723             let mutability = explicit_self_mutability(&args[0]);
1724             let type_str = ty.rewrite(
1725                 context,
1726                 Shape::legacy(context.config.max_width(), Indent::empty()),
1727             )?;
1728
1729             Some(format!(
1730                 "{}self: {}",
1731                 format_mutability(mutability),
1732                 type_str
1733             ))
1734         }
1735         ast::SelfKind::Value(_) => {
1736             assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty.");
1737
1738             let mutability = explicit_self_mutability(&args[0]);
1739
1740             Some(format!("{}self", format_mutability(mutability)))
1741         }
1742     }
1743 }
1744
1745 // Hacky solution caused by absence of `Mutability` in `SelfValue` and
1746 // `SelfExplicit` variants of `ast::ExplicitSelf_`.
1747 fn explicit_self_mutability(arg: &ast::Arg) -> ast::Mutability {
1748     if let ast::PatKind::Ident(ast::BindingMode::ByValue(mutability), _, _) = arg.pat.node {
1749         mutability
1750     } else {
1751         unreachable!()
1752     }
1753 }
1754
1755 pub fn span_lo_for_arg(arg: &ast::Arg) -> BytePos {
1756     if is_named_arg(arg) {
1757         arg.pat.span.lo()
1758     } else {
1759         arg.ty.span.lo()
1760     }
1761 }
1762
1763 pub fn span_hi_for_arg(context: &RewriteContext, arg: &ast::Arg) -> BytePos {
1764     match arg.ty.node {
1765         ast::TyKind::Infer if context.snippet(arg.ty.span) == "_" => arg.ty.span.hi(),
1766         ast::TyKind::Infer if is_named_arg(arg) => arg.pat.span.hi(),
1767         _ => arg.ty.span.hi(),
1768     }
1769 }
1770
1771 pub fn is_named_arg(arg: &ast::Arg) -> bool {
1772     if let ast::PatKind::Ident(_, ident, _) = arg.pat.node {
1773         ident.node != symbol::keywords::Invalid.ident()
1774     } else {
1775         true
1776     }
1777 }
1778
1779 // Return type is (result, force_new_line_for_brace)
1780 fn rewrite_fn_base(
1781     context: &RewriteContext,
1782     indent: Indent,
1783     ident: ast::Ident,
1784     fn_sig: &FnSig,
1785     span: Span,
1786     newline_brace: bool,
1787     has_body: bool,
1788 ) -> Option<(String, bool)> {
1789     let mut force_new_line_for_brace = false;
1790
1791     let where_clause = &fn_sig.generics.where_clause;
1792
1793     let mut result = String::with_capacity(1024);
1794     result.push_str(&fn_sig.to_str(context));
1795
1796     // fn foo
1797     result.push_str("fn ");
1798     result.push_str(&ident.to_string());
1799
1800     // Generics.
1801     let overhead = if has_body && !newline_brace {
1802         // 4 = `() {`
1803         4
1804     } else {
1805         // 2 = `()`
1806         2
1807     };
1808     let used_width = last_line_used_width(&result, indent.width());
1809     let one_line_budget = context.budget(used_width + overhead);
1810     let shape = Shape {
1811         width: one_line_budget,
1812         indent,
1813         offset: used_width,
1814     };
1815     let fd = fn_sig.decl;
1816     let g_span = mk_sp(span.lo(), fd.output.span().lo());
1817     let generics_str = rewrite_generics(context, fn_sig.generics, shape, g_span)?;
1818     result.push_str(&generics_str);
1819
1820     let snuggle_angle_bracket = generics_str
1821         .lines()
1822         .last()
1823         .map_or(false, |l| l.trim_left().len() == 1);
1824
1825     // Note that the width and indent don't really matter, we'll re-layout the
1826     // return type later anyway.
1827     let ret_str = fd.output
1828         .rewrite(context, Shape::indented(indent, context.config))?;
1829
1830     let multi_line_ret_str = ret_str.contains('\n');
1831     let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() };
1832
1833     // Args.
1834     let (one_line_budget, multi_line_budget, mut arg_indent) = compute_budgets_for_args(
1835         context,
1836         &result,
1837         indent,
1838         ret_str_len,
1839         newline_brace,
1840         has_body,
1841         multi_line_ret_str,
1842     )?;
1843
1844     debug!(
1845         "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}",
1846         one_line_budget, multi_line_budget, arg_indent
1847     );
1848
1849     // Check if vertical layout was forced.
1850     if one_line_budget == 0 {
1851         if snuggle_angle_bracket {
1852             result.push('(');
1853         } else {
1854             result.push_str("(");
1855             if context.config.indent_style() == IndentStyle::Visual {
1856                 result.push_str(&arg_indent.to_string_with_newline(context.config));
1857             }
1858         }
1859     } else {
1860         result.push('(');
1861     }
1862     if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty()
1863         && result.ends_with('(')
1864     {
1865         result.push(' ')
1866     }
1867
1868     // Skip `pub(crate)`.
1869     let lo_after_visibility = get_bytepos_after_visibility(&fn_sig.visibility, span);
1870     // A conservative estimation, to goal is to be over all parens in generics
1871     let args_start = fn_sig
1872         .generics
1873         .params
1874         .iter()
1875         .last()
1876         .map_or(lo_after_visibility, |param| param.span().hi());
1877     let args_end = if fd.inputs.is_empty() {
1878         context
1879             .snippet_provider
1880             .span_after(mk_sp(args_start, span.hi()), ")")
1881     } else {
1882         let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi(), span.hi());
1883         context.snippet_provider.span_after(last_span, ")")
1884     };
1885     let args_span = mk_sp(
1886         context
1887             .snippet_provider
1888             .span_after(mk_sp(args_start, span.hi()), "("),
1889         args_end,
1890     );
1891     let arg_str = rewrite_args(
1892         context,
1893         &fd.inputs,
1894         fd.get_self().as_ref(),
1895         one_line_budget,
1896         multi_line_budget,
1897         indent,
1898         arg_indent,
1899         args_span,
1900         fd.variadic,
1901         generics_str.contains('\n'),
1902     )?;
1903
1904     let put_args_in_block = match context.config.indent_style() {
1905         IndentStyle::Block => arg_str.contains('\n') || arg_str.len() > one_line_budget,
1906         _ => false,
1907     } && !fd.inputs.is_empty();
1908
1909     let mut args_last_line_contains_comment = false;
1910     if put_args_in_block {
1911         arg_indent = indent.block_indent(context.config);
1912         result.push_str(&arg_indent.to_string_with_newline(context.config));
1913         result.push_str(&arg_str);
1914         result.push_str(&indent.to_string_with_newline(context.config));
1915         result.push(')');
1916     } else {
1917         result.push_str(&arg_str);
1918         let used_width = last_line_used_width(&result, indent.width()) + first_line_width(&ret_str);
1919         // Put the closing brace on the next line if it overflows the max width.
1920         // 1 = `)`
1921         if fd.inputs.is_empty() && used_width + 1 > context.config.max_width() {
1922             result.push('\n');
1923         }
1924         if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() {
1925             result.push(' ')
1926         }
1927         // If the last line of args contains comment, we cannot put the closing paren
1928         // on the same line.
1929         if arg_str
1930             .lines()
1931             .last()
1932             .map_or(false, |last_line| last_line.contains("//"))
1933         {
1934             args_last_line_contains_comment = true;
1935             result.push_str(&arg_indent.to_string_with_newline(context.config));
1936         }
1937         result.push(')');
1938     }
1939
1940     // Return type.
1941     if let ast::FunctionRetTy::Ty(..) = fd.output {
1942         let ret_should_indent = match context.config.indent_style() {
1943             // If our args are block layout then we surely must have space.
1944             IndentStyle::Block if put_args_in_block || fd.inputs.is_empty() => false,
1945             _ if args_last_line_contains_comment => false,
1946             _ if result.contains('\n') || multi_line_ret_str => true,
1947             _ => {
1948                 // If the return type would push over the max width, then put the return type on
1949                 // a new line. With the +1 for the signature length an additional space between
1950                 // the closing parenthesis of the argument and the arrow '->' is considered.
1951                 let mut sig_length = result.len() + indent.width() + ret_str_len + 1;
1952
1953                 // If there is no where clause, take into account the space after the return type
1954                 // and the brace.
1955                 if where_clause.predicates.is_empty() {
1956                     sig_length += 2;
1957                 }
1958
1959                 sig_length > context.config.max_width()
1960             }
1961         };
1962         let ret_indent = if ret_should_indent {
1963             let indent = if arg_str.is_empty() {
1964                 // Aligning with non-existent args looks silly.
1965                 force_new_line_for_brace = true;
1966                 indent + 4
1967             } else {
1968                 // FIXME: we might want to check that using the arg indent
1969                 // doesn't blow our budget, and if it does, then fallback to
1970                 // the where clause indent.
1971                 arg_indent
1972             };
1973
1974             result.push_str(&indent.to_string_with_newline(context.config));
1975             indent
1976         } else {
1977             result.push(' ');
1978             Indent::new(indent.block_indent, last_line_width(&result))
1979         };
1980
1981         if multi_line_ret_str || ret_should_indent {
1982             // Now that we know the proper indent and width, we need to
1983             // re-layout the return type.
1984             let ret_str = fd.output
1985                 .rewrite(context, Shape::indented(ret_indent, context.config))?;
1986             result.push_str(&ret_str);
1987         } else {
1988             result.push_str(&ret_str);
1989         }
1990
1991         // Comment between return type and the end of the decl.
1992         let snippet_lo = fd.output.span().hi();
1993         if where_clause.predicates.is_empty() {
1994             let snippet_hi = span.hi();
1995             let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi));
1996             // Try to preserve the layout of the original snippet.
1997             let original_starts_with_newline = snippet
1998                 .find(|c| c != ' ')
1999                 .map_or(false, |i| starts_with_newline(&snippet[i..]));
2000             let original_ends_with_newline = snippet
2001                 .rfind(|c| c != ' ')
2002                 .map_or(false, |i| snippet[i..].ends_with('\n'));
2003             let snippet = snippet.trim();
2004             if !snippet.is_empty() {
2005                 result.push(if original_starts_with_newline {
2006                     '\n'
2007                 } else {
2008                     ' '
2009                 });
2010                 result.push_str(snippet);
2011                 if original_ends_with_newline {
2012                     force_new_line_for_brace = true;
2013                 }
2014             }
2015         }
2016     }
2017
2018     let pos_before_where = match fd.output {
2019         ast::FunctionRetTy::Default(..) => args_span.hi(),
2020         ast::FunctionRetTy::Ty(ref ty) => ty.span.hi(),
2021     };
2022
2023     let is_args_multi_lined = arg_str.contains('\n');
2024
2025     let option = WhereClauseOption::new(!has_body, put_args_in_block && ret_str.is_empty());
2026     let where_clause_str = rewrite_where_clause(
2027         context,
2028         where_clause,
2029         context.config.brace_style(),
2030         Shape::indented(indent, context.config),
2031         Density::Tall,
2032         "{",
2033         Some(span.hi()),
2034         pos_before_where,
2035         option,
2036         is_args_multi_lined,
2037     )?;
2038     // If there are neither where clause nor return type, we may be missing comments between
2039     // args and `{`.
2040     if where_clause_str.is_empty() {
2041         if let ast::FunctionRetTy::Default(ret_span) = fd.output {
2042             match recover_missing_comment_in_span(
2043                 mk_sp(args_span.hi(), ret_span.hi()),
2044                 shape,
2045                 context,
2046                 last_line_width(&result),
2047             ) {
2048                 Some(ref missing_comment) if !missing_comment.is_empty() => {
2049                     result.push_str(missing_comment);
2050                     force_new_line_for_brace = true;
2051                 }
2052                 _ => (),
2053             }
2054         }
2055     }
2056
2057     result.push_str(&where_clause_str);
2058
2059     force_new_line_for_brace |= last_line_contains_single_line_comment(&result);
2060     force_new_line_for_brace |= is_args_multi_lined && context.config.where_single_line();
2061     Some((result, force_new_line_for_brace))
2062 }
2063
2064 #[derive(Copy, Clone)]
2065 struct WhereClauseOption {
2066     suppress_comma: bool, // Force no trailing comma
2067     snuggle: bool,        // Do not insert newline before `where`
2068     compress_where: bool, // Try single line where clause instead of vertical layout
2069 }
2070
2071 impl WhereClauseOption {
2072     pub fn new(suppress_comma: bool, snuggle: bool) -> WhereClauseOption {
2073         WhereClauseOption {
2074             suppress_comma,
2075             snuggle,
2076             compress_where: false,
2077         }
2078     }
2079
2080     pub fn snuggled(current: &str) -> WhereClauseOption {
2081         WhereClauseOption {
2082             suppress_comma: false,
2083             snuggle: trimmed_last_line_width(current) == 1,
2084             compress_where: false,
2085         }
2086     }
2087 }
2088
2089 fn rewrite_args(
2090     context: &RewriteContext,
2091     args: &[ast::Arg],
2092     explicit_self: Option<&ast::ExplicitSelf>,
2093     one_line_budget: usize,
2094     multi_line_budget: usize,
2095     indent: Indent,
2096     arg_indent: Indent,
2097     span: Span,
2098     variadic: bool,
2099     generics_str_contains_newline: bool,
2100 ) -> Option<String> {
2101     let mut arg_item_strs = args.iter()
2102         .map(|arg| arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent)))
2103         .collect::<Option<Vec<_>>>()?;
2104
2105     // Account for sugary self.
2106     // FIXME: the comment for the self argument is dropped. This is blocked
2107     // on rust issue #27522.
2108     let min_args = explicit_self
2109         .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context))
2110         .map_or(1, |self_str| {
2111             arg_item_strs[0] = self_str;
2112             2
2113         });
2114
2115     // Comments between args.
2116     let mut arg_items = Vec::new();
2117     if min_args == 2 {
2118         arg_items.push(ListItem::from_str(""));
2119     }
2120
2121     // FIXME(#21): if there are no args, there might still be a comment, but
2122     // without spans for the comment or parens, there is no chance of
2123     // getting it right. You also don't get to put a comment on self, unless
2124     // it is explicit.
2125     if args.len() >= min_args || variadic {
2126         let comment_span_start = if min_args == 2 {
2127             let second_arg_start = if arg_has_pattern(&args[1]) {
2128                 args[1].pat.span.lo()
2129             } else {
2130                 args[1].ty.span.lo()
2131             };
2132             let reduced_span = mk_sp(span.lo(), second_arg_start);
2133
2134             context.snippet_provider.span_after_last(reduced_span, ",")
2135         } else {
2136             span.lo()
2137         };
2138
2139         enum ArgumentKind<'a> {
2140             Regular(&'a ast::Arg),
2141             Variadic(BytePos),
2142         }
2143
2144         let variadic_arg = if variadic {
2145             let variadic_span = mk_sp(args.last().unwrap().ty.span.hi(), span.hi());
2146             let variadic_start =
2147                 context.snippet_provider.span_after(variadic_span, "...") - BytePos(3);
2148             Some(ArgumentKind::Variadic(variadic_start))
2149         } else {
2150             None
2151         };
2152
2153         let more_items = itemize_list(
2154             context.snippet_provider,
2155             args[min_args - 1..]
2156                 .iter()
2157                 .map(ArgumentKind::Regular)
2158                 .chain(variadic_arg),
2159             ")",
2160             ",",
2161             |arg| match *arg {
2162                 ArgumentKind::Regular(arg) => span_lo_for_arg(arg),
2163                 ArgumentKind::Variadic(start) => start,
2164             },
2165             |arg| match *arg {
2166                 ArgumentKind::Regular(arg) => arg.ty.span.hi(),
2167                 ArgumentKind::Variadic(start) => start + BytePos(3),
2168             },
2169             |arg| match *arg {
2170                 ArgumentKind::Regular(..) => None,
2171                 ArgumentKind::Variadic(..) => Some("...".to_owned()),
2172             },
2173             comment_span_start,
2174             span.hi(),
2175             false,
2176         );
2177
2178         arg_items.extend(more_items);
2179     }
2180
2181     let fits_in_one_line = !generics_str_contains_newline
2182         && (arg_items.is_empty()
2183             || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget);
2184
2185     for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) {
2186         item.item = Some(arg);
2187     }
2188
2189     let last_line_ends_with_comment = arg_items
2190         .iter()
2191         .last()
2192         .and_then(|item| item.post_comment.as_ref())
2193         .map_or(false, |s| s.trim().starts_with("//"));
2194
2195     let (indent, trailing_comma) = match context.config.indent_style() {
2196         IndentStyle::Block if fits_in_one_line => {
2197             (indent.block_indent(context.config), SeparatorTactic::Never)
2198         }
2199         IndentStyle::Block => (
2200             indent.block_indent(context.config),
2201             context.config.trailing_comma(),
2202         ),
2203         IndentStyle::Visual if last_line_ends_with_comment => {
2204             (arg_indent, context.config.trailing_comma())
2205         }
2206         IndentStyle::Visual => (arg_indent, SeparatorTactic::Never),
2207     };
2208
2209     let tactic = definitive_tactic(
2210         &arg_items,
2211         context.config.fn_args_density().to_list_tactic(),
2212         Separator::Comma,
2213         one_line_budget,
2214     );
2215     let budget = match tactic {
2216         DefinitiveListTactic::Horizontal => one_line_budget,
2217         _ => multi_line_budget,
2218     };
2219
2220     debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic);
2221
2222     let fmt = ListFormatting {
2223         tactic,
2224         separator: ",",
2225         trailing_separator: if variadic {
2226             SeparatorTactic::Never
2227         } else {
2228             trailing_comma
2229         },
2230         separator_place: SeparatorPlace::Back,
2231         shape: Shape::legacy(budget, indent),
2232         ends_with_newline: tactic.ends_with_newline(context.config.indent_style()),
2233         preserve_newline: true,
2234         config: context.config,
2235     };
2236
2237     write_list(&arg_items, &fmt)
2238 }
2239
2240 fn arg_has_pattern(arg: &ast::Arg) -> bool {
2241     if let ast::PatKind::Ident(_, ident, _) = arg.pat.node {
2242         ident.node != symbol::keywords::Invalid.ident()
2243     } else {
2244         true
2245     }
2246 }
2247
2248 fn compute_budgets_for_args(
2249     context: &RewriteContext,
2250     result: &str,
2251     indent: Indent,
2252     ret_str_len: usize,
2253     newline_brace: bool,
2254     has_braces: bool,
2255     force_vertical_layout: bool,
2256 ) -> Option<((usize, usize, Indent))> {
2257     debug!(
2258         "compute_budgets_for_args {} {:?}, {}, {}",
2259         result.len(),
2260         indent,
2261         ret_str_len,
2262         newline_brace
2263     );
2264     // Try keeping everything on the same line.
2265     if !result.contains('\n') && !force_vertical_layout {
2266         // 2 = `()`, 3 = `() `, space is before ret_string.
2267         let overhead = if ret_str_len == 0 { 2 } else { 3 };
2268         let mut used_space = indent.width() + result.len() + ret_str_len + overhead;
2269         if has_braces {
2270             if !newline_brace {
2271                 // 2 = `{}`
2272                 used_space += 2;
2273             }
2274         } else {
2275             // 1 = `;`
2276             used_space += 1;
2277         }
2278         let one_line_budget = context.budget(used_space);
2279
2280         if one_line_budget > 0 {
2281             // 4 = "() {".len()
2282             let (indent, multi_line_budget) = match context.config.indent_style() {
2283                 IndentStyle::Block => {
2284                     let indent = indent.block_indent(context.config);
2285                     (indent, context.budget(indent.width() + 1))
2286                 }
2287                 IndentStyle::Visual => {
2288                     let indent = indent + result.len() + 1;
2289                     let multi_line_overhead = indent.width() + if newline_brace { 2 } else { 4 };
2290                     (indent, context.budget(multi_line_overhead))
2291                 }
2292             };
2293
2294             return Some((one_line_budget, multi_line_budget, indent));
2295         }
2296     }
2297
2298     // Didn't work. we must force vertical layout and put args on a newline.
2299     let new_indent = indent.block_indent(context.config);
2300     let used_space = match context.config.indent_style() {
2301         // 1 = `,`
2302         IndentStyle::Block => new_indent.width() + 1,
2303         // Account for `)` and possibly ` {`.
2304         IndentStyle::Visual => new_indent.width() + if ret_str_len == 0 { 1 } else { 3 },
2305     };
2306     Some((0, context.budget(used_space), new_indent))
2307 }
2308
2309 fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool {
2310     let predicate_count = where_clause.predicates.len();
2311
2312     if config.where_single_line() && predicate_count == 1 {
2313         return false;
2314     }
2315     let brace_style = config.brace_style();
2316
2317     brace_style == BraceStyle::AlwaysNextLine
2318         || (brace_style == BraceStyle::SameLineWhere && predicate_count > 0)
2319 }
2320
2321 fn rewrite_generics(
2322     context: &RewriteContext,
2323     generics: &ast::Generics,
2324     shape: Shape,
2325     span: Span,
2326 ) -> Option<String> {
2327     let g_shape = generics_shape_from_config(context.config, shape, 0)?;
2328     let one_line_width = shape.width.checked_sub(2).unwrap_or(0);
2329     rewrite_generics_inner(context, generics, g_shape, one_line_width, span)
2330         .or_else(|| rewrite_generics_inner(context, generics, g_shape, 0, span))
2331 }
2332
2333 fn rewrite_generics_inner(
2334     context: &RewriteContext,
2335     generics: &ast::Generics,
2336     shape: Shape,
2337     one_line_width: usize,
2338     span: Span,
2339 ) -> Option<String> {
2340     // FIXME: convert bounds to where clauses where they get too big or if
2341     // there is a where clause at all.
2342
2343     if generics.params.is_empty() {
2344         return Some(String::new());
2345     }
2346
2347     let items = itemize_list(
2348         context.snippet_provider,
2349         generics.params.iter(),
2350         ">",
2351         ",",
2352         |arg| arg.span().lo(),
2353         |arg| arg.span().hi(),
2354         |arg| arg.rewrite(context, shape),
2355         context.snippet_provider.span_after(span, "<"),
2356         span.hi(),
2357         false,
2358     );
2359     format_generics_item_list(context, items, shape, one_line_width)
2360 }
2361
2362 pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option<Shape> {
2363     match config.indent_style() {
2364         IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width(offset + 2),
2365         IndentStyle::Block => {
2366             // 1 = ","
2367             shape
2368                 .block()
2369                 .block_indent(config.tab_spaces())
2370                 .with_max_width(config)
2371                 .sub_width(1)
2372         }
2373     }
2374 }
2375
2376 pub fn format_generics_item_list<I>(
2377     context: &RewriteContext,
2378     items: I,
2379     shape: Shape,
2380     one_line_budget: usize,
2381 ) -> Option<String>
2382 where
2383     I: Iterator<Item = ListItem>,
2384 {
2385     let item_vec = items.collect::<Vec<_>>();
2386
2387     let tactic = definitive_tactic(
2388         &item_vec,
2389         ListTactic::HorizontalVertical,
2390         Separator::Comma,
2391         one_line_budget,
2392     );
2393     let fmt = ListFormatting {
2394         tactic,
2395         separator: ",",
2396         trailing_separator: if context.config.indent_style() == IndentStyle::Visual {
2397             SeparatorTactic::Never
2398         } else {
2399             context.config.trailing_comma()
2400         },
2401         separator_place: SeparatorPlace::Back,
2402         shape,
2403         ends_with_newline: tactic.ends_with_newline(context.config.indent_style()),
2404         preserve_newline: true,
2405         config: context.config,
2406     };
2407
2408     let list_str = write_list(&item_vec, &fmt)?;
2409
2410     Some(wrap_generics_with_angle_brackets(
2411         context,
2412         &list_str,
2413         shape.indent,
2414     ))
2415 }
2416
2417 pub fn wrap_generics_with_angle_brackets(
2418     context: &RewriteContext,
2419     list_str: &str,
2420     list_offset: Indent,
2421 ) -> String {
2422     if context.config.indent_style() == IndentStyle::Block
2423         && (list_str.contains('\n') || list_str.ends_with(','))
2424     {
2425         format!(
2426             "<\n{}{}\n{}>",
2427             list_offset.to_string(context.config),
2428             list_str,
2429             list_offset
2430                 .block_unindent(context.config)
2431                 .to_string(context.config)
2432         )
2433     } else if context.config.spaces_within_parens_and_brackets() {
2434         format!("< {} >", list_str)
2435     } else {
2436         format!("<{}>", list_str)
2437     }
2438 }
2439
2440 fn rewrite_trait_bounds(
2441     context: &RewriteContext,
2442     bounds: &[ast::TyParamBound],
2443     shape: Shape,
2444 ) -> Option<String> {
2445     if bounds.is_empty() {
2446         return Some(String::new());
2447     }
2448     let bound_str = bounds
2449         .iter()
2450         .map(|ty_bound| ty_bound.rewrite(context, shape))
2451         .collect::<Option<Vec<_>>>()?;
2452     Some(format!(": {}", join_bounds(context, shape, &bound_str)))
2453 }
2454
2455 fn rewrite_where_clause_rfc_style(
2456     context: &RewriteContext,
2457     where_clause: &ast::WhereClause,
2458     shape: Shape,
2459     terminator: &str,
2460     span_end: Option<BytePos>,
2461     span_end_before_where: BytePos,
2462     where_clause_option: WhereClauseOption,
2463     is_args_multi_line: bool,
2464 ) -> Option<String> {
2465     let block_shape = shape.block().with_max_width(context.config);
2466
2467     let (span_before, span_after) =
2468         missing_span_before_after_where(span_end_before_where, where_clause);
2469     let (comment_before, comment_after) =
2470         rewrite_comments_before_after_where(context, span_before, span_after, shape)?;
2471
2472     let starting_newline = if where_clause_option.snuggle && comment_before.is_empty() {
2473         Cow::from(" ")
2474     } else {
2475         block_shape.indent.to_string_with_newline(context.config)
2476     };
2477
2478     let clause_shape = block_shape.block_left(context.config.tab_spaces())?;
2479     // 1 = `,`
2480     let clause_shape = clause_shape.sub_width(1)?;
2481     // each clause on one line, trailing comma (except if suppress_comma)
2482     let span_start = where_clause.predicates[0].span().lo();
2483     // If we don't have the start of the next span, then use the end of the
2484     // predicates, but that means we miss comments.
2485     let len = where_clause.predicates.len();
2486     let end_of_preds = where_clause.predicates[len - 1].span().hi();
2487     let span_end = span_end.unwrap_or(end_of_preds);
2488     let items = itemize_list(
2489         context.snippet_provider,
2490         where_clause.predicates.iter(),
2491         terminator,
2492         ",",
2493         |pred| pred.span().lo(),
2494         |pred| pred.span().hi(),
2495         |pred| pred.rewrite(context, clause_shape),
2496         span_start,
2497         span_end,
2498         false,
2499     );
2500     let where_single_line = context.config.where_single_line() && len == 1 && !is_args_multi_line;
2501     let comma_tactic = if where_clause_option.suppress_comma || where_single_line {
2502         SeparatorTactic::Never
2503     } else {
2504         context.config.trailing_comma()
2505     };
2506
2507     // shape should be vertical only and only if we have `where_single_line` option enabled
2508     // and the number of items of the where clause is equal to 1
2509     let shape_tactic = if where_single_line {
2510         DefinitiveListTactic::Horizontal
2511     } else {
2512         DefinitiveListTactic::Vertical
2513     };
2514
2515     let fmt = ListFormatting {
2516         tactic: shape_tactic,
2517         separator: ",",
2518         trailing_separator: comma_tactic,
2519         separator_place: SeparatorPlace::Back,
2520         shape: clause_shape,
2521         ends_with_newline: true,
2522         preserve_newline: true,
2523         config: context.config,
2524     };
2525     let preds_str = write_list(&items.collect::<Vec<_>>(), &fmt)?;
2526
2527     let comment_separator = |comment: &str, shape: Shape| {
2528         if comment.is_empty() {
2529             Cow::from("")
2530         } else {
2531             shape.indent.to_string_with_newline(context.config)
2532         }
2533     };
2534     let newline_before_where = comment_separator(&comment_before, shape);
2535     let newline_after_where = comment_separator(&comment_after, clause_shape);
2536
2537     // 6 = `where `
2538     let clause_sep = if where_clause_option.compress_where && comment_before.is_empty()
2539         && comment_after.is_empty() && !preds_str.contains('\n')
2540         && 6 + preds_str.len() <= shape.width || where_single_line
2541     {
2542         Cow::from(" ")
2543     } else {
2544         clause_shape.indent.to_string_with_newline(context.config)
2545     };
2546     Some(format!(
2547         "{}{}{}where{}{}{}{}",
2548         starting_newline,
2549         comment_before,
2550         newline_before_where,
2551         newline_after_where,
2552         comment_after,
2553         clause_sep,
2554         preds_str
2555     ))
2556 }
2557
2558 fn rewrite_where_clause(
2559     context: &RewriteContext,
2560     where_clause: &ast::WhereClause,
2561     brace_style: BraceStyle,
2562     shape: Shape,
2563     density: Density,
2564     terminator: &str,
2565     span_end: Option<BytePos>,
2566     span_end_before_where: BytePos,
2567     where_clause_option: WhereClauseOption,
2568     is_args_multi_line: bool,
2569 ) -> Option<String> {
2570     if where_clause.predicates.is_empty() {
2571         return Some(String::new());
2572     }
2573
2574     if context.config.indent_style() == IndentStyle::Block {
2575         return rewrite_where_clause_rfc_style(
2576             context,
2577             where_clause,
2578             shape,
2579             terminator,
2580             span_end,
2581             span_end_before_where,
2582             where_clause_option,
2583             is_args_multi_line,
2584         );
2585     }
2586
2587     let extra_indent = Indent::new(context.config.tab_spaces(), 0);
2588
2589     let offset = match context.config.indent_style() {
2590         IndentStyle::Block => shape.indent + extra_indent.block_indent(context.config),
2591         // 6 = "where ".len()
2592         IndentStyle::Visual => shape.indent + extra_indent + 6,
2593     };
2594     // FIXME: if indent_style != Visual, then the budgets below might
2595     // be out by a char or two.
2596
2597     let budget = context.config.max_width() - offset.width();
2598     let span_start = where_clause.predicates[0].span().lo();
2599     // If we don't have the start of the next span, then use the end of the
2600     // predicates, but that means we miss comments.
2601     let len = where_clause.predicates.len();
2602     let end_of_preds = where_clause.predicates[len - 1].span().hi();
2603     let span_end = span_end.unwrap_or(end_of_preds);
2604     let items = itemize_list(
2605         context.snippet_provider,
2606         where_clause.predicates.iter(),
2607         terminator,
2608         ",",
2609         |pred| pred.span().lo(),
2610         |pred| pred.span().hi(),
2611         |pred| pred.rewrite(context, Shape::legacy(budget, offset)),
2612         span_start,
2613         span_end,
2614         false,
2615     );
2616     let item_vec = items.collect::<Vec<_>>();
2617     // FIXME: we don't need to collect here
2618     let tactic = definitive_tactic(&item_vec, ListTactic::Vertical, Separator::Comma, budget);
2619
2620     let mut comma_tactic = context.config.trailing_comma();
2621     // Kind of a hack because we don't usually have trailing commas in where clauses.
2622     if comma_tactic == SeparatorTactic::Vertical || where_clause_option.suppress_comma {
2623         comma_tactic = SeparatorTactic::Never;
2624     }
2625
2626     let fmt = ListFormatting {
2627         tactic,
2628         separator: ",",
2629         trailing_separator: comma_tactic,
2630         separator_place: SeparatorPlace::Back,
2631         shape: Shape::legacy(budget, offset),
2632         ends_with_newline: tactic.ends_with_newline(context.config.indent_style()),
2633         preserve_newline: true,
2634         config: context.config,
2635     };
2636     let preds_str = write_list(&item_vec, &fmt)?;
2637
2638     let end_length = if terminator == "{" {
2639         // If the brace is on the next line we don't need to count it otherwise it needs two
2640         // characters " {"
2641         match brace_style {
2642             BraceStyle::AlwaysNextLine | BraceStyle::SameLineWhere => 0,
2643             BraceStyle::PreferSameLine => 2,
2644         }
2645     } else if terminator == "=" {
2646         2
2647     } else {
2648         terminator.len()
2649     };
2650     if density == Density::Tall || preds_str.contains('\n')
2651         || shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width
2652     {
2653         Some(format!(
2654             "\n{}where {}",
2655             (shape.indent + extra_indent).to_string(context.config),
2656             preds_str
2657         ))
2658     } else {
2659         Some(format!(" where {}", preds_str))
2660     }
2661 }
2662
2663 fn missing_span_before_after_where(
2664     before_item_span_end: BytePos,
2665     where_clause: &ast::WhereClause,
2666 ) -> (Span, Span) {
2667     let missing_span_before = mk_sp(before_item_span_end, where_clause.span.lo());
2668     // 5 = `where`
2669     let pos_after_where = where_clause.span.lo() + BytePos(5);
2670     let missing_span_after = mk_sp(pos_after_where, where_clause.predicates[0].span().lo());
2671     (missing_span_before, missing_span_after)
2672 }
2673
2674 fn rewrite_comments_before_after_where(
2675     context: &RewriteContext,
2676     span_before_where: Span,
2677     span_after_where: Span,
2678     shape: Shape,
2679 ) -> Option<(String, String)> {
2680     let before_comment = rewrite_missing_comment(span_before_where, shape, context)?;
2681     let after_comment = rewrite_missing_comment(
2682         span_after_where,
2683         shape.block_indent(context.config.tab_spaces()),
2684         context,
2685     )?;
2686     Some((before_comment, after_comment))
2687 }
2688
2689 fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String {
2690     format!("{}{}{}", format_visibility(vis), item_name, ident)
2691 }
2692
2693 #[derive(PartialEq, Eq, Clone, Copy)]
2694 enum BracePos {
2695     None,
2696     Auto,
2697     ForceSameLine,
2698 }
2699
2700 fn format_generics(
2701     context: &RewriteContext,
2702     generics: &ast::Generics,
2703     brace_style: BraceStyle,
2704     brace_pos: BracePos,
2705     offset: Indent,
2706     span: Span,
2707     used_width: usize,
2708 ) -> Option<String> {
2709     let shape = Shape::legacy(context.budget(used_width + offset.width()), offset);
2710     let mut result = rewrite_generics(context, generics, shape, span)?;
2711
2712     let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') {
2713         let budget = context.budget(last_line_used_width(&result, offset.width()));
2714         let mut option = WhereClauseOption::snuggled(&result);
2715         if brace_pos == BracePos::None {
2716             option.suppress_comma = true;
2717         }
2718         // If the generics are not parameterized then generics.span.hi() == 0,
2719         // so we use span.lo(), which is the position after `struct Foo`.
2720         let span_end_before_where = if generics.is_parameterized() {
2721             generics.span.hi()
2722         } else {
2723             span.lo()
2724         };
2725         let where_clause_str = rewrite_where_clause(
2726             context,
2727             &generics.where_clause,
2728             brace_style,
2729             Shape::legacy(budget, offset.block_only()),
2730             Density::Tall,
2731             "{",
2732             Some(span.hi()),
2733             span_end_before_where,
2734             option,
2735             false,
2736         )?;
2737         result.push_str(&where_clause_str);
2738         brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine
2739             || (generics.where_clause.predicates.is_empty()
2740                 && trimmed_last_line_width(&result) == 1)
2741     } else {
2742         brace_pos == BracePos::ForceSameLine || trimmed_last_line_width(&result) == 1
2743             || brace_style != BraceStyle::AlwaysNextLine
2744     };
2745     if brace_pos == BracePos::None {
2746         return Some(result);
2747     }
2748     let total_used_width = last_line_used_width(&result, used_width);
2749     let remaining_budget = context.budget(total_used_width);
2750     // If the same line brace if forced, it indicates that we are rewriting an item with empty body,
2751     // and hence we take the closer into account as well for one line budget.
2752     // We assume that the closer has the same length as the opener.
2753     let overhead = if brace_pos == BracePos::ForceSameLine {
2754         // 3 = ` {}`
2755         3
2756     } else {
2757         // 2 = ` {`
2758         2
2759     };
2760     let forbid_same_line_brace = overhead > remaining_budget;
2761     if !forbid_same_line_brace && same_line_brace {
2762         result.push(' ');
2763     } else {
2764         result.push('\n');
2765         result.push_str(&offset.block_only().to_string(context.config));
2766     }
2767     result.push('{');
2768
2769     Some(result)
2770 }
2771
2772 impl Rewrite for ast::ForeignItem {
2773     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
2774         let attrs_str = self.attrs.rewrite(context, shape)?;
2775         // Drop semicolon or it will be interpreted as comment.
2776         // FIXME: this may be a faulty span from libsyntax.
2777         let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1));
2778
2779         let item_str = match self.node {
2780             ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => {
2781                 rewrite_fn_base(
2782                     context,
2783                     shape.indent,
2784                     self.ident,
2785                     &FnSig::new(fn_decl, generics, self.vis.clone()),
2786                     span,
2787                     false,
2788                     false,
2789                 ).map(|(s, _)| format!("{};", s))
2790             }
2791             ast::ForeignItemKind::Static(ref ty, is_mutable) => {
2792                 // FIXME(#21): we're dropping potential comments in between the
2793                 // function keywords here.
2794                 let vis = format_visibility(&self.vis);
2795                 let mut_str = if is_mutable { "mut " } else { "" };
2796                 let prefix = format!("{}static {}{}:", vis, mut_str, self.ident);
2797                 // 1 = ;
2798                 let shape = shape.sub_width(1)?;
2799                 ty.rewrite(context, shape).map(|ty_str| {
2800                     // 1 = space between prefix and type.
2801                     let sep = if prefix.len() + ty_str.len() + 1 <= shape.width {
2802                         Cow::from(" ")
2803                     } else {
2804                         let nested_indent = shape.indent.block_indent(context.config);
2805                         nested_indent.to_string_with_newline(context.config)
2806                     };
2807                     format!("{}{}{};", prefix, sep, ty_str)
2808                 })
2809             }
2810             ast::ForeignItemKind::Ty => {
2811                 let vis = format_visibility(&self.vis);
2812                 Some(format!("{}type {};", vis, self.ident))
2813             }
2814         }?;
2815
2816         let missing_span = if self.attrs.is_empty() {
2817             mk_sp(self.span.lo(), self.span.lo())
2818         } else {
2819             mk_sp(self.attrs[self.attrs.len() - 1].span.hi(), self.span.lo())
2820         };
2821         combine_strs_with_missing_comments(
2822             context,
2823             &attrs_str,
2824             &item_str,
2825             missing_span,
2826             shape,
2827             false,
2828         )
2829     }
2830 }
2831
2832 impl Rewrite for ast::GenericParam {
2833     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
2834         match *self {
2835             ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.rewrite(context, shape),
2836             ast::GenericParam::Type(ref ty) => ty.rewrite(context, shape),
2837         }
2838     }
2839 }
2840
2841 /// Rewrite an inline mod.
2842 pub fn rewrite_mod(item: &ast::Item) -> String {
2843     let mut result = String::with_capacity(32);
2844     result.push_str(&*format_visibility(&item.vis));
2845     result.push_str("mod ");
2846     result.push_str(&item.ident.to_string());
2847     result.push(';');
2848     result
2849 }
2850
2851 /// Rewrite `extern crate foo;` WITHOUT attributes.
2852 pub fn rewrite_extern_crate(context: &RewriteContext, item: &ast::Item) -> Option<String> {
2853     assert!(is_extern_crate(item));
2854     let new_str = context.snippet(item.span);
2855     Some(if contains_comment(new_str) {
2856         new_str.to_owned()
2857     } else {
2858         let no_whitespace = &new_str.split_whitespace().collect::<Vec<&str>>().join(" ");
2859         String::from(&*Regex::new(r"\s;").unwrap().replace(no_whitespace, ";"))
2860     })
2861 }
2862
2863 /// Returns true for `mod foo;`, false for `mod foo { .. }`.
2864 pub fn is_mod_decl(item: &ast::Item) -> bool {
2865     match item.node {
2866         ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(),
2867         _ => false,
2868     }
2869 }
2870
2871 pub fn is_use_item(item: &ast::Item) -> bool {
2872     match item.node {
2873         ast::ItemKind::Use(_) => true,
2874         _ => false,
2875     }
2876 }
2877
2878 pub fn is_extern_crate(item: &ast::Item) -> bool {
2879     match item.node {
2880         ast::ItemKind::ExternCrate(..) => true,
2881         _ => false,
2882     }
2883 }