]> git.lizzy.rs Git - rust.git/blobdiff - src/items.rs
Cargo clippy
[rust.git] / src / items.rs
index 989793cb6ba887fabe891882c7472a6712bab516..7771344f3dbfea382ec6718db566279856d6b132 100644 (file)
@@ -22,8 +22,8 @@
 use codemap::{LineRangeUtils, SpanUtils};
 use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed,
               recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented};
-use config::{BraceStyle, Config, Density, IndentStyle, ReturnIndent, Style};
-use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs,
+use config::{BraceStyle, Config, Density, IndentStyle};
+use expr::{choose_rhs, format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs,
            rewrite_call_inner, ExprType};
 use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting,
             ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic};
 use visitor::FmtVisitor;
 
 fn type_annotation_separator(config: &Config) -> &str {
-    colon_spaces(
-        config.space_before_type_annotation(),
-        config.space_after_type_annotation_colon(),
-    )
+    colon_spaces(config.space_before_colon(), config.space_after_colon())
 }
 
 // Statements of the form
@@ -51,9 +48,7 @@ impl Rewrite for ast::Local {
     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
         debug!(
             "Local::rewrite {:?} {} {:?}",
-            self,
-            shape.width,
-            shape.indent
+            self, shape.width, shape.indent
         );
 
         skip_out_of_file_lines_range!(context, self.span);
@@ -114,7 +109,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
             // 1 = trailing semicolon;
             let nested_shape = shape.sub_width(1)?;
 
-            result = rewrite_assign_rhs(context, result, ex, nested_shape)?;
+            result = rewrite_assign_rhs(context, result, &**ex, nested_shape)?;
         }
 
         result.push(';');
@@ -215,7 +210,7 @@ pub fn from_fn_kind(
                 unsafety: unsafety,
                 visibility: visibility.clone(),
             },
-            visit::FnKind::Method(_, ref method_sig, vis, _) => {
+            visit::FnKind::Method(_, method_sig, vis, _) => {
                 let mut fn_sig = FnSig::from_method_sig(method_sig, generics);
                 fn_sig.defaultness = defualtness;
                 if let Some(vis) = vis {
@@ -244,13 +239,13 @@ fn to_str(&self, context: &RewriteContext) -> String {
 }
 
 impl<'a> FmtVisitor<'a> {
-    fn format_item(&mut self, item: Item) {
+    fn format_item(&mut self, item: &Item) {
         self.buffer.push_str(&item.abi);
 
         let snippet = self.snippet(item.span);
         let brace_pos = snippet.find_uncommented("{").unwrap();
 
-        self.buffer.push_str("{");
+        self.push_str("{");
         if !item.body.is_empty() || contains_comment(&snippet[brace_pos..]) {
             // FIXME: this skips comments between the extern keyword and the opening
             // brace.
@@ -260,9 +255,8 @@ fn format_item(&mut self, item: Item) {
             if item.body.is_empty() {
                 self.format_missing_no_indent(item.span.hi() - BytePos(1));
                 self.block_indent = self.block_indent.block_unindent(self.config);
-
-                self.buffer
-                    .push_str(&self.block_indent.to_string(self.config));
+                let indent_str = self.block_indent.to_string(self.config);
+                self.push_str(&indent_str);
             } else {
                 for item in &item.body {
                     self.format_body_element(item);
@@ -273,7 +267,7 @@ fn format_item(&mut self, item: Item) {
             }
         }
 
-        self.buffer.push_str("}");
+        self.push_str("}");
         self.last_pos = item.span.hi();
     }
 
@@ -285,10 +279,9 @@ fn format_body_element(&mut self, element: &BodyElement) {
 
     pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) {
         let item = Item::from_foreign_mod(fm, span, self.config);
-        self.format_item(item);
+        self.format_item(&item);
     }
 
-
     fn format_foreign_item(&mut self, item: &ast::ForeignItem) {
         let rewrite = item.rewrite(&self.get_context(), self.shape());
         self.push_rewrite(item.span(), rewrite);
@@ -305,18 +298,15 @@ pub fn rewrite_fn(
     ) -> Option<String> {
         let context = self.get_context();
 
-        let has_body =
-            !is_empty_block(block, self.codemap) || !context.config.fn_empty_single_line();
-        let mut newline_brace =
-            newline_for_brace(self.config, &fn_sig.generics.where_clause, has_body);
+        let mut newline_brace = newline_for_brace(self.config, &fn_sig.generics.where_clause);
 
         let (mut result, force_newline_brace) =
             rewrite_fn_base(&context, indent, ident, fn_sig, span, newline_brace, true)?;
 
-        if self.config.fn_brace_style() == BraceStyle::AlwaysNextLine || force_newline_brace {
-            newline_brace = true;
-        } else if last_line_width(&result) + 2 > self.shape().width {
-            // 2 = ` {`
+        // 2 = ` {`
+        if self.config.brace_style() == BraceStyle::AlwaysNextLine || force_newline_brace
+            || last_line_width(&result) + 2 > self.shape().width
+        {
             newline_brace = true;
         } else if !result.contains('\n') {
             newline_brace = false;
@@ -372,7 +362,7 @@ fn single_line_fn(&self, fn_str: &str, block: &ast::Block) -> Option<String> {
 
         let codemap = self.get_context().codemap;
 
-        if self.config.fn_empty_single_line() && is_empty_block(block, codemap)
+        if self.config.empty_item_single_line() && is_empty_block(block, codemap)
             && self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width()
         {
             return Some(format!("{}{{}}", fn_str));
@@ -391,7 +381,7 @@ fn single_line_fn(&self, fn_str: &str, block: &ast::Block) -> Option<String> {
 
                             format_expr(e, ExprType::Statement, &self.get_context(), self.shape())
                                 .map(|s| s + suffix)
-                                .or_else(|| Some(self.snippet(e.span)))
+                                .or_else(|| Some(self.snippet(e.span).to_owned()))
                         }
                         None => stmt.rewrite(&self.get_context(), self.shape()),
                     }
@@ -411,6 +401,18 @@ fn single_line_fn(&self, fn_str: &str, block: &ast::Block) -> Option<String> {
         None
     }
 
+    pub fn visit_static(&mut self, static_parts: &StaticParts) {
+        let rewrite = rewrite_static(&self.get_context(), static_parts, self.block_indent);
+        self.push_rewrite(static_parts.span, rewrite);
+    }
+
+    pub fn visit_struct(&mut self, struct_parts: &StructParts) {
+        let is_tuple = struct_parts.def.is_tuple();
+        let rewrite = format_struct(&self.get_context(), struct_parts, self.block_indent, None)
+            .map(|s| if is_tuple { s + ";" } else { s });
+        self.push_rewrite(struct_parts.span, rewrite);
+    }
+
     pub fn visit_enum(
         &mut self,
         ident: ast::Ident,
@@ -420,7 +422,7 @@ pub fn visit_enum(
         span: Span,
     ) {
         let enum_header = format_header("enum ", ident, vis);
-        self.buffer.push_str(&enum_header);
+        self.push_str(&enum_header);
 
         let enum_snippet = self.snippet(span);
         let brace_pos = enum_snippet.find_uncommented("{").unwrap();
@@ -428,33 +430,33 @@ pub fn visit_enum(
         let generics_str = format_generics(
             &self.get_context(),
             generics,
-            "{",
-            "{",
-            self.config.item_brace_style(),
-            enum_def.variants.is_empty(),
+            self.config.brace_style(),
+            if enum_def.variants.is_empty() {
+                BracePos::ForceSameLine
+            } else {
+                BracePos::Auto
+            },
             self.block_indent,
             mk_sp(span.lo(), body_start),
             last_line_width(&enum_header),
         ).unwrap();
-        self.buffer.push_str(&generics_str);
+        self.push_str(&generics_str);
 
         self.last_pos = body_start;
 
         self.block_indent = self.block_indent.block_indent(self.config);
         let variant_list = self.format_variant_list(enum_def, body_start, span.hi() - BytePos(1));
         match variant_list {
-            Some(ref body_str) => self.buffer.push_str(body_str),
-            None => if contains_comment(&enum_snippet[brace_pos..]) {
-                self.format_missing_no_indent(span.hi() - BytePos(1))
-            },
+            Some(ref body_str) => self.push_str(body_str),
+            None => self.format_missing_no_indent(span.hi() - BytePos(1)),
         }
         self.block_indent = self.block_indent.block_unindent(self.config);
 
         if variant_list.is_some() || contains_comment(&enum_snippet[brace_pos..]) {
-            self.buffer
-                .push_str(&self.block_indent.to_string(self.config));
+            let indent_str = self.block_indent.to_string(self.config);
+            self.push_str(&indent_str);
         }
-        self.buffer.push_str("}");
+        self.push_str("}");
         self.last_pos = span.hi();
     }
 
@@ -473,21 +475,34 @@ fn format_variant_list(
         let indentation = self.block_indent.to_string(self.config);
         result.push_str(&indentation);
 
-        let items = itemize_list(
-            self.codemap,
-            enum_def.variants.iter(),
-            "}",
-            |f| if !f.node.attrs.is_empty() {
-                f.node.attrs[0].span.lo()
-            } else {
-                f.span.lo()
-            },
-            |f| f.span.hi(),
-            |f| self.format_variant(f),
-            body_lo,
-            body_hi,
-            false,
-        );
+        let itemize_list_with = |one_line_width: usize| {
+            itemize_list(
+                self.codemap,
+                enum_def.variants.iter(),
+                "}",
+                ",",
+                |f| {
+                    if !f.node.attrs.is_empty() {
+                        f.node.attrs[0].span.lo()
+                    } else {
+                        f.span.lo()
+                    }
+                },
+                |f| f.span.hi(),
+                |f| self.format_variant(f, one_line_width),
+                body_lo,
+                body_hi,
+                false,
+            ).collect()
+        };
+        let mut items: Vec<_> =
+            itemize_list_with(self.config.width_heuristics().struct_variant_width);
+        // If one of the variants use multiple lines, use multi-lined formatting for all variants.
+        let has_multiline_variant = items.iter().any(|item| item.inner_as_ref().contains('\n'));
+        let has_single_line_variant = items.iter().any(|item| !item.inner_as_ref().contains('\n'));
+        if has_multiline_variant && has_single_line_variant {
+            items = itemize_list_with(0);
+        }
 
         let shape = self.shape().sub_width(2).unwrap();
         let fmt = ListFormatting {
@@ -501,23 +516,23 @@ fn format_variant_list(
             config: self.config,
         };
 
-        let list = write_list(&items.collect::<Vec<_>>(), &fmt)?;
+        let list = write_list(&items, &fmt)?;
         result.push_str(&list);
         result.push('\n');
         Some(result)
     }
 
     // Variant of an enum.
-    fn format_variant(&self, field: &ast::Variant) -> Option<String> {
+    fn format_variant(&self, field: &ast::Variant, one_line_width: usize) -> Option<String> {
         if contains_skip(&field.node.attrs) {
             let lo = field.node.attrs[0].span.lo();
             let span = mk_sp(lo, field.span.hi());
-            return Some(self.snippet(span));
+            return Some(self.snippet(span).to_owned());
         }
 
         let context = self.get_context();
-        let indent = self.block_indent;
-        let shape = self.shape();
+        // 1 = ','
+        let shape = self.shape().sub_width(1)?;
         let attrs_str = field.node.attrs.rewrite(&context, shape)?;
         let lo = field
             .node
@@ -527,32 +542,24 @@ fn format_variant(&self, field: &ast::Variant) -> Option<String> {
         let span = mk_sp(lo, field.span.lo());
 
         let variant_body = match field.node.data {
-            ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => {
-                // FIXME: Should limit the width, as we have a trailing comma
-                format_struct(
-                    &context,
-                    "",
-                    field.node.name,
-                    &ast::Visibility::Inherited,
-                    &field.node.data,
-                    None,
-                    field.span,
-                    indent,
-                    Some(self.config.struct_variant_width()),
-                )?
+            ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => format_struct(
+                &context,
+                &StructParts::from_variant(field),
+                self.block_indent,
+                Some(one_line_width),
+            )?,
+            ast::VariantData::Unit(..) => {
+                if let Some(ref expr) = field.node.disr_expr {
+                    let lhs = format!("{} =", field.node.name);
+                    rewrite_assign_rhs(&context, lhs, &**expr, shape)?
+                } else {
+                    field.node.name.to_string()
+                }
             }
-            ast::VariantData::Unit(..) => if let Some(ref expr) = field.node.disr_expr {
-                let lhs = format!("{} =", field.node.name);
-                // 1 = ','
-                rewrite_assign_rhs(&context, lhs, expr, shape.sub_width(1)?)?
-            } else {
-                String::from(field.node.name.to_string())
-            },
         };
 
         let attrs_extendable = attrs_str.is_empty()
-            || (context.config.attributes_on_same_line_as_variant()
-                && is_attributes_extendable(&attrs_str));
+            || (context.config.same_line_attributes() && is_attributes_extendable(&attrs_str));
         combine_strs_with_missing_comments(
             &context,
             &attrs_str,
@@ -586,9 +593,9 @@ pub fn format_impl(
         let where_clause_str = rewrite_where_clause(
             context,
             &generics.where_clause,
-            context.config.item_brace_style(),
+            context.config.brace_style(),
             Shape::legacy(where_budget, offset.block_only()),
-            context.config.where_density(),
+            Density::Vertical,
             "{",
             where_span_end,
             self_ty.span.hi(),
@@ -632,15 +639,17 @@ pub fn format_impl(
         }
         result.push_str(&where_clause_str);
 
-        match context.config.item_brace_style() {
+        match context.config.brace_style() {
             _ if last_line_contains_single_line_comment(&result) => result.push_str(&sep),
             BraceStyle::AlwaysNextLine => result.push_str(&sep),
             BraceStyle::PreferSameLine => result.push(' '),
-            BraceStyle::SameLineWhere => if !where_clause_str.is_empty() {
-                result.push_str(&sep);
-            } else {
-                result.push(' ');
-            },
+            BraceStyle::SameLineWhere => {
+                if !where_clause_str.is_empty() {
+                    result.push_str(&sep);
+                } else {
+                    result.push(' ');
+                }
+            }
         }
 
         result.push('{');
@@ -649,7 +658,7 @@ pub fn format_impl(
         let open_pos = snippet.find_uncommented("{")? + 1;
 
         if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
-            let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config);
+            let mut visitor = FmtVisitor::from_context(context);
             visitor.block_indent = offset.block_only().block_indent(context.config);
             visitor.last_pos = item.span.lo() + BytePos(open_pos as u32);
 
@@ -670,7 +679,7 @@ pub fn format_impl(
             result.push_str(&outer_indent_str);
         }
 
-        if result.chars().last().unwrap() == '{' {
+        if result.ends_with('{') {
             result.push_str(&sep);
         }
         result.push('}');
@@ -692,7 +701,7 @@ fn is_impl_single_line(
     let open_pos = snippet.find_uncommented("{")? + 1;
 
     Some(
-        context.config.impl_empty_single_line() && items.is_empty() && !result.contains('\n')
+        context.config.empty_item_single_line() && items.is_empty() && !result.contains('\n')
             && result.len() + where_clause_str.len() <= context.config.max_width()
             && !contains_comment(&snippet[open_pos..]),
     )
@@ -775,7 +784,7 @@ fn format_impl_ref_and_type(
         let curly_brace_overhead = if generics.where_clause.predicates.is_empty() {
             // If there is no where clause adapt budget for type formatting to take space and curly
             // brace into account.
-            match context.config.item_brace_style() {
+            match context.config.brace_style() {
                 BraceStyle::AlwaysNextLine => 0,
                 _ => 2,
             }
@@ -806,12 +815,11 @@ fn format_impl_ref_and_type(
             result.push_str("for ");
         }
         let budget = context.budget(last_line_width(&result));
-        let type_offset = match context.config.where_style() {
-            Style::Legacy => new_line_offset + trait_ref_overhead,
-            Style::Rfc => new_line_offset,
+        let type_offset = match context.config.indent_style() {
+            IndentStyle::Visual => new_line_offset + trait_ref_overhead,
+            IndentStyle::Block => new_line_offset,
         };
-        result.push_str(&*self_ty
-            .rewrite(context, Shape::legacy(budget, type_offset))?);
+        result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?);
         Some(result)
     } else {
         unreachable!();
@@ -834,9 +842,7 @@ fn rewrite_trait_ref(
         if !(retry && trait_ref_str.contains('\n')) {
             return Some(format!(
                 "{} {}{}",
-                generics_str,
-                polarity_str,
-                &trait_ref_str
+                generics_str, polarity_str, &trait_ref_str
             ));
         }
     }
@@ -857,40 +863,62 @@ fn rewrite_trait_ref(
     }
 }
 
-pub fn format_struct(
-    context: &RewriteContext,
-    item_name: &str,
+pub struct StructParts<'a> {
+    prefix: &'a str,
     ident: ast::Ident,
-    vis: &ast::Visibility,
-    struct_def: &ast::VariantData,
-    generics: Option<&ast::Generics>,
+    vis: &'a ast::Visibility,
+    def: &'a ast::VariantData,
+    generics: Option<&'a ast::Generics>,
     span: Span,
+}
+
+impl<'a> StructParts<'a> {
+    fn format_header(&self) -> String {
+        format_header(self.prefix, self.ident, self.vis)
+    }
+
+    fn from_variant(variant: &'a ast::Variant) -> Self {
+        StructParts {
+            prefix: "",
+            ident: variant.node.name,
+            vis: &ast::Visibility::Inherited,
+            def: &variant.node.data,
+            generics: None,
+            span: variant.span,
+        }
+    }
+
+    pub fn from_item(item: &'a ast::Item) -> Self {
+        let (prefix, def, generics) = match item.node {
+            ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics),
+            ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics),
+            _ => unreachable!(),
+        };
+        StructParts {
+            prefix: prefix,
+            ident: item.ident,
+            vis: &item.vis,
+            def: def,
+            generics: Some(generics),
+            span: item.span,
+        }
+    }
+}
+
+fn format_struct(
+    context: &RewriteContext,
+    struct_parts: &StructParts,
     offset: Indent,
     one_line_width: Option<usize>,
 ) -> Option<String> {
-    match *struct_def {
-        ast::VariantData::Unit(..) => Some(format_unit_struct(item_name, ident, vis)),
-        ast::VariantData::Tuple(ref fields, _) => format_tuple_struct(
-            context,
-            item_name,
-            ident,
-            vis,
-            fields,
-            generics,
-            span,
-            offset,
-        ),
-        ast::VariantData::Struct(ref fields, _) => format_struct_struct(
-            context,
-            item_name,
-            ident,
-            vis,
-            fields,
-            generics,
-            span,
-            offset,
-            one_line_width,
-        ),
+    match *struct_parts.def {
+        ast::VariantData::Unit(..) => format_unit_struct(context, struct_parts, offset),
+        ast::VariantData::Tuple(ref fields, _) => {
+            format_tuple_struct(context, struct_parts, fields, offset)
+        }
+        ast::VariantData::Struct(ref fields, _) => {
+            format_struct_struct(context, struct_parts, fields, offset, one_line_width)
+        }
     }
 }
 
@@ -910,11 +938,22 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
 
         let body_lo = context.codemap.span_after(item.span, "{");
 
-        let shape = Shape::indented(offset + last_line_width(&result), context.config);
+        let shape = Shape::indented(offset, context.config);
         let generics_str =
             rewrite_generics(context, generics, shape, mk_sp(item.span.lo(), body_lo))?;
         result.push_str(&generics_str);
 
+        // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
+        if !type_param_bounds.is_empty() {
+            let ident_hi = context
+                .codemap
+                .span_after(item.span, &format!("{}", item.ident));
+            let bound_hi = type_param_bounds.last().unwrap().span().hi();
+            let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
+            if contains_comment(snippet) {
+                return None;
+            }
+        }
         let trait_bound_str = rewrite_trait_bounds(
             context,
             type_param_bounds,
@@ -931,18 +970,12 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
         }
         result.push_str(&trait_bound_str);
 
-        let has_body = !trait_items.is_empty();
-
-        let where_density = if (context.config.where_density() == Density::Compressed
-            && (!result.contains('\n') || context.config.fn_args_indent() == IndentStyle::Block))
-            || (context.config.fn_args_indent() == IndentStyle::Block && result.is_empty())
-            || (context.config.where_density() == Density::CompressedIfEmpty && !has_body
-                && !result.contains('\n'))
-        {
-            Density::Compressed
-        } else {
-            Density::Tall
-        };
+        let where_density =
+            if context.config.indent_style() == IndentStyle::Block && result.is_empty() {
+                Density::Compressed
+            } else {
+                Density::Tall
+            };
 
         let where_budget = context.budget(last_line_width(&result));
         let pos_before_where = if type_param_bounds.is_empty() {
@@ -954,7 +987,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
         let where_clause_str = rewrite_where_clause(
             context,
             &generics.where_clause,
-            context.config.item_brace_style(),
+            context.config.brace_style(),
             Shape::legacy(where_budget, offset.block_only()),
             where_density,
             "{",
@@ -998,7 +1031,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
             }
         }
 
-        match context.config.item_brace_style() {
+        match context.config.brace_style() {
             _ if last_line_contains_single_line_comment(&result) => {
                 result.push('\n');
                 result.push_str(&offset.to_string(context.config));
@@ -1008,14 +1041,16 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
                 result.push_str(&offset.to_string(context.config));
             }
             BraceStyle::PreferSameLine => result.push(' '),
-            BraceStyle::SameLineWhere => if !where_clause_str.is_empty()
-                && (!trait_items.is_empty() || result.contains('\n'))
-            {
-                result.push('\n');
-                result.push_str(&offset.to_string(context.config));
-            } else {
-                result.push(' ');
-            },
+            BraceStyle::SameLineWhere => {
+                if !where_clause_str.is_empty()
+                    && (!trait_items.is_empty() || result.contains('\n'))
+                {
+                    result.push('\n');
+                    result.push_str(&offset.to_string(context.config));
+                } else {
+                    result.push(' ');
+                }
+            }
         }
         result.push('{');
 
@@ -1023,7 +1058,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
         let open_pos = snippet.find_uncommented("{")? + 1;
 
         if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) {
-            let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config);
+            let mut visitor = FmtVisitor::from_context(context);
             visitor.block_indent = offset.block_only().block_indent(context.config);
             visitor.last_pos = item.span.lo() + BytePos(open_pos as u32);
 
@@ -1052,37 +1087,55 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
     }
 }
 
-fn format_unit_struct(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String {
-    format!("{};", format_header(item_name, ident, vis))
+fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) -> Option<String> {
+    let header_str = format_header(p.prefix, p.ident, p.vis);
+    let generics_str = if let Some(generics) = p.generics {
+        let hi = if generics.where_clause.predicates.is_empty() {
+            generics.span.hi()
+        } else {
+            generics.where_clause.span.hi()
+        };
+        format_generics(
+            context,
+            generics,
+            context.config.brace_style(),
+            BracePos::None,
+            offset,
+            mk_sp(generics.span.lo(), hi),
+            last_line_width(&header_str),
+        )?
+    } else {
+        String::new()
+    };
+    Some(format!("{}{};", header_str, generics_str))
 }
 
 pub fn format_struct_struct(
     context: &RewriteContext,
-    item_name: &str,
-    ident: ast::Ident,
-    vis: &ast::Visibility,
+    struct_parts: &StructParts,
     fields: &[ast::StructField],
-    generics: Option<&ast::Generics>,
-    span: Span,
     offset: Indent,
     one_line_width: Option<usize>,
 ) -> Option<String> {
     let mut result = String::with_capacity(1024);
+    let span = struct_parts.span;
 
-    let header_str = format_header(item_name, ident, vis);
+    let header_str = struct_parts.format_header();
     result.push_str(&header_str);
 
     let header_hi = span.lo() + BytePos(header_str.len() as u32);
     let body_lo = context.codemap.span_after(span, "{");
 
-    let generics_str = match generics {
+    let generics_str = match struct_parts.generics {
         Some(g) => format_generics(
             context,
             g,
-            "{",
-            "{",
-            context.config.item_brace_style(),
-            fields.is_empty(),
+            context.config.brace_style(),
+            if fields.is_empty() {
+                BracePos::ForceSameLine
+            } else {
+                BracePos::Auto
+            },
             offset,
             mk_sp(header_hi, body_lo),
             last_line_width(&result),
@@ -1090,8 +1143,7 @@ pub fn format_struct_struct(
         None => {
             // 3 = ` {}`, 2 = ` {`.
             let overhead = if fields.is_empty() { 3 } else { 2 };
-            if (context.config.item_brace_style() == BraceStyle::AlwaysNextLine
-                && !fields.is_empty())
+            if (context.config.brace_style() == BraceStyle::AlwaysNextLine && !fields.is_empty())
                 || context.config.max_width() < overhead + result.len()
             {
                 format!("\n{}{{", offset.block_only().to_string(context.config))
@@ -1123,7 +1175,7 @@ pub fn format_struct_struct(
             result.push('\n');
             result.push_str(&offset.to_string(context.config));
         } else {
-            result.push_str(&snippet);
+            result.push_str(snippet);
         }
         result.push('}');
         return Some(result);
@@ -1137,7 +1189,7 @@ pub fn format_struct_struct(
     let items_str = rewrite_with_alignment(
         fields,
         context,
-        Shape::indented(offset, context.config),
+        Shape::indented(offset, context.config).sub_width(1)?,
         mk_sp(body_lo, span.hi()),
         one_line_budget,
     )?;
@@ -1178,21 +1230,18 @@ fn get_bytepos_after_visibility(
 
 fn format_tuple_struct(
     context: &RewriteContext,
-    item_name: &str,
-    ident: ast::Ident,
-    vis: &ast::Visibility,
+    struct_parts: &StructParts,
     fields: &[ast::StructField],
-    generics: Option<&ast::Generics>,
-    span: Span,
     offset: Indent,
 ) -> Option<String> {
     let mut result = String::with_capacity(1024);
+    let span = struct_parts.span;
 
-    let header_str = format_header(item_name, ident, vis);
+    let header_str = struct_parts.format_header();
     result.push_str(&header_str);
 
     let body_lo = if fields.is_empty() {
-        let lo = get_bytepos_after_visibility(context, vis, span, ")");
+        let lo = get_bytepos_after_visibility(context, struct_parts.vis, span, ")");
         context.codemap.span_after(mk_sp(lo, span.hi()), "(")
     } else {
         fields[0].span.lo()
@@ -1211,7 +1260,7 @@ fn format_tuple_struct(
         }
     };
 
-    let where_clause_str = match generics {
+    let where_clause_str = match struct_parts.generics {
         Some(generics) => {
             let budget = context.budget(last_line_width(&header_str));
             let shape = Shape::legacy(budget, offset);
@@ -1224,7 +1273,7 @@ fn format_tuple_struct(
             rewrite_where_clause(
                 context,
                 &generics.where_clause,
-                context.config.item_brace_style(),
+                context.config.brace_style(),
                 Shape::legacy(where_budget, offset.block_only()),
                 Density::Compressed,
                 ";",
@@ -1258,21 +1307,14 @@ fn format_tuple_struct(
             result.push('\n');
             result.push_str(&offset.to_string(context.config));
         } else {
-            result.push_str(&snippet);
+            result.push_str(snippet);
         }
         result.push(')');
     } else {
-        // 1 = ","
-        let body = rewrite_call_inner(
-            context,
-            "",
-            &fields.iter().map(|field| field).collect::<Vec<_>>()[..],
-            span,
-            Shape::indented(offset, context.config).sub_width(1)?,
-            context.config.fn_call_width(),
-            false,
-        )?;
-        result.push_str(&body);
+        let shape = Shape::indented(offset, context.config).sub_width(1)?;
+        let fields = &fields.iter().collect::<Vec<_>>()[..];
+        let one_line_width = context.config.width_heuristics().fn_call_width;
+        result = rewrite_call_inner(context, &result, fields, span, shape, one_line_width, false)?;
     }
 
     if !where_clause_str.is_empty() && !where_clause_str.contains('\n')
@@ -1317,9 +1359,9 @@ pub fn rewrite_type_alias(
     let where_clause_str = rewrite_where_clause(
         context,
         &generics.where_clause,
-        context.config.item_brace_style(),
+        context.config.brace_style(),
         Shape::legacy(where_budget, indent),
-        context.config.where_density(),
+        Density::Vertical,
         "=",
         Some(span.hi()),
         generics.span.hi(),
@@ -1358,16 +1400,8 @@ pub fn rewrite_type_alias(
 
 fn type_annotation_spacing(config: &Config) -> (&str, &str) {
     (
-        if config.space_before_type_annotation() {
-            " "
-        } else {
-            ""
-        },
-        if config.space_after_type_annotation_colon() {
-            " "
-        } else {
-            ""
-        },
+        if config.space_before_colon() { " " } else { "" },
+        if config.space_after_colon() { " " } else { "" },
     )
 }
 
@@ -1396,7 +1430,8 @@ pub fn rewrite_struct_field(
     lhs_max_width: usize,
 ) -> Option<String> {
     if contains_skip(&field.attrs) {
-        return Some(context.snippet(mk_sp(field.attrs[0].span.lo(), field.span.hi())));
+        let snippet = context.snippet(mk_sp(field.attrs[0].span.lo(), field.span.hi()));
+        return Some(snippet.to_owned());
     }
 
     let type_annotation_spacing = type_annotation_spacing(context.config);
@@ -1404,8 +1439,7 @@ pub fn rewrite_struct_field(
 
     let attrs_str = field.attrs.rewrite(context, shape)?;
     let attrs_extendable = attrs_str.is_empty()
-        || (context.config.attributes_on_same_line_as_field()
-            && is_attributes_extendable(&attrs_str));
+        || (context.config.same_line_attributes() && is_attributes_extendable(&attrs_str));
     let missing_span = if field.attrs.is_empty() {
         mk_sp(field.span.lo(), field.span.lo())
     } else {
@@ -1435,75 +1469,125 @@ pub fn rewrite_struct_field(
         spacing.push(' ');
     }
     let ty_shape = shape.offset_left(overhead + spacing.len())?;
-    if let Some(ref ty) = field.ty.rewrite(context, ty_shape) {
+    let mut orig_ty = field.ty.rewrite(context, ty_shape);
+    if let Some(ref ty) = orig_ty {
         if !ty.contains('\n') {
             return Some(attr_prefix + &spacing + ty);
         }
     }
 
-    // We must use multiline.
-    let new_shape = shape.with_max_width(context.config);
-    let ty_rewritten = field.ty.rewrite(context, new_shape)?;
-
+    // We must use multiline. We are going to put attributes and a field on different lines.
+    // 1 = " "
+    let rhs_shape = shape.offset_left(last_line_width(&prefix) + 1)?;
+    orig_ty = field.ty.rewrite(context, rhs_shape);
     let field_str = if prefix.is_empty() {
-        ty_rewritten
-    } else if prefix.len() + first_line_width(&ty_rewritten) + 1 <= shape.width {
-        prefix + " " + &ty_rewritten
+        orig_ty?
     } else {
-        let type_offset = shape.indent.block_indent(context.config);
-        let nested_shape = Shape::indented(type_offset, context.config);
-        let nested_ty = field.ty.rewrite(context, nested_shape)?;
-        prefix + "\n" + &type_offset.to_string(context.config) + &nested_ty
+        prefix + &choose_rhs(context, &*field.ty, rhs_shape, orig_ty)?
     };
-    combine_strs_with_missing_comments(
-        context,
-        &attrs_str,
-        &field_str,
-        missing_span,
-        shape,
-        attrs_extendable,
-    )
+    combine_strs_with_missing_comments(context, &attrs_str, &field_str, missing_span, shape, false)
 }
 
-pub fn rewrite_static(
-    prefix: &str,
-    vis: &ast::Visibility,
+pub struct StaticParts<'a> {
+    prefix: &'a str,
+    vis: &'a ast::Visibility,
     ident: ast::Ident,
-    ty: &ast::Ty,
+    ty: &'a ast::Ty,
     mutability: ast::Mutability,
-    expr_opt: Option<&ptr::P<ast::Expr>>,
-    offset: Indent,
+    expr_opt: Option<&'a ptr::P<ast::Expr>>,
+    defaultness: Option<ast::Defaultness>,
     span: Span,
+}
+
+impl<'a> StaticParts<'a> {
+    pub fn from_item(item: &'a ast::Item) -> Self {
+        let (prefix, ty, mutability, expr) = match item.node {
+            ast::ItemKind::Static(ref ty, mutability, ref expr) => ("static", ty, mutability, expr),
+            ast::ItemKind::Const(ref ty, ref expr) => {
+                ("const", ty, ast::Mutability::Immutable, expr)
+            }
+            _ => unreachable!(),
+        };
+        StaticParts {
+            prefix: prefix,
+            vis: &item.vis,
+            ident: item.ident,
+            ty: ty,
+            mutability: mutability,
+            expr_opt: Some(expr),
+            defaultness: None,
+            span: item.span,
+        }
+    }
+
+    pub fn from_trait_item(ti: &'a ast::TraitItem) -> Self {
+        let (ty, expr_opt) = match ti.node {
+            ast::TraitItemKind::Const(ref ty, ref expr_opt) => (ty, expr_opt),
+            _ => unreachable!(),
+        };
+        StaticParts {
+            prefix: "const",
+            vis: &ast::Visibility::Inherited,
+            ident: ti.ident,
+            ty: ty,
+            mutability: ast::Mutability::Immutable,
+            expr_opt: expr_opt.as_ref(),
+            defaultness: None,
+            span: ti.span,
+        }
+    }
+
+    pub fn from_impl_item(ii: &'a ast::ImplItem) -> Self {
+        let (ty, expr) = match ii.node {
+            ast::ImplItemKind::Const(ref ty, ref expr) => (ty, expr),
+            _ => unreachable!(),
+        };
+        StaticParts {
+            prefix: "const",
+            vis: &ii.vis,
+            ident: ii.ident,
+            ty: ty,
+            mutability: ast::Mutability::Immutable,
+            expr_opt: Some(expr),
+            defaultness: Some(ii.defaultness),
+            span: ii.span,
+        }
+    }
+}
+
+fn rewrite_static(
     context: &RewriteContext,
+    static_parts: &StaticParts,
+    offset: Indent,
 ) -> Option<String> {
     let colon = colon_spaces(
-        context.config.space_before_type_annotation(),
-        context.config.space_after_type_annotation_colon(),
+        context.config.space_before_colon(),
+        context.config.space_after_colon(),
     );
     let prefix = format!(
-        "{}{} {}{}{}",
-        format_visibility(vis),
-        prefix,
-        format_mutability(mutability),
-        ident,
+        "{}{}{} {}{}{}",
+        format_visibility(static_parts.vis),
+        static_parts.defaultness.map_or("", format_defaultness),
+        static_parts.prefix,
+        format_mutability(static_parts.mutability),
+        static_parts.ident,
         colon,
     );
     // 2 = " =".len()
-    let ty_str = ty.rewrite(
-        context,
-        Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2)?,
-    )?;
+    let ty_shape =
+        Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2)?;
+    let ty_str = static_parts.ty.rewrite(context, ty_shape)?;
 
-    if let Some(expr) = expr_opt {
+    if let Some(expr) = static_parts.expr_opt {
         let lhs = format!("{}{} =", prefix, ty_str);
         // 1 = ;
         let remaining_width = context.budget(offset.block_indent + 1);
         rewrite_assign_rhs(
             context,
             lhs,
-            expr,
+            &**expr,
             Shape::legacy(remaining_width, offset.block_only()),
-        ).and_then(|res| recover_comment_removed(res, span, context))
+        ).and_then(|res| recover_comment_removed(res, static_parts.span, context))
             .map(|s| if s.ends_with(';') { s } else { s + ";" })
     } else {
         Some(format!("{}{};", prefix, ty_str))
@@ -1519,10 +1603,9 @@ pub fn rewrite_associated_type(
 ) -> Option<String> {
     let prefix = format!("type {}", ident);
 
-    let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt {
+    let type_bounds_str = if let Some(bounds) = ty_param_bounds_opt {
         // 2 = ": ".len()
         let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?;
-        let bounds: &[_] = ty_param_bounds;
         let bound_str = bounds
             .iter()
             .map(|ty_bound| ty_bound.rewrite(context, shape))
@@ -1537,14 +1620,10 @@ pub fn rewrite_associated_type(
     };
 
     if let Some(ty) = ty_opt {
-        let ty_str = ty.rewrite(
-            context,
-            Shape::legacy(
-                context.budget(indent.block_indent + prefix.len() + 2),
-                indent.block_only(),
-            ),
-        )?;
-        Some(format!("{}{} = {};", prefix, type_bounds_str, ty_str))
+        // 1 = `;`
+        let shape = Shape::indented(indent, context.config).sub_width(1)?;
+        let lhs = format!("{}{} =", prefix, type_bounds_str);
+        rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";")
     } else {
         Some(format!("{}{};", prefix, type_bounds_str))
     }
@@ -1596,11 +1675,11 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
                 .rewrite(context, Shape::legacy(shape.width, shape.indent))?;
 
             if !is_empty_infer(context, &*self.ty) {
-                if context.config.space_before_type_annotation() {
+                if context.config.space_before_colon() {
                     result.push_str(" ");
                 }
                 result.push_str(":");
-                if context.config.space_after_type_annotation_colon() {
+                if context.config.space_after_colon() {
                     result.push_str(" ");
                 }
                 let overhead = last_line_width(&result);
@@ -1762,25 +1841,16 @@ fn rewrite_fn_base(
 
     debug!(
         "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}",
-        one_line_budget,
-        multi_line_budget,
-        arg_indent
+        one_line_budget, multi_line_budget, arg_indent
     );
 
     // Check if vertical layout was forced.
     if one_line_budget == 0 {
         if snuggle_angle_bracket {
             result.push('(');
-        } else if context.config.fn_args_paren_newline() {
-            result.push('\n');
-            result.push_str(&arg_indent.to_string(context.config));
-            if context.config.fn_args_indent() == IndentStyle::Visual {
-                arg_indent = arg_indent + 1; // extra space for `(`
-            }
-            result.push('(');
         } else {
             result.push_str("(");
-            if context.config.fn_args_indent() == IndentStyle::Visual {
+            if context.config.indent_style() == IndentStyle::Visual {
                 result.push('\n');
                 result.push_str(&arg_indent.to_string(context.config));
             }
@@ -1788,7 +1858,9 @@ fn rewrite_fn_base(
     } else {
         result.push('(');
     }
-    if context.config.spaces_within_parens() && !fd.inputs.is_empty() && result.ends_with('(') {
+    if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty()
+        && result.ends_with('(')
+    {
         result.push(' ')
     }
 
@@ -1827,7 +1899,7 @@ fn rewrite_fn_base(
         generics_str.contains('\n'),
     )?;
 
-    let put_args_in_block = match context.config.fn_args_indent() {
+    let put_args_in_block = match context.config.indent_style() {
         IndentStyle::Block => arg_str.contains('\n') || arg_str.len() > one_line_budget,
         _ => false,
     } && !fd.inputs.is_empty();
@@ -1849,7 +1921,7 @@ fn rewrite_fn_base(
         if fd.inputs.is_empty() && used_width + 1 > context.config.max_width() {
             result.push('\n');
         }
-        if context.config.spaces_within_parens() && !fd.inputs.is_empty() {
+        if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() {
             result.push(' ')
         }
         // If the last line of args contains comment, we cannot put the closing paren
@@ -1868,7 +1940,7 @@ fn rewrite_fn_base(
 
     // Return type.
     if let ast::FunctionRetTy::Ty(..) = fd.output {
-        let ret_should_indent = match context.config.fn_args_indent() {
+        let ret_should_indent = match context.config.indent_style() {
             // If our args are block layout then we surely must have space.
             IndentStyle::Block if put_args_in_block || fd.inputs.is_empty() => false,
             _ if args_last_line_contains_comment => false,
@@ -1889,17 +1961,15 @@ fn rewrite_fn_base(
             }
         };
         let ret_indent = if ret_should_indent {
-            let indent = match context.config.fn_return_indent() {
-                ReturnIndent::WithWhereClause => indent + 4,
+            let indent = if arg_str.is_empty() {
                 // Aligning with non-existent args looks silly.
-                _ if arg_str.is_empty() => {
-                    force_new_line_for_brace = true;
-                    indent + 4
-                }
+                force_new_line_for_brace = true;
+                indent + 4
+            } else {
                 // FIXME: we might want to check that using the arg indent
                 // doesn't blow our budget, and if it does, then fallback to
                 // the where clause indent.
-                _ => arg_indent,
+                arg_indent
             };
 
             result.push('\n');
@@ -1947,12 +2017,6 @@ fn rewrite_fn_base(
         }
     }
 
-    let should_compress_where = match context.config.where_density() {
-        Density::Compressed => !result.contains('\n'),
-        Density::CompressedIfEmpty => !has_body && !result.contains('\n'),
-        _ => false,
-    };
-
     let pos_before_where = match fd.output {
         ast::FunctionRetTy::Default(..) => args_span.hi(),
         ast::FunctionRetTy::Ty(ref ty) => ty.span.hi(),
@@ -1960,31 +2024,11 @@ fn rewrite_fn_base(
 
     let is_args_multi_lined = arg_str.contains('\n');
 
-    if where_clause.predicates.len() == 1 && should_compress_where {
-        let budget = context.budget(last_line_used_width(&result, indent.width()));
-        if let Some(where_clause_str) = rewrite_where_clause(
-            context,
-            where_clause,
-            context.config.fn_brace_style(),
-            Shape::legacy(budget, indent),
-            Density::Compressed,
-            "{",
-            Some(span.hi()),
-            pos_before_where,
-            WhereClauseOption::compressed(),
-            is_args_multi_lined,
-        ) {
-            result.push_str(&where_clause_str);
-            force_new_line_for_brace |= last_line_contains_single_line_comment(&result);
-            return Some((result, force_new_line_for_brace));
-        }
-    }
-
     let option = WhereClauseOption::new(!has_body, put_args_in_block && ret_str.is_empty());
     let where_clause_str = rewrite_where_clause(
         context,
         where_clause,
-        context.config.fn_brace_style(),
+        context.config.brace_style(),
         Shape::indented(indent, context.config),
         Density::Tall,
         "{",
@@ -2035,14 +2079,6 @@ pub fn new(suppress_comma: bool, snuggle: bool) -> WhereClauseOption {
         }
     }
 
-    pub fn compressed() -> WhereClauseOption {
-        WhereClauseOption {
-            suppress_comma: true,
-            snuggle: false,
-            compress_where: true,
-        }
-    }
-
     pub fn snuggled(current: &str) -> WhereClauseOption {
         WhereClauseOption {
             suppress_comma: false,
@@ -2072,9 +2108,7 @@ fn rewrite_args(
     // FIXME: the comment for the self argument is dropped. This is blocked
     // on rust issue #27522.
     let min_args = explicit_self
-        .and_then(|explicit_self| {
-            rewrite_explicit_self(explicit_self, args, context)
-        })
+        .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context))
         .map_or(1, |self_str| {
             arg_item_strs[0] = self_str;
             2
@@ -2124,6 +2158,7 @@ enum ArgumentKind<'a> {
                 .map(ArgumentKind::Regular)
                 .chain(variadic_arg),
             ")",
+            ",",
             |arg| match *arg {
                 ArgumentKind::Regular(arg) => span_lo_for_arg(arg),
                 ArgumentKind::Variadic(start) => start,
@@ -2158,7 +2193,7 @@ enum ArgumentKind<'a> {
         .and_then(|item| item.post_comment.as_ref())
         .map_or(false, |s| s.trim().starts_with("//"));
 
-    let (indent, trailing_comma) = match context.config.fn_args_indent() {
+    let (indent, trailing_comma) = match context.config.indent_style() {
         IndentStyle::Block if fits_in_one_line => {
             (indent.block_indent(context.config), SeparatorTactic::Never)
         }
@@ -2195,7 +2230,7 @@ enum ArgumentKind<'a> {
         },
         separator_place: SeparatorPlace::Back,
         shape: Shape::legacy(budget, indent),
-        ends_with_newline: tactic.ends_with_newline(context.config.fn_args_indent()),
+        ends_with_newline: tactic.ends_with_newline(context.config.indent_style()),
         preserve_newline: true,
         config: context.config,
     };
@@ -2245,7 +2280,7 @@ fn compute_budgets_for_args(
 
         if one_line_budget > 0 {
             // 4 = "() {".len()
-            let (indent, multi_line_budget) = match context.config.fn_args_indent() {
+            let (indent, multi_line_budget) = match context.config.indent_style() {
                 IndentStyle::Block => {
                     let indent = indent.block_indent(context.config);
                     (indent, context.budget(indent.width() + 1))
@@ -2263,7 +2298,7 @@ fn compute_budgets_for_args(
 
     // Didn't work. we must force vertical layout and put args on a newline.
     let new_indent = indent.block_indent(context.config);
-    let used_space = match context.config.fn_args_indent() {
+    let used_space = match context.config.indent_style() {
         // 1 = `,`
         IndentStyle::Block => new_indent.width() + 1,
         // Account for `)` and possibly ` {`.
@@ -2272,19 +2307,16 @@ fn compute_budgets_for_args(
     Some((0, context.budget(used_space), new_indent))
 }
 
-fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause, has_body: bool) -> bool {
+fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool {
     let predicate_count = where_clause.predicates.len();
 
     if config.where_single_line() && predicate_count == 1 {
         return false;
     }
-    match (config.fn_brace_style(), config.where_density()) {
-        (BraceStyle::AlwaysNextLine, _) => true,
-        (_, Density::Compressed) if predicate_count == 1 => false,
-        (_, Density::CompressedIfEmpty) if predicate_count == 1 && !has_body => false,
-        (BraceStyle::SameLineWhere, _) if predicate_count > 0 => true,
-        _ => false,
-    }
+    let brace_style = config.brace_style();
+
+    brace_style == BraceStyle::AlwaysNextLine
+        || (brace_style == BraceStyle::SameLineWhere && predicate_count > 0)
 }
 
 fn rewrite_generics(
@@ -2295,9 +2327,8 @@ fn rewrite_generics(
 ) -> Option<String> {
     let g_shape = generics_shape_from_config(context.config, shape, 0)?;
     let one_line_width = shape.width.checked_sub(2).unwrap_or(0);
-    rewrite_generics_inner(context, generics, g_shape, one_line_width, span).or_else(|| {
-        rewrite_generics_inner(context, generics, g_shape, 0, span)
-    })
+    rewrite_generics_inner(context, generics, g_shape, one_line_width, span)
+        .or_else(|| rewrite_generics_inner(context, generics, g_shape, 0, span))
 }
 
 fn rewrite_generics_inner(
@@ -2318,16 +2349,16 @@ enum GenericsArg<'a> {
     impl<'a> Rewrite for GenericsArg<'a> {
         fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
             match *self {
-                GenericsArg::Lifetime(ref lifetime) => lifetime.rewrite(context, shape),
-                GenericsArg::TyParam(ref ty) => ty.rewrite(context, shape),
+                GenericsArg::Lifetime(lifetime) => lifetime.rewrite(context, shape),
+                GenericsArg::TyParam(ty) => ty.rewrite(context, shape),
             }
         }
     }
     impl<'a> Spanned for GenericsArg<'a> {
         fn span(&self) -> Span {
             match *self {
-                GenericsArg::Lifetime(ref lifetime) => lifetime.span(),
-                GenericsArg::TyParam(ref ty) => ty.span(),
+                GenericsArg::Lifetime(lifetime) => lifetime.span(),
+                GenericsArg::TyParam(ty) => ty.span(),
             }
         }
     }
@@ -2345,6 +2376,7 @@ fn span(&self) -> Span {
         context.codemap,
         generics_args,
         ">",
+        ",",
         |arg| arg.span().lo(),
         |arg| arg.span().hi(),
         |arg| arg.rewrite(context, shape),
@@ -2356,7 +2388,7 @@ fn span(&self) -> Span {
 }
 
 pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option<Shape> {
-    match config.generics_indent() {
+    match config.indent_style() {
         IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width(offset + 2),
         IndentStyle::Block => {
             // 1 = ","
@@ -2389,14 +2421,14 @@ pub fn format_generics_item_list<I>(
     let fmt = ListFormatting {
         tactic: tactic,
         separator: ",",
-        trailing_separator: if context.config.generics_indent() == IndentStyle::Visual {
+        trailing_separator: if context.config.indent_style() == IndentStyle::Visual {
             SeparatorTactic::Never
         } else {
             context.config.trailing_comma()
         },
         separator_place: SeparatorPlace::Back,
         shape: shape,
-        ends_with_newline: tactic.ends_with_newline(context.config.generics_indent()),
+        ends_with_newline: tactic.ends_with_newline(context.config.indent_style()),
         preserve_newline: true,
         config: context.config,
     };
@@ -2415,7 +2447,7 @@ pub fn wrap_generics_with_angle_brackets(
     list_str: &str,
     list_offset: Indent,
 ) -> String {
-    if context.config.generics_indent() == IndentStyle::Block
+    if context.config.indent_style() == IndentStyle::Block
         && (list_str.contains('\n') || list_str.ends_with(','))
     {
         format!(
@@ -2426,7 +2458,7 @@ pub fn wrap_generics_with_angle_brackets(
                 .block_unindent(context.config)
                 .to_string(context.config)
         )
-    } else if context.config.spaces_within_angle_brackets() {
+    } else if context.config.spaces_within_parens_and_brackets() {
         format!("< {} >", list_str)
     } else {
         format!("<{}>", list_str)
@@ -2435,11 +2467,9 @@ pub fn wrap_generics_with_angle_brackets(
 
 fn rewrite_trait_bounds(
     context: &RewriteContext,
-    type_param_bounds: &ast::TyParamBounds,
+    bounds: &[ast::TyParamBound],
     shape: Shape,
 ) -> Option<String> {
-    let bounds: &[_] = type_param_bounds;
-
     if bounds.is_empty() {
         return Some(String::new());
     }
@@ -2487,6 +2517,7 @@ fn rewrite_where_clause_rfc_style(
         context.codemap,
         where_clause.predicates.iter(),
         terminator,
+        ",",
         |pred| pred.span().lo(),
         |pred| pred.span().hi(),
         |pred| pred.rewrite(context, clause_shape),
@@ -2521,10 +2552,12 @@ fn rewrite_where_clause_rfc_style(
     };
     let preds_str = write_list(&items.collect::<Vec<_>>(), &fmt)?;
 
-    let comment_separator = |comment: &str, shape: Shape| if comment.is_empty() {
-        String::new()
-    } else {
-        format!("\n{}", shape.indent.to_string(context.config))
+    let comment_separator = |comment: &str, shape: Shape| {
+        if comment.is_empty() {
+            String::new()
+        } else {
+            format!("\n{}", shape.indent.to_string(context.config))
+        }
     };
     let newline_before_where = comment_separator(&comment_before, shape);
     let newline_after_where = comment_separator(&comment_after, clause_shape);
@@ -2566,7 +2599,7 @@ fn rewrite_where_clause(
         return Some(String::new());
     }
 
-    if context.config.where_style() == Style::Rfc {
+    if context.config.indent_style() == IndentStyle::Block {
         return rewrite_where_clause_rfc_style(
             context,
             where_clause,
@@ -2581,12 +2614,12 @@ fn rewrite_where_clause(
 
     let extra_indent = Indent::new(context.config.tab_spaces(), 0);
 
-    let offset = match context.config.where_pred_indent() {
+    let offset = match context.config.indent_style() {
         IndentStyle::Block => shape.indent + extra_indent.block_indent(context.config),
         // 6 = "where ".len()
         IndentStyle::Visual => shape.indent + extra_indent + 6,
     };
-    // FIXME: if where_pred_indent != Visual, then the budgets below might
+    // FIXME: if indent_style != Visual, then the budgets below might
     // be out by a char or two.
 
     let budget = context.config.max_width() - offset.width();
@@ -2600,6 +2633,7 @@ fn rewrite_where_clause(
         context.codemap,
         where_clause.predicates.iter(),
         terminator,
+        ",",
         |pred| pred.span().lo(),
         |pred| pred.span().hi(),
         |pred| pred.rewrite(context, Shape::legacy(budget, offset)),
@@ -2608,14 +2642,8 @@ fn rewrite_where_clause(
         false,
     );
     let item_vec = items.collect::<Vec<_>>();
-    // FIXME: we don't need to collect here if the where_layout isn't
-    // HorizontalVertical.
-    let tactic = definitive_tactic(
-        &item_vec,
-        context.config.where_layout(),
-        Separator::Comma,
-        budget,
-    );
+    // FIXME: we don't need to collect here
+    let tactic = definitive_tactic(&item_vec, ListTactic::Vertical, Separator::Comma, budget);
 
     let mut comma_tactic = context.config.trailing_comma();
     // Kind of a hack because we don't usually have trailing commas in where clauses.
@@ -2629,7 +2657,7 @@ fn rewrite_where_clause(
         trailing_separator: comma_tactic,
         separator_place: SeparatorPlace::Back,
         shape: Shape::legacy(budget, offset),
-        ends_with_newline: tactic.ends_with_newline(context.config.where_pred_indent()),
+        ends_with_newline: tactic.ends_with_newline(context.config.indent_style()),
         preserve_newline: true,
         config: context.config,
     };
@@ -2690,13 +2718,18 @@ fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> S
     format!("{}{}{}", format_visibility(vis), item_name, ident)
 }
 
+#[derive(PartialEq, Eq, Clone, Copy)]
+enum BracePos {
+    None,
+    Auto,
+    ForceSameLine,
+}
+
 fn format_generics(
     context: &RewriteContext,
     generics: &ast::Generics,
-    opener: &str,
-    terminator: &str,
     brace_style: BraceStyle,
-    force_same_line_brace: bool,
+    brace_pos: BracePos,
     offset: Indent,
     span: Span,
     used_width: usize,
@@ -2706,7 +2739,10 @@ fn format_generics(
 
     let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') {
         let budget = context.budget(last_line_used_width(&result, offset.width()));
-        let option = WhereClauseOption::snuggled(&result);
+        let mut option = WhereClauseOption::snuggled(&result);
+        if brace_pos == BracePos::None {
+            option.suppress_comma = true;
+        }
         // If the generics are not parameterized then generics.span.hi() == 0,
         // so we use span.lo(), which is the position after `struct Foo`.
         let span_end_before_where = if generics.is_parameterized() {
@@ -2720,29 +2756,34 @@ fn format_generics(
             brace_style,
             Shape::legacy(budget, offset.block_only()),
             Density::Tall,
-            terminator,
+            "{",
             Some(span.hi()),
             span_end_before_where,
             option,
             false,
         )?;
         result.push_str(&where_clause_str);
-        force_same_line_brace || brace_style == BraceStyle::PreferSameLine
+        brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine
             || (generics.where_clause.predicates.is_empty()
                 && trimmed_last_line_width(&result) == 1)
     } else {
-        force_same_line_brace || trimmed_last_line_width(&result) == 1
+        brace_pos == BracePos::ForceSameLine || trimmed_last_line_width(&result) == 1
             || brace_style != BraceStyle::AlwaysNextLine
     };
+    if brace_pos == BracePos::None {
+        return Some(result);
+    }
     let total_used_width = last_line_used_width(&result, used_width);
     let remaining_budget = context.budget(total_used_width);
     // If the same line brace if forced, it indicates that we are rewriting an item with empty body,
     // and hence we take the closer into account as well for one line budget.
     // We assume that the closer has the same length as the opener.
-    let overhead = if force_same_line_brace {
-        1 + opener.len() + opener.len()
+    let overhead = if brace_pos == BracePos::ForceSameLine {
+        // 3 = ` {}`
+        3
     } else {
-        1 + opener.len()
+        // 2 = ` {`
+        2
     };
     let forbid_same_line_brace = overhead > remaining_budget;
     if !forbid_same_line_brace && same_line_brace {
@@ -2751,7 +2792,7 @@ fn format_generics(
         result.push('\n');
         result.push_str(&offset.block_only().to_string(context.config));
     }
-    result.push_str(opener);
+    result.push('{');
 
     Some(result)
 }
@@ -2764,15 +2805,17 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
         let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1));
 
         let item_str = match self.node {
-            ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => rewrite_fn_base(
-                context,
-                shape.indent,
-                self.ident,
-                &FnSig::new(fn_decl, generics, self.vis.clone()),
-                span,
-                false,
-                false,
-            ).map(|(s, _)| format!("{};", s)),
+            ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => {
+                rewrite_fn_base(
+                    context,
+                    shape.indent,
+                    self.ident,
+                    &FnSig::new(fn_decl, generics, self.vis.clone()),
+                    span,
+                    false,
+                    false,
+                ).map(|(s, _)| format!("{};", s))
+            }
             ast::ForeignItemKind::Static(ref ty, is_mutable) => {
                 // FIXME(#21): we're dropping potential comments in between the
                 // function keywords here.