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