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