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