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