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